From b011415e0e9ebe76a52605881b6146f6e76f49d9 Mon Sep 17 00:00:00 2001 From: sentouki Date: Fri, 24 Sep 2021 01:35:49 +0200 Subject: [PATCH] - fixed Pixiv Login - changed ArtifyModel to a Singleton - refactoring --- ArtAPI/PixivAPI.cs | 4 +- Artify/Models/ArtifyModel.cs | 47 ++++++++++++-------- Artify/ViewModels/ArtifyViewModel.cs | 27 +++++------- Artify/ViewModels/SettingsViewModel.cs | 61 ++++++++++---------------- Artify/Views/MainView.xaml.cs | 11 +++-- Artify/Views/SettingsPopUp.xaml | 23 +++++++++- Artify/Views/SettingsPopUp.xaml.cs | 29 ++++++++++-- Artify/Views/misc/CEFRequestHandler.cs | 22 ++++++++++ README.md | 3 +- 9 files changed, 138 insertions(+), 89 deletions(-) create mode 100644 Artify/Views/misc/CEFRequestHandler.cs diff --git a/ArtAPI/PixivAPI.cs b/ArtAPI/PixivAPI.cs index 7119aae..b6f86bd 100644 --- a/ArtAPI/PixivAPI.cs +++ b/ArtAPI/PixivAPI.cs @@ -29,8 +29,8 @@ public PixivAPI() { Client.DefaultRequestHeaders.Referrer = new Uri("https://www.pixiv.net"); Client.DefaultRequestHeaders.UserAgent.Clear(); - Client.DefaultRequestHeaders.UserAgent.ParseAdd("PixivAndroidApp/5.0.115 (Android 6.0; ArtifyApp)"); - Client.DefaultRequestHeaders.Host = "oauth.secure.pixiv.net"; + Client.DefaultRequestHeaders.UserAgent.ParseAdd("PixivAndroidApp/5.0.219 (Android 11; Artify)"); + //Client.DefaultRequestHeaders.Host = "oauth.secure.pixiv.net"; } public override async Task CreateUrlFromName(string artistName) diff --git a/Artify/Models/ArtifyModel.cs b/Artify/Models/ArtifyModel.cs index eafbf6f..3e4f426 100644 --- a/Artify/Models/ArtifyModel.cs +++ b/Artify/Models/ArtifyModel.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Dynamic; using System.IO; using System.Text.RegularExpressions; using System.Threading.Tasks; @@ -18,13 +17,12 @@ public enum InputType ArtistNameOrID, } /// - /// a wrapper around the ArtAPI + /// a wrapper singleton around the ArtAPI /// public class ArtifyModel { - private readonly string SettingsDirPath, SettingsFilePath; - private RequestArt _platform; - private readonly Dictionary URLpattern = new Dictionary() + private readonly string _settingsDirPath, _settingsFilePath; + private readonly Dictionary _urlPattern = new Dictionary() { {"general", new Regex(@"(https?://)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}(\/?[a-zA-Z0-9]*\/?)*") }, {"artstation", new Regex(@"(https://)?(www\.)?artstation\.com/[0-9a-zA-Z]+/?") }, @@ -38,6 +36,9 @@ public class ArtifyModel { "pixiv", () => new PixivAPI() }, { "deviantart", () => new DeviantArtAPI()} }; + private static ArtifyModel _instance; + public static ArtifyModel Instance => _instance ??= new ArtifyModel(); + private RequestArt _platform; public RequestArt Platform { get => _platform; @@ -71,10 +72,10 @@ public int ConcurrentTasks private string _selectedPlatform; public Settings settings = new Settings(); - public ArtifyModel() + private ArtifyModel() { - SettingsDirPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), ".artify"); - SettingsFilePath = Path.Combine(SettingsDirPath, "settings.json"); + _settingsDirPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), ".artify"); + _settingsFilePath = Path.Combine(_settingsDirPath, "settings.json"); if (CheckSettingsDir()) LoadSettings(); else CreateSettingsDir(); @@ -82,14 +83,14 @@ public ArtifyModel() private bool CheckSettingsDir() { - return Directory.Exists(SettingsDirPath) && File.Exists(SettingsFilePath); + return Directory.Exists(_settingsDirPath) && File.Exists(_settingsFilePath); } private void LoadSettings() { - var fi = new FileInfo(SettingsFilePath) { Attributes = FileAttributes.Normal }; + var fi = new FileInfo(_settingsFilePath) { Attributes = FileAttributes.Normal }; try { - using var sr = new StreamReader(SettingsFilePath); + using var sr = new StreamReader(_settingsFilePath); var stringJson = sr.ReadToEnd(); if (stringJson.Length > 0) { @@ -104,9 +105,9 @@ private void LoadSettings() } private void CreateSettingsDir() { - var di = Directory.CreateDirectory(SettingsDirPath); + var di = Directory.CreateDirectory(_settingsDirPath); di.Attributes = FileAttributes.Directory | FileAttributes.Hidden; - File.Create(SettingsFilePath).Close(); + File.Create(_settingsFilePath).Close(); } public void UpdateSettings() { @@ -116,8 +117,8 @@ public void UpdateSettings() { settings.pixiv_refresh_token = null; } - var fi = new FileInfo(SettingsFilePath) { Attributes = FileAttributes.Normal }; - using (var sw = new StreamWriter(SettingsFilePath)) + var fi = new FileInfo(_settingsFilePath) { Attributes = FileAttributes.Normal }; + using (var sw = new StreamWriter(_settingsFilePath)) { new JsonSerializer().Serialize(sw, settings); } @@ -130,11 +131,11 @@ public void UpdateSettings() /// true if it's the right url, false if it's a url but a wrong one, null if neither (e.g. artist name) private bool? CheckUrl(string input) { - if (!URLpattern["general"].IsMatch(input)) + if (!_urlPattern["general"].IsMatch(input)) { return null; } - return URLpattern[_selectedPlatform].IsMatch(input); + return _urlPattern[_selectedPlatform].IsMatch(input); } /// /// check the user input @@ -166,7 +167,7 @@ public async Task CheckUserInput(string input) public void SelectPlatform(string platformName) { - Platform = ArtPlatform[platformName](); // create object of the selected platform + Platform = ArtPlatform[platformName](); // create an object of the selected platform _selectedPlatform = platformName; Platform.SavePath = SavePath; Platform.ClientTimeout = ClientTimeout; @@ -183,5 +184,15 @@ public async Task Auth() } return false; } + + public async Task PixivLogin(string code) + { + var pixiv = (PixivAPI)Platform; + if (await pixiv.Login(code) is { } result) + { + settings.pixiv_refresh_token = result; + UpdateSettings(); + } + } } } diff --git a/Artify/ViewModels/ArtifyViewModel.cs b/Artify/ViewModels/ArtifyViewModel.cs index 5756c39..c7ae879 100644 --- a/Artify/ViewModels/ArtifyViewModel.cs +++ b/Artify/ViewModels/ArtifyViewModel.cs @@ -8,7 +8,6 @@ namespace Artify.ViewModels { public class ArtifyViewModel : BaseViewModel { - private readonly ArtifyModel artifyModel; private State _currentState; #region public properties public string RunDownloadButtonContent { get; set; } = "Download"; @@ -30,7 +29,6 @@ public class ArtifyViewModel : BaseViewModel #region ctor public ArtifyViewModel() { - artifyModel = new ArtifyModel(); RunDownloadCommand = new RelayCommand(RunDownload); SelectPlatformCommand = new RelayCommand(SelectPlatform); ShutdownCommand = new RelayCommand(Shutdown); @@ -38,15 +36,10 @@ public ArtifyViewModel() #endregion private void Shutdown(IShutDown view) { - artifyModel.UpdateSettings(); + ArtifyModel.Instance.UpdateSettings(); CancelDownload(); view.AppShutDown(); } - - public SettingsViewModel CreateSettingsVM() - { - return new SettingsViewModel(artifyModel); - } #region ArtAPI event handler private void Platform_DownloadStateChanged(object sender, DownloadStateChangedEventArgs e) { @@ -124,11 +117,11 @@ private async void SelectPlatform(string platform) CancelDownload(); } SelectedPlatform = platform; - artifyModel.SelectPlatform(platform); - artifyModel.Platform.DownloadProgressChanged += UpdateProgress; - artifyModel.Platform.DownloadStateChanged += Platform_DownloadStateChanged; - artifyModel.Platform.LoginStatusChanged += PlatformOnLoginStatusChanged; - IsLoggedIn = await artifyModel.Auth(); + ArtifyModel.Instance.SelectPlatform(platform); + ArtifyModel.Instance.Platform.DownloadProgressChanged += UpdateProgress; + ArtifyModel.Instance.Platform.DownloadStateChanged += Platform_DownloadStateChanged; + ArtifyModel.Instance.Platform.LoginStatusChanged += PlatformOnLoginStatusChanged; + IsLoggedIn = await ArtifyModel.Instance.Auth(); } private async void RunDownload() @@ -142,7 +135,7 @@ private async void RunDownload() #endif try { - switch (await artifyModel.CheckUserInput(UserInput)) + switch (await ArtifyModel.Instance.CheckUserInput(UserInput)) { case InputType.Empty: InputErrorMessage = "Input field cannot be empty!"; @@ -157,10 +150,10 @@ private async void RunDownload() IsInputValid = false; break; case InputType.URL: - await artifyModel.Platform.GetImagesAsync(UserInput); + await ArtifyModel.Instance.Platform.GetImagesAsync(UserInput); break; case InputType.ArtistNameOrID: - await artifyModel.Platform.GetImagesAsync(await artifyModel.Platform.CreateUrlFromName(UserInput)); + await ArtifyModel.Instance.Platform.GetImagesAsync(await ArtifyModel.Instance.Platform.CreateUrlFromName(UserInput)); break; } } @@ -187,7 +180,7 @@ private async void RunDownload() private void CancelDownload() { - artifyModel.Platform?.CancelDownload(); + ArtifyModel.Instance.Platform?.CancelDownload(); } #endregion } diff --git a/Artify/ViewModels/SettingsViewModel.cs b/Artify/ViewModels/SettingsViewModel.cs index edbd96a..fd79dc7 100644 --- a/Artify/ViewModels/SettingsViewModel.cs +++ b/Artify/ViewModels/SettingsViewModel.cs @@ -1,5 +1,4 @@ -using System.Threading.Tasks; -using ArtAPI; +using ArtAPI; using ArtAPI.misc; using Artify.Models; @@ -7,48 +6,45 @@ namespace Artify.ViewModels { public class SettingsViewModel : BaseViewModel { - private readonly ArtifyModel _artifyModel; public bool IsInputEnabled { get; set; } = true; - public bool OpenBrowser { get; set; } = false; + public bool OpenBrowser { get; set; } public string LoginUrl { get; set; } - public string LoginNotification { get; set; } public string SaveLocation { - get => _artifyModel.SavePath; - set => _artifyModel.SavePath = value; + get => ArtifyModel.Instance.SavePath; + set => ArtifyModel.Instance.SavePath = value; } public int ClientTimeout { - get => _artifyModel.ClientTimeout; - set => _artifyModel.ClientTimeout = value > 0 ? value : 1; + get => ArtifyModel.Instance.ClientTimeout; + set => ArtifyModel.Instance.ClientTimeout = value > 0 ? value : 1; } public int DownloadAttempts { - get => _artifyModel.DownloadAttempts; - set => _artifyModel.DownloadAttempts = value > 0 ? value : 1; + get => ArtifyModel.Instance.DownloadAttempts; + set => ArtifyModel.Instance.DownloadAttempts = value > 0 ? value : 1; } public int ConcurrentTasks { - get => _artifyModel.ConcurrentTasks; - set => _artifyModel.ConcurrentTasks = value > 0 ? value : 1; + get => ArtifyModel.Instance.ConcurrentTasks; + set => ArtifyModel.Instance.ConcurrentTasks = value > 0 ? value : 1; } public bool IsLoggedIn { get; set; } public RelayCommand LoginCommand { get; } - public SettingsViewModel(ArtifyModel artifyM) + public SettingsViewModel() { - _artifyModel = artifyM; - _artifyModel.Platform.LoginStatusChanged += Platform_LoginStatusChanged; - Platform_LoginStatusChanged(this, new LoginStatusChangedEventArgs(_artifyModel.Platform.LoginState)); - LoginCommand = new RelayCommand(async () => await Login()); - if (_artifyModel.Platform.CurrentState == State.DownloadRunning) + ArtifyModel.Instance.Platform.LoginStatusChanged += Platform_LoginStatusChanged; + Platform_LoginStatusChanged(this, new LoginStatusChangedEventArgs(ArtifyModel.Instance.Platform.LoginState)); + LoginCommand = new RelayCommand(GetCode); + if (ArtifyModel.Instance.Platform.CurrentState == State.DownloadRunning) { IsInputEnabled = false; } } ~SettingsViewModel() { - _artifyModel.Platform.LoginStatusChanged -= Platform_LoginStatusChanged; + ArtifyModel.Instance.Platform.LoginStatusChanged -= Platform_LoginStatusChanged; } private void Platform_LoginStatusChanged(object sender, LoginStatusChangedEventArgs e) @@ -57,40 +53,29 @@ private void Platform_LoginStatusChanged(object sender, LoginStatusChangedEventA { case LoginStatus.LoggingIn: IsInputEnabled = false; - LoginNotification = "Logging in ..."; break; case LoginStatus.Authenticating: IsInputEnabled = false; - LoginNotification = "Authenticating ..."; break; case LoginStatus.LoggedIn: IsInputEnabled = true; - LoginNotification = ""; IsLoggedIn = true; + OpenBrowser = false; break; case LoginStatus.Failed: - LoginNotification = "Authenticating failed"; IsInputEnabled = true; + OpenBrowser = false; break; } } - - private async Task Login() + /// + /// get the URL with code for the further login process and open the browser + /// + private void GetCode() { - var pixiv = (PixivAPI) _artifyModel.Platform; - IsInputEnabled = false; + var pixiv = (PixivAPI) ArtifyModel.Instance.Platform; LoginUrl = pixiv.Pkce(); OpenBrowser = true; - if (await _artifyModel.Platform.Login(UserName, UserPassword) is { } result) - { - _artifyModel.settings.pixiv_refresh_token = result; - _artifyModel.UpdateSettings(); - } - else - { - LoginNotification = "Something went wrong"; - } - IsInputEnabled = true; } } } diff --git a/Artify/Views/MainView.xaml.cs b/Artify/Views/MainView.xaml.cs index 1e19f8f..c02caf3 100644 --- a/Artify/Views/MainView.xaml.cs +++ b/Artify/Views/MainView.xaml.cs @@ -2,12 +2,12 @@ using System.Windows; using System.Windows.Input; using System.Windows.Media.Animation; -using ArtAPI; using Artify.ViewModels; using Artify.ViewModels.misc; namespace Artify.Views { + // ReSharper disable once RedundantExtendsListEntry public partial class MainWindow : Window, IShutDown { private Storyboard @@ -49,8 +49,7 @@ private void SettingsClick(object sender, RoutedEventArgs e) { popUp = new SettingsPopUp { - Owner = this, - DataContext = _artifyVM.CreateSettingsVM() + Owner = this }; popUp.ShowDialog(); } @@ -67,13 +66,13 @@ private void ResizeButton_Click(object sender, RoutedEventArgs e) WindowState = WindowState == WindowState.Normal ? WindowState.Maximized : WindowState.Normal; } - private void Window_KeyDown(object sender, System.Windows.Input.KeyEventArgs e) + private void Window_KeyDown(object sender, KeyEventArgs e) { - if ((e.Key == System.Windows.Input.Key.Escape) && SelectionMenu.Visibility == Visibility.Hidden) + if ((e.Key == Key.Escape) && SelectionMenu.Visibility == Visibility.Hidden) { ShowSelectionMenu(); } - else if ((e.Key == System.Windows.Input.Key.Escape) && SelectionMenu.Visibility == Visibility.Visible && SelectedPlatformIcon.Source != null) + else if ((e.Key == Key.Escape) && SelectionMenu.Visibility == Visibility.Visible && SelectedPlatformIcon.Source != null) { HideSelectionMenu(); } diff --git a/Artify/Views/SettingsPopUp.xaml b/Artify/Views/SettingsPopUp.xaml index d5c6f46..60b2947 100644 --- a/Artify/Views/SettingsPopUp.xaml +++ b/Artify/Views/SettingsPopUp.xaml @@ -3,6 +3,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:wpf="clr-namespace:CefSharp.Wpf;assembly=CefSharp.Wpf" mc:Ignorable="d" Title="SettingsPopUp" MinHeight="450" MinWidth="400" Height="450" Width="400" MaxHeight="700" MaxWidth="900" WindowStartupLocation="CenterOwner" ShowInTaskbar="False" Background="#141414" Opacity="0.99" Style="{StaticResource ArtifyPopUpWindowStyle}" KeyDown="Window_KeyDown"> @@ -28,7 +29,7 @@ - +