mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-08-19 12:59:39 -07:00
Added the SickRage API integration
This commit is contained in:
parent
6e04e2effe
commit
f21cd89a74
14 changed files with 295 additions and 3 deletions
17
src/Ombi.Api.SickRage/ISickRageApi.cs
Normal file
17
src/Ombi.Api.SickRage/ISickRageApi.cs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Ombi.Api.SickRage.Models;
|
||||||
|
|
||||||
|
namespace Ombi.Api.SickRage
|
||||||
|
{
|
||||||
|
public interface ISickRageApi
|
||||||
|
{
|
||||||
|
Task<SickRageTvAdd> AddSeason(int tvdbId, int season, string apiKey, string baseUrl);
|
||||||
|
Task<SickRageTvAdd> AddSeries(int tvdbId, int seasonCount, int[] seasons, string quality, string apiKey, string baseUrl);
|
||||||
|
Task<SickRageShows> GetShows(string apiKey, string baseUrl);
|
||||||
|
Task<SickRagePing> Ping(string apiKey, string baseUrl);
|
||||||
|
Task<SickRageSeasonList> VerifyShowHasLoaded(int tvdbId, string apiKey, string baseUrl);
|
||||||
|
|
||||||
|
Task<SickRageEpisodeStatus> SetEpisodeStatus(string apiKey, string baseUrl, int tvdbid, string status,
|
||||||
|
int season, int episode = -1);
|
||||||
|
}
|
||||||
|
}
|
10
src/Ombi.Api.SickRage/Models/SickRageBase.cs
Normal file
10
src/Ombi.Api.SickRage/Models/SickRageBase.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
namespace Ombi.Api.SickRage.Models
|
||||||
|
{
|
||||||
|
public abstract class SickRageBase<T>
|
||||||
|
{
|
||||||
|
public T data { get; set; }
|
||||||
|
public string message { get; set; }
|
||||||
|
public string result { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
src/Ombi.Api.SickRage/Models/SickRageEpisodeStatus.cs
Normal file
18
src/Ombi.Api.SickRage/Models/SickRageEpisodeStatus.cs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
namespace Ombi.Api.SickRage.Models
|
||||||
|
{
|
||||||
|
public class SickRageEpisodeStatus
|
||||||
|
{
|
||||||
|
public Data[] data { get; set; }
|
||||||
|
public string message { get; set; }
|
||||||
|
public string result { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Data
|
||||||
|
{
|
||||||
|
public int episode { get; set; }
|
||||||
|
public string message { get; set; }
|
||||||
|
public string result { get; set; }
|
||||||
|
public int season { get; set; }
|
||||||
|
public string status { get; set; }
|
||||||
|
}
|
||||||
|
}
|
11
src/Ombi.Api.SickRage/Models/SickRagePing.cs
Normal file
11
src/Ombi.Api.SickRage/Models/SickRagePing.cs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
namespace Ombi.Api.SickRage.Models
|
||||||
|
{
|
||||||
|
public class SickRagePingData
|
||||||
|
{
|
||||||
|
public int pid { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SickRagePing : SickRageBase<SickRagePingData>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
11
src/Ombi.Api.SickRage/Models/SickRageSeasonList.cs
Normal file
11
src/Ombi.Api.SickRage/Models/SickRageSeasonList.cs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Ombi.Helpers;
|
||||||
|
|
||||||
|
namespace Ombi.Api.SickRage.Models
|
||||||
|
{
|
||||||
|
public class SickRageSeasonList : SickRageBase<object>
|
||||||
|
{
|
||||||
|
[JsonIgnore]
|
||||||
|
public int[] Data => JsonConvertHelper.ParseObjectToArray<int>(data);
|
||||||
|
}
|
||||||
|
}
|
14
src/Ombi.Api.SickRage/Models/SickRageShows.cs
Normal file
14
src/Ombi.Api.SickRage/Models/SickRageShows.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Ombi.Api.SickRage.Models
|
||||||
|
{
|
||||||
|
public class SickRageShows : SickRageBase<Dictionary<int, Item>>
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Item
|
||||||
|
{
|
||||||
|
public int tvdbid { get; set; }
|
||||||
|
}
|
||||||
|
}
|
9
src/Ombi.Api.SickRage/Models/SickRageStatus.cs
Normal file
9
src/Ombi.Api.SickRage/Models/SickRageStatus.cs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
namespace Ombi.Api.SickRage.Models
|
||||||
|
{
|
||||||
|
public static class SickRageStatus
|
||||||
|
{
|
||||||
|
public const string Wanted = "wanted";
|
||||||
|
public const string Skipped = "skipped";
|
||||||
|
public const string Ignored = "Ignored";
|
||||||
|
}
|
||||||
|
}
|
11
src/Ombi.Api.SickRage/Models/SickRageTvAdd.cs
Normal file
11
src/Ombi.Api.SickRage/Models/SickRageTvAdd.cs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
namespace Ombi.Api.SickRage.Models
|
||||||
|
{
|
||||||
|
public class SickRageTvAddData
|
||||||
|
{
|
||||||
|
public string name { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SickRageTvAdd : SickRageBase<SickRageTvAddData>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
11
src/Ombi.Api.SickRage/Ombi.Api.SickRage.csproj
Normal file
11
src/Ombi.Api.SickRage/Ombi.Api.SickRage.csproj
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Ombi.Api\Ombi.Api.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
143
src/Ombi.Api.SickRage/SickRageApi.cs
Normal file
143
src/Ombi.Api.SickRage/SickRageApi.cs
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Ombi.Api.SickRage.Models;
|
||||||
|
|
||||||
|
namespace Ombi.Api.SickRage
|
||||||
|
{
|
||||||
|
public class SickRageApi : ISickRageApi
|
||||||
|
{
|
||||||
|
public SickRageApi(IApi api, ILogger<SickRageApi> log)
|
||||||
|
{
|
||||||
|
_api = api;
|
||||||
|
_log = log;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly IApi _api;
|
||||||
|
private readonly ILogger<SickRageApi> _log;
|
||||||
|
|
||||||
|
public async Task<SickRageSeasonList> VerifyShowHasLoaded(int tvdbId, string apiKey, string baseUrl)
|
||||||
|
{
|
||||||
|
var request = new Request($"/api/{apiKey}/?cmd=show.seasonlist", baseUrl, HttpMethod.Get);
|
||||||
|
request.AddQueryString("tvdbid", tvdbId.ToString());
|
||||||
|
|
||||||
|
return await _api.Request<SickRageSeasonList>(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<SickRageTvAdd> AddSeries(int tvdbId, int seasonCount, int[] seasons, string quality, string apiKey, string baseUrl)
|
||||||
|
{
|
||||||
|
var futureStatus = seasons.Length > 0 && seasons.All(x => x != seasonCount) ? SickRageStatus.Skipped : SickRageStatus.Wanted;
|
||||||
|
var status = seasons.Length > 0 ? SickRageStatus.Skipped : SickRageStatus.Wanted;
|
||||||
|
var request = new Request($"/api/{apiKey}/?cmd=show.addnew", baseUrl, HttpMethod.Get);
|
||||||
|
|
||||||
|
request.AddQueryString("tvdbid", tvdbId.ToString());
|
||||||
|
request.AddQueryString("status", status);
|
||||||
|
request.AddQueryString("future_status", futureStatus);
|
||||||
|
|
||||||
|
if (!quality.Equals("default", StringComparison.CurrentCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
request.AddQueryString("initial", quality);
|
||||||
|
}
|
||||||
|
|
||||||
|
var obj = await _api.Request<SickRageTvAdd>(request);
|
||||||
|
|
||||||
|
if (obj.result != "failure")
|
||||||
|
{
|
||||||
|
var sw = new Stopwatch();
|
||||||
|
sw.Start();
|
||||||
|
|
||||||
|
var seasonIncrement = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (seasonIncrement < seasonCount)
|
||||||
|
{
|
||||||
|
var seasonList = await VerifyShowHasLoaded(tvdbId, apiKey, baseUrl);
|
||||||
|
if (seasonList.result.Equals("failure"))
|
||||||
|
{
|
||||||
|
await Task.Delay(3000);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
seasonIncrement = seasonList.Data?.Length ?? 0;
|
||||||
|
|
||||||
|
if (sw.ElapsedMilliseconds > 30000) // Break out after 30 seconds, it's not going to get added
|
||||||
|
{
|
||||||
|
_log.LogWarning("Couldn't find out if the show had been added after 10 seconds. I doubt we can change the status to wanted.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sw.Stop();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_log.LogCritical(e, "Exception thrown when getting the seasonList");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (seasons.Length > 0)
|
||||||
|
{
|
||||||
|
//handle the seasons requested
|
||||||
|
foreach (var s in seasons)
|
||||||
|
{
|
||||||
|
var result = await AddSeason(tvdbId, s, apiKey, baseUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_log.LogCritical(e, "Exception when adding seasons:");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<SickRageTvAdd> AddSeason(int tvdbId, int season, string apiKey, string baseUrl)
|
||||||
|
{
|
||||||
|
var request = new Request($"/api/{apiKey}/?cmd=episode.setstatus", baseUrl, HttpMethod.Get);
|
||||||
|
request.AddQueryString("tvdbid", tvdbId.ToString());
|
||||||
|
request.AddQueryString("season", season.ToString());
|
||||||
|
request.AddQueryString("status", SickRageStatus.Wanted);
|
||||||
|
|
||||||
|
return await _api.Request<SickRageTvAdd>(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<SickRageShows> GetShows(string apiKey, string baseUrl)
|
||||||
|
{
|
||||||
|
var request = new Request($"/api/{apiKey}/?cmd=shows", baseUrl, HttpMethod.Get);
|
||||||
|
|
||||||
|
return await _api.Request<SickRageShows>(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<SickRagePing> Ping(string apiKey, string baseUrl)
|
||||||
|
{
|
||||||
|
var request = new Request($"/api/{apiKey}/?cmd=sb.ping", baseUrl, HttpMethod.Get);
|
||||||
|
|
||||||
|
return await _api.Request<SickRagePing>(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the epsiode status e.g. wanted
|
||||||
|
/// The episode number is optional, if not supplied it will set the whole season as the status passed in
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<SickRageEpisodeStatus> SetEpisodeStatus(string apiKey, string baseUrl, int tvdbid, string status, int season, int episode = -1)
|
||||||
|
{
|
||||||
|
var request = new Request($"/api/{apiKey}/?cmd=episode.setstatus", baseUrl, HttpMethod.Get);
|
||||||
|
request.AddQueryString("tvdbid", tvdbid.ToString());
|
||||||
|
request.AddQueryString("status", status);
|
||||||
|
request.AddQueryString("season", season.ToString());
|
||||||
|
|
||||||
|
if (episode != -1)
|
||||||
|
{
|
||||||
|
request.AddQueryString("episode", episode.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return await _api.Request<SickRageEpisodeStatus>(request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,6 +36,7 @@ using Ombi.Api.Mattermost;
|
||||||
using Ombi.Api.Pushbullet;
|
using Ombi.Api.Pushbullet;
|
||||||
using Ombi.Api.Pushover;
|
using Ombi.Api.Pushover;
|
||||||
using Ombi.Api.Service;
|
using Ombi.Api.Service;
|
||||||
|
using Ombi.Api.SickRage;
|
||||||
using Ombi.Api.Slack;
|
using Ombi.Api.Slack;
|
||||||
using Ombi.Core.Rule.Interfaces;
|
using Ombi.Core.Rule.Interfaces;
|
||||||
using Ombi.Core.Senders;
|
using Ombi.Core.Senders;
|
||||||
|
@ -102,6 +103,7 @@ namespace Ombi.DependencyInjection
|
||||||
services.AddTransient<IDogNzbApi, DogNzbApi>();
|
services.AddTransient<IDogNzbApi, DogNzbApi>();
|
||||||
services.AddTransient<ITelegramApi, TelegramApi>();
|
services.AddTransient<ITelegramApi, TelegramApi>();
|
||||||
services.AddTransient<IGithubApi, GithubApi>();
|
services.AddTransient<IGithubApi, GithubApi>();
|
||||||
|
services.AddTransient<ISickRageApi, SickRageApi>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RegisterStore(this IServiceCollection services) {
|
public static void RegisterStore(this IServiceCollection services) {
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
<ProjectReference Include="..\Ombi.Api.Pushover\Ombi.Api.Pushover.csproj" />
|
<ProjectReference Include="..\Ombi.Api.Pushover\Ombi.Api.Pushover.csproj" />
|
||||||
<ProjectReference Include="..\Ombi.Api.Radarr\Ombi.Api.Radarr.csproj" />
|
<ProjectReference Include="..\Ombi.Api.Radarr\Ombi.Api.Radarr.csproj" />
|
||||||
<ProjectReference Include="..\Ombi.Api.Service\Ombi.Api.Service.csproj" />
|
<ProjectReference Include="..\Ombi.Api.Service\Ombi.Api.Service.csproj" />
|
||||||
|
<ProjectReference Include="..\Ombi.Api.SickRage\Ombi.Api.SickRage.csproj" />
|
||||||
<ProjectReference Include="..\Ombi.Api.Slack\Ombi.Api.Slack.csproj" />
|
<ProjectReference Include="..\Ombi.Api.Slack\Ombi.Api.Slack.csproj" />
|
||||||
<ProjectReference Include="..\Ombi.Api.Sonarr\Ombi.Api.Sonarr.csproj" />
|
<ProjectReference Include="..\Ombi.Api.Sonarr\Ombi.Api.Sonarr.csproj" />
|
||||||
<ProjectReference Include="..\Ombi.Api.Telegram\Ombi.Api.Telegram.csproj" />
|
<ProjectReference Include="..\Ombi.Api.Telegram\Ombi.Api.Telegram.csproj" />
|
||||||
|
|
27
src/Ombi.Helpers/JsonConvertHelper.cs
Normal file
27
src/Ombi.Helpers/JsonConvertHelper.cs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Ombi.Helpers
|
||||||
|
{
|
||||||
|
public static class JsonConvertHelper
|
||||||
|
{
|
||||||
|
public static T[] ParseObjectToArray<T>(object ambiguousObject)
|
||||||
|
{
|
||||||
|
var json = ambiguousObject.ToString();
|
||||||
|
if (string.IsNullOrWhiteSpace(json))
|
||||||
|
{
|
||||||
|
return new T[0]; // Could return null here instead.
|
||||||
|
}
|
||||||
|
if (json.TrimStart().StartsWith("["))
|
||||||
|
{
|
||||||
|
return JsonConvert.DeserializeObject<T[]>(json);
|
||||||
|
}
|
||||||
|
if (json.TrimStart().Equals("{}"))
|
||||||
|
{
|
||||||
|
return new T[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return new T[1] { JsonConvert.DeserializeObject<T>(json) };
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
src/Ombi.sln
13
src/Ombi.sln
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 15
|
# Visual Studio 15
|
||||||
VisualStudioVersion = 15.0.26730.15
|
VisualStudioVersion = 15.0.27004.2009
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi", "Ombi\Ombi.csproj", "{C987AA67-AFE1-468F-ACD3-EAD5A48E1F6A}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi", "Ombi\Ombi.csproj", "{C987AA67-AFE1-468F-ACD3-EAD5A48E1F6A}"
|
||||||
EndProject
|
EndProject
|
||||||
|
@ -86,9 +86,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.DogNzb", "Ombi.Api
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Tests", "Ombi.Tests\Ombi.Tests.csproj", "{C12F5276-352A-43CF-8E33-400E768E9757}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Tests", "Ombi.Tests\Ombi.Tests.csproj", "{C12F5276-352A-43CF-8E33-400E768E9757}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.Telegram", "Ombi.Api.Telegram\Ombi.Api.Telegram.csproj", "{CB9DD209-8E09-4E01-983E-C77C89592D36}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.Telegram", "Ombi.Api.Telegram\Ombi.Api.Telegram.csproj", "{CB9DD209-8E09-4E01-983E-C77C89592D36}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.Github", "Ombi.Api.Github\Ombi.Api.Github.csproj", "{55866DEE-46D1-4AF7-B1A2-62F6190C8EC7}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.Github", "Ombi.Api.Github\Ombi.Api.Github.csproj", "{55866DEE-46D1-4AF7-B1A2-62F6190C8EC7}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.SickRage", "Ombi.Api.SickRage\Ombi.Api.SickRage.csproj", "{94C9A366-2595-45EA-AABB-8E4A2E90EC5B}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
@ -232,6 +234,10 @@ Global
|
||||||
{55866DEE-46D1-4AF7-B1A2-62F6190C8EC7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{55866DEE-46D1-4AF7-B1A2-62F6190C8EC7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{55866DEE-46D1-4AF7-B1A2-62F6190C8EC7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{55866DEE-46D1-4AF7-B1A2-62F6190C8EC7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{55866DEE-46D1-4AF7-B1A2-62F6190C8EC7}.Release|Any CPU.Build.0 = Release|Any CPU
|
{55866DEE-46D1-4AF7-B1A2-62F6190C8EC7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{94C9A366-2595-45EA-AABB-8E4A2E90EC5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{94C9A366-2595-45EA-AABB-8E4A2E90EC5B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{94C9A366-2595-45EA-AABB-8E4A2E90EC5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{94C9A366-2595-45EA-AABB-8E4A2E90EC5B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@ -265,6 +271,7 @@ Global
|
||||||
{C12F5276-352A-43CF-8E33-400E768E9757} = {6F42AB98-9196-44C4-B888-D5E409F415A1}
|
{C12F5276-352A-43CF-8E33-400E768E9757} = {6F42AB98-9196-44C4-B888-D5E409F415A1}
|
||||||
{CB9DD209-8E09-4E01-983E-C77C89592D36} = {9293CA11-360A-4C20-A674-B9E794431BF5}
|
{CB9DD209-8E09-4E01-983E-C77C89592D36} = {9293CA11-360A-4C20-A674-B9E794431BF5}
|
||||||
{55866DEE-46D1-4AF7-B1A2-62F6190C8EC7} = {9293CA11-360A-4C20-A674-B9E794431BF5}
|
{55866DEE-46D1-4AF7-B1A2-62F6190C8EC7} = {9293CA11-360A-4C20-A674-B9E794431BF5}
|
||||||
|
{94C9A366-2595-45EA-AABB-8E4A2E90EC5B} = {9293CA11-360A-4C20-A674-B9E794431BF5}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {192E9BF8-00B4-45E4-BCCC-4C215725C869}
|
SolutionGuid = {192E9BF8-00B4-45E4-BCCC-4C215725C869}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue