236 lines
8.9 KiB
C#
236 lines
8.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Google.Apis.Auth.OAuth2;
|
|
using Google.Apis.Services;
|
|
using Google.Apis.YouTube.v3;
|
|
using Google.Apis.YouTube.v3.Data;
|
|
using Newtonsoft.Json;
|
|
using Windows.Storage;
|
|
using Windows.Services.Store;
|
|
|
|
namespace FoxTube
|
|
{
|
|
public static class SecretsVault
|
|
{
|
|
#region Properties
|
|
//Events
|
|
public static event ObjectEventHandler AuthorizationStateChanged;
|
|
public static event ObjectEventHandler SubscriptionsChanged;
|
|
public static event ObjectEventHandler Purchased; //Rising when app finds out that it's not a PRO version
|
|
|
|
//Private properties
|
|
private static ClientSecrets Secrets => new ClientSecrets()
|
|
{
|
|
ClientId = "349735264870-2ekqlm0a4mkg3mmrfcv90s3qp3o15dq0.apps.googleusercontent.com",
|
|
ClientSecret = "BkVZOAaCU2Zclf0Zlicg6y2_"
|
|
};
|
|
private static YouTubeService NoAuthService => new YouTubeService(new BaseClientService.Initializer()
|
|
{
|
|
ApiKey = "AIzaSyBgHrCnrlzlVmk0cJKL8RqP9Y8x6XSuk_0",
|
|
ApplicationName = "FoxTube"
|
|
});
|
|
public static BaseClientService.Initializer Initializer => new BaseClientService.Initializer()
|
|
{
|
|
HttpClientInitializer = Credential,
|
|
ApplicationName = "FoxTube"
|
|
};
|
|
public static YouTubeService Service => IsAuthorized ? new YouTubeService(Initializer) : NoAuthService;
|
|
public static string AppId => true ? "d25517cb-12d4-4699-8bdc-52040c712cab" : "9ncqqxjtdlfh";
|
|
public static string AdUnitId => true ? "test" : "1100037769";
|
|
public static bool AdsDisabled { get; private set; } = true;
|
|
|
|
//User info
|
|
public static bool IsAuthorized => Credential != null;
|
|
public static UserCredential Credential { get; set; }
|
|
|
|
public static string AccountId => UserChannel?.Id;
|
|
public static Channel UserChannel { get; private set; }
|
|
|
|
public static List<Subscription> Subscriptions { get; } = new List<Subscription>();
|
|
#endregion
|
|
|
|
#region Methods
|
|
/// <summary>
|
|
/// Subscribes or unsibscribes authorized user from the channel
|
|
/// </summary>
|
|
/// <param name="id">The ID of channel which has to be added/removed</param>
|
|
/// <returns>Returns 'true' if channel is in subscriptions now; 'false' if it's not</returns>
|
|
public static async Task<bool> ChangeSubscriptionState(string id)
|
|
{
|
|
if (!IsAuthorized)
|
|
return false;
|
|
|
|
if(Subscriptions.Exists(x => x.Snippet.ResourceId.ChannelId == id))
|
|
{
|
|
Subscription s = Subscriptions.Find(x => x.Snippet.ResourceId.ChannelId == id);
|
|
|
|
try { await Service.Subscriptions.Delete(s.Id).ExecuteAsync(); }
|
|
catch { return true; }
|
|
|
|
SubscriptionsChanged?.Invoke(null, "remove", Subscriptions.IndexOf(s));
|
|
Subscriptions.Remove(s);
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
var request = Service.Subscriptions.Insert(new Subscription()
|
|
{
|
|
Snippet = new SubscriptionSnippet()
|
|
{
|
|
ResourceId = new ResourceId()
|
|
{
|
|
ChannelId = id,
|
|
Kind = "youtube#channel"
|
|
}
|
|
}
|
|
}, "snippet");
|
|
|
|
Subscription s = await request.ExecuteAsync();
|
|
if (s == null)
|
|
return false;
|
|
Subscriptions.Add(s);
|
|
SubscriptionsChanged?.Invoke(null, "add", s);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Prompts to add an Youtube account and retrieves its info when successful
|
|
/// </summary>
|
|
/// <param name="retrieveSubs">Loads user's subscriptions if true</param>
|
|
public static async void Authorize(bool retrieveSubs = true)
|
|
{
|
|
try
|
|
{
|
|
#region Retrieving user's credential
|
|
Credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
|
|
Secrets,
|
|
new[]
|
|
{
|
|
Google.Apis.Oauth2.v2.Oauth2Service.Scope.UserinfoProfile,
|
|
YouTubeService.Scope.YoutubeForceSsl
|
|
},
|
|
"user",
|
|
CancellationToken.None);
|
|
|
|
if (Credential == null || !retrieveSubs)
|
|
goto InvokeEvent;
|
|
|
|
SettingsStorage.HasAccount = true;
|
|
#endregion
|
|
|
|
#region Retrieving user's data
|
|
var request = Service.Channels.List("snippet,contentDetails");
|
|
request.Mine = true;
|
|
UserChannel = (await request.ExecuteAsync()).Items[0];
|
|
|
|
SubscriptionsResource.ListRequest subRequest = Service.Subscriptions.List("snippet");
|
|
subRequest.Mine = true;
|
|
subRequest.MaxResults = 50;
|
|
subRequest.Order = SubscriptionsResource.ListRequest.OrderEnum.Relevance;
|
|
SubscriptionListResponse subResponse;
|
|
string nextToken = null;
|
|
Subscriptions.Clear();
|
|
|
|
do
|
|
{
|
|
subRequest.PageToken = nextToken;
|
|
subResponse = await subRequest.ExecuteAsync();
|
|
foreach (Subscription s in subResponse.Items)
|
|
Subscriptions.Add(s);
|
|
nextToken = subResponse.NextPageToken;
|
|
|
|
} while (!string.IsNullOrWhiteSpace(nextToken));
|
|
#endregion
|
|
|
|
//Saving user's subscriptions for background task
|
|
SaveSubscriptions();
|
|
|
|
InvokeEvent:
|
|
AuthorizationStateChanged?.Invoke(args: IsAuthorized);
|
|
}
|
|
catch
|
|
{
|
|
AuthorizationStateChanged?.Invoke(args: new bool?[] { null });
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Saves user's subscriptions keypairs (channel ID: avatar URL) into "background.json" file for concurrent background processing
|
|
/// </summary>
|
|
public static async void SaveSubscriptions()
|
|
{
|
|
Dictionary<string, string> subs = new Dictionary<string, string>();
|
|
Subscriptions.ForEach(x => subs.Add(x.Snippet.ResourceId.ChannelId, x.Snippet.Thumbnails.Medium.Url));
|
|
await FileIO.WriteTextAsync(
|
|
await ApplicationData.Current.RoamingFolder.CreateFileAsync("background.json", CreationCollisionOption.ReplaceExisting),
|
|
JsonConvert.SerializeObject(subs));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Deauthenticates current user
|
|
/// </summary>
|
|
public static async void Deauthenticate()
|
|
{
|
|
if(await Credential.RevokeTokenAsync(CancellationToken.None))
|
|
{
|
|
Credential = null;
|
|
AuthorizationStateChanged?.Invoke(args: false);
|
|
SettingsStorage.HasAccount = false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if any user has already been logged in. If has, calls *Authorize()* to retrieve his info
|
|
/// </summary>
|
|
/// <param name="retrieveSubs">Loads user's subscriptions if true</param>
|
|
public static void CheckAuthorization(bool retrieveSubs = true)
|
|
{
|
|
if (SettingsStorage.HasAccount)
|
|
Authorize(retrieveSubs);
|
|
else AuthorizationStateChanged.Invoke(args: false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Connects to MS Store and checks if user has bought ad-free
|
|
/// </summary>
|
|
public static async void CheckAddons()
|
|
{
|
|
try
|
|
{
|
|
StoreContext store = StoreContext.GetDefault();
|
|
StoreProductQueryResult requset = await store.GetAssociatedStoreProductsAsync(new[] { "Consumable", "Durable", "UnmanagedConsumable" });
|
|
|
|
if (!requset.Products["foxtube-adsremove"].IsInUserCollection)
|
|
{
|
|
AdsDisabled = false;
|
|
Purchased?.Invoke(args:false);
|
|
}
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
public static async void GetAdblock()
|
|
{
|
|
StoreContext store = StoreContext.GetDefault();
|
|
StorePurchaseResult request = await store.RequestPurchaseAsync("foxtube-adsremove");
|
|
|
|
switch (request.Status)
|
|
{
|
|
case StorePurchaseStatus.AlreadyPurchased:
|
|
Purchased?.Invoke(args: true);
|
|
AdsDisabled = true;
|
|
break;
|
|
|
|
case StorePurchaseStatus.Succeeded:
|
|
Purchased?.Invoke(args: true);
|
|
AdsDisabled = true;
|
|
break;
|
|
}
|
|
}
|
|
#endregion
|
|
}
|
|
}
|