From 3995577133cb6d1387d92c29d9591df44389653b Mon Sep 17 00:00:00 2001 From: Rinacm <2653221698@qq.com> Date: Thu, 29 Oct 2020 17:52:44 +0800 Subject: [PATCH] fix --- .idea/.idea.Pixeval/.idea/encodings.xml | 4 + .idea/.idea.Pixeval/.idea/indexLayout.xml | 8 + .idea/.idea.Pixeval/.idea/modules.xml | 8 + .../.idea/projectSettingsUpdater.xml | 6 + .../.idea.Pixeval}/.idea/vcs.xml | 2 +- .idea/.idea.Pixeval/riderModule.iml | 36 + .../App.xaml | 0 .../App.xaml.cs | 0 .../AssemblyInfo.cs | 0 .../ChecksumFailedException.cs | 0 .../Cipher.cs | 0 .../MainWindow.xaml | 77 +- .../MainWindow.xaml.cs | 51 +- .../Pixeval.Updater.csproj | 0 .../RelevantURL.cs | 0 .../Resources/pxlogo.ico | Bin .../build.ps1 | 0 .../pxlogo.ico | Bin Pixeval.sln | 18 +- Pixeval/AppContext.cs | 2 +- Pixeval/Pixeval.csproj | 1 + .../Pixeval.Interchange.csproj | 12 - src/Pixeval.Interchange/Program.cs | 61 - .../Properties/launchSettings.json | 11 - src/Pixeval.Interchange/build.ps1 | 1 - src/Pixeval/Annotations.cs | 1383 ---------- src/Pixeval/App.xaml | 307 --- src/Pixeval/App.xaml.cs | 281 -- src/Pixeval/AppContext.cs | 74 - .../Core/AbstractPixivAsyncEnumerable.cs | 64 - .../Core/AbstractPixivAsyncEnumerator.cs | 50 - src/Pixeval/Core/BrowsingHistoryAccessor.cs | 128 - ...ateNewFolderForUserDownloadPathProvider.cs | 51 - .../Core/DefaultDownloadPathProvider.cs | 44 - .../DefaultIllustrationFileNameFormatter.cs | 44 - src/Pixeval/Core/EnumeratingSchedule.cs | 47 - src/Pixeval/Core/GalleryAsyncEnumerable.cs | 157 -- src/Pixeval/Core/ICancellable.cs | 29 - src/Pixeval/Core/IDownloadPathProvider.cs | 49 - src/Pixeval/Core/IPixivAsyncEnumerable.cs | 56 - src/Pixeval/Core/IQualifier.cs | 27 - src/Pixeval/Core/ITimelineService.cs | 43 - src/Pixeval/Core/IllustrationQualification.cs | 53 - src/Pixeval/Core/IllustrationQualifier.cs | 39 - src/Pixeval/Core/Managers.cs | 95 - src/Pixeval/Core/PixivClient.cs | 43 - src/Pixeval/Core/PixivClientExtension.cs | 94 - src/Pixeval/Core/PixivHelper.cs | 129 - src/Pixeval/Core/PixivIO.cs | 98 - src/Pixeval/Core/PluggableProtocolListener.cs | 50 - src/Pixeval/Core/PluggableProtocolParser.cs | 105 - src/Pixeval/Core/QueryAsyncEnumerable.cs | 169 -- src/Pixeval/Core/RankOption.cs | 136 - src/Pixeval/Core/RankingAsyncEnumerable.cs | 128 - src/Pixeval/Core/RecommendAsyncEnumerable.cs | 127 - .../Core/RecommendIllustratorDeferrer.cs | 68 - src/Pixeval/Core/RestrictPolicy.cs | 27 - src/Pixeval/Core/SearchTagMatchOption.cs | 48 - .../Core/SpotlightQueryAsyncEnumerable.cs | 112 - src/Pixeval/Core/TrendsAsyncEnumerable.cs | 229 -- src/Pixeval/Core/UploadAsyncEnumerable.cs | 124 - .../Core/UserFollowingAsyncEnumerable.cs | 151 -- .../Core/UserPreviewAsyncEnumerable.cs | 111 - src/Pixeval/Core/UserUpdateAsyncEnumerable.cs | 109 - .../Core/WindowsUserActivityManager.cs | 135 - src/Pixeval/Data/IParser.cs | 27 - src/Pixeval/Data/ViewModel/AutoCompletion.cs | 32 - src/Pixeval/Data/ViewModel/BrowsingHistory.cs | 61 - src/Pixeval/Data/ViewModel/ConditionString.cs | 33 - .../ViewModel/DownloadableIllustration.cs | 200 -- src/Pixeval/Data/ViewModel/I18nOption.cs | 46 - src/Pixeval/Data/ViewModel/Illustration.cs | 114 - src/Pixeval/Data/ViewModel/RankOptionModel.cs | 60 - .../ViewModel/SearchTagMatchOptionModel.cs | 50 - .../Data/ViewModel/SpotlightArticle.cs | 69 - src/Pixeval/Data/ViewModel/TrendingTag.cs | 34 - src/Pixeval/Data/ViewModel/Trends.cs | 67 - src/Pixeval/Data/ViewModel/User.cs | 46 - .../DnsResolvedHttpClientHandler.cs | 89 - .../Data/Web/Delegation/DnsResolver.cs | 135 - .../Data/Web/Delegation/HttpClientFactory.cs | 72 - .../Web/Delegation/IHttpRequestHandler.cs | 29 - .../Web/Delegation/PixivApiDnsResolver.cs | 37 - .../Delegation/PixivApiHttpClientHandler.cs | 38 - .../PixivAuthenticationHttpRequestHandler.cs | 62 - .../Delegation/PixivImageHttpClientHandler.cs | 35 - src/Pixeval/Data/Web/HttpResponse.cs | 47 - .../Data/Web/Protocol/IAppApiProtocol.cs | 64 - .../Data/Web/Protocol/IResolveDnsProtocol.cs | 33 - .../Data/Web/Protocol/ISauceNAOProtocol.cs | 35 - .../Data/Web/Protocol/ITokenProtocol.cs | 37 - .../Data/Web/Protocol/IWebApiProtocol.cs | 41 - src/Pixeval/Data/Web/ProtocolBase.cs | 37 - .../Data/Web/Request/AddBookmarkRequest.cs | 33 - .../Data/Web/Request/AutoCompletionRequest.cs | 33 - .../Data/Web/Request/DeleteBookmarkRequest.cs | 30 - .../Data/Web/Request/DnsResolveRequest.cs | 42 - .../Data/Web/Request/FollowArtistRequest.cs | 33 - .../Data/Web/Request/PasswordTokenRequest.cs | 45 - .../Request/RecommendIllustratorRequest.cs | 33 - .../Data/Web/Request/RefreshTokenRequest.cs | 42 - .../Data/Web/Request/ToggleR18StateRequest.cs | 45 - .../Data/Web/Request/UnFollowArtistRequest.cs | 30 - .../Web/Request/UserInformationRequest.cs | 33 - .../Web/Response/AutoCompletionResponse.cs | 40 - .../Data/Web/Response/DnsResolveResponse.cs | 76 - .../Data/Web/Response/FollowingResponse.cs | 263 -- .../Data/Web/Response/GalleryResponse.cs | 204 -- .../Data/Web/Response/QueryWorksResponse.cs | 203 -- .../Data/Web/Response/RankingResponse.cs | 204 -- .../Response/RecommendIllustratorResponse.cs | 179 -- .../Data/Web/Response/RecommendResponse.cs | 207 -- .../Data/Web/Response/SingleWorkResponse.cs | 164 -- .../Web/Response/SpotlightArticleResponse.cs | 49 - .../Data/Web/Response/SpotlightResponse.cs | 35 - .../Data/Web/Response/TokenResponse.cs | 130 - .../Data/Web/Response/TrendingTagResponse.cs | 173 -- .../Web/Response/UgoiraMetadataResponse.cs | 55 - .../Data/Web/Response/UploadResponse.cs | 206 -- .../Web/Response/UserInformationResponse.cs | 198 -- .../Data/Web/Response/UserNavResponse.cs | 106 - .../Data/Web/Response/UserUpdateResponse.cs | 204 -- .../Web/Response/WebApiUserDetailResponse.cs | 54 - src/Pixeval/FodyWeavers.xml | 3 - src/Pixeval/FodyWeavers.xsd | 64 - src/Pixeval/Objects/Caching/CachingPolicy.cs | 27 - src/Pixeval/Objects/Caching/FileCache.cs | 112 - .../Objects/Caching/IWeakCacheProvider.cs | 40 - src/Pixeval/Objects/Caching/MemoryCache.cs | 71 - src/Pixeval/Objects/Caching/WeakEntry.cs | 71 - .../Exceptions/AttributeNotFoundException.cs | 44 - .../Exceptions/AuthenticateFailedException.cs | 44 - .../Exceptions/Logger/ExceptionDumper.cs | 137 - .../Exceptions/QueryNotRespondingException.cs | 44 - .../Exceptions/TokenNotFoundException.cs | 44 - .../Exceptions/TypeMismatchException.cs | 44 - src/Pixeval/Objects/Generic/Enumerates.cs | 78 - src/Pixeval/Objects/Generic/Functions.cs | 47 - src/Pixeval/Objects/Generic/Observable.cs | 64 - src/Pixeval/Objects/Generic/Tasks.cs | 66 - src/Pixeval/Objects/I18n/ResourceLocator.cs | 93 - src/Pixeval/Objects/I18n/StringResources.cs | 1788 ------------- src/Pixeval/Objects/I18n/Xml/resx_en-us.xml | 175 -- src/Pixeval/Objects/I18n/Xml/resx_zh-cn.xml | 173 -- .../Objects/Native/WallpaperManager.cs | 76 - src/Pixeval/Objects/Primitive/Attributes.cs | 46 - src/Pixeval/Objects/Primitive/InternalIO.cs | 134 - src/Pixeval/Objects/Primitive/Reflection.cs | 44 - src/Pixeval/Objects/Primitive/Strings.cs | 103 - src/Pixeval/Objects/Primitive/UIHelper.cs | 243 -- .../BoolToCachingPolicyConverter.cs | 40 - .../ValueConverters/DateTimeConverter.cs | 41 - .../DateTimeOffsetConverter.cs | 41 - .../DoubleToPercentConverter.cs | 41 - .../ValueConverters/EnumToStringConverter.cs | 49 - .../IllustSubscriptConverter.cs | 46 - ...IllustrationMatchConditionMaskConverter.cs | 44 - .../InverseBooleanConverter.cs | 39 - .../ValueConverters/MultiCultureConverter.cs | 45 - .../ValueConverters/NumericConverter.cs | 55 - .../QueryR18ToggleButtonIsCheckedConverter.cs | 47 - .../ValueConverters/StringSplitConverter.cs | 42 - .../TagMatchEnumToModelConverter.cs | 51 - .../ValueConverters/TrendsStatConverter.cs | 51 - .../ValueConverters/VisibilityConverter.cs | 93 - src/Pixeval/Objects/Web/HttpsProxyServer.cs | 148 - src/Pixeval/Objects/Web/PacFileServer.cs | 36 - src/Pixeval/Persisting/Authentication.cs | 193 -- src/Pixeval/Persisting/Session.cs | 232 -- src/Pixeval/Persisting/Settings.cs | 159 -- .../WebApi/BypassProxyRequestHandler.cs | 41 - .../BypassProxyResourceRequestHandler.cs | 40 - .../Persisting/WebApi/CertificateManager.cs | 133 - src/Pixeval/Pixeval.csproj | 78 - src/Pixeval/Properties/Annotations.cs | 1461 ---------- src/Pixeval/Properties/launchSettings.json | 7 - src/Pixeval/Resources/dqueue.ttf | Bin 8028 -> 0 bytes src/Pixeval/Resources/iconfont.ttf | Bin 16276 -> 0 bytes src/Pixeval/Resources/iconfontex.ttf | Bin 1992 -> 0 bytes src/Pixeval/Resources/interchange.zip | Bin 78811 -> 0 bytes src/Pixeval/Resources/logo-only.svg | 1216 --------- src/Pixeval/Resources/pixeval_ca.cer | Bin 982 -> 0 bytes src/Pixeval/Resources/pixeval_server_cert.pfx | Bin 3758 -> 0 bytes src/Pixeval/Resources/pxlogo.ico | Bin 209762 -> 0 bytes src/Pixeval/Resources/saucenao.png | Bin 5599 -> 0 bytes src/Pixeval/UI/MainWindow.xaml | 2382 ----------------- src/Pixeval/UI/MainWindow.xaml.cs | 1075 -------- src/Pixeval/UI/SignIn.xaml | 153 -- src/Pixeval/UI/SignIn.xaml.cs | 106 - .../UI/UserControls/DownloadQueue.xaml | 423 --- .../UI/UserControls/DownloadQueue.xaml.cs | 157 -- .../UI/UserControls/IllustPresenter.xaml | 102 - .../UI/UserControls/IllustPresenter.xaml.cs | 162 -- .../UI/UserControls/IllustTransitioner.xaml | 35 - .../UserControls/IllustTransitioner.xaml.cs | 41 - .../UI/UserControls/InputBoxControl.xaml | 48 - .../UI/UserControls/InputBoxControl.xaml.cs | 40 - .../UI/UserControls/PixevalSettingPage.xaml | 274 -- .../UserControls/PixevalSettingPage.xaml.cs | 91 - .../UI/UserControls/SauceNAOHomePage.xaml | 84 - .../UI/UserControls/SauceNAOHomePage.xaml.cs | 115 - .../UI/UserControls/TrendingTagControl.xaml | 132 - .../UserControls/TrendingTagControl.xaml.cs | 63 - .../UserControls/UserPreviewPopupContent.xaml | 155 -- .../UserPreviewPopupContent.xaml.cs | 65 - src/Pixeval/app.manifest | 76 - src/Pixeval/build.ps1 | 1 - .../6.1/executionHistory/executionHistory.bin | Bin 111278 -> 0 bytes .../executionHistory/executionHistory.lock | Bin 17 -> 0 bytes .../.gradle/6.1/fileChanges/last-build.bin | Bin 1 -> 0 bytes .../.gradle/6.1/fileContent/fileContent.lock | Bin 17 -> 0 bytes .../.gradle/6.1/fileHashes/fileHashes.bin | Bin 20847 -> 0 bytes .../.gradle/6.1/fileHashes/fileHashes.lock | Bin 17 -> 0 bytes src/pixeval-backend/.gradle/6.1/gc.properties | 0 .../buildOutputCleanup.lock | Bin 17 -> 0 bytes .../buildOutputCleanup/cache.properties | 2 - .../buildOutputCleanup/outputFiles.bin | Bin 18839 -> 0 bytes .../.gradle/checksums/checksums.lock | Bin 17 -> 0 bytes .../.gradle/checksums/md5-checksums.bin | Bin 22497 -> 0 bytes .../.gradle/checksums/sha1-checksums.bin | Bin 33779 -> 0 bytes .../.gradle/vcs-1/gc.properties | 0 .../.idea/codeStyles/Project.xml | 13 - .../.idea/codeStyles/codeStyleConfig.xml | 5 - src/pixeval-backend/.idea/compiler.xml | 6 - .../.idea/dictionaries/26532.xml | 7 - src/pixeval-backend/.idea/gradle.xml | 18 - src/pixeval-backend/.idea/jarRepositories.xml | 20 - src/pixeval-backend/.idea/misc.xml | 10 - src/pixeval-backend/.idea/workspace.xml | 313 --- src/pixeval-backend/build.gradle | 39 - .../META-INF/pixeval-backend.kotlin_module | Bin 70 -> 0 bytes .../main/io/pixeval/statistics/Asset.class | Bin 8376 -> 0 bytes .../main/io/pixeval/statistics/Author.class | Bin 10810 -> 0 bytes .../io/pixeval/statistics/GithubRelease.class | Bin 11625 -> 0 bytes .../pixeval/statistics/GithubReleaseKt.class | Bin 423 -> 0 bytes ...ReleaseTotalDownloads$$inlined$get$1.class | Bin 2304 -> 0 bytes ...ker$getGithubReleaseTotalDownloads$1.class | Bin 2493 -> 0 bytes ...thubReleaseTotalDownloads$client$1$1.class | Bin 1972 -> 0 bytes ...GithubReleaseTotalDownloads$client$1.class | Bin 2283 -> 0 bytes .../io/pixeval/statistics/GithubTracker.class | Bin 12632 -> 0 bytes .../io/pixeval/statistics/ListenerKt.class | Bin 1757 -> 0 bytes .../statistics/helper/Properties.class | Bin 3048 -> 0 bytes .../kotlin/compileKotlin/build-history.bin | Bin 1186 -> 0 bytes .../caches-jvm/inputs/source-to-output.tab | Bin 4096 -> 0 bytes .../inputs/source-to-output.tab.keystream | Bin 4096 -> 0 bytes .../inputs/source-to-output.tab.keystream.len | Bin 8 -> 0 bytes .../inputs/source-to-output.tab.len | Bin 8 -> 0 bytes .../inputs/source-to-output.tab.values.at | Bin 25633 -> 0 bytes .../caches-jvm/inputs/source-to-output.tab_i | Bin 32768 -> 0 bytes .../inputs/source-to-output.tab_i.len | Bin 8 -> 0 bytes .../jvm/kotlin/class-fq-name-to-source.tab | Bin 4096 -> 0 bytes .../class-fq-name-to-source.tab.keystream | Bin 4096 -> 0 bytes .../class-fq-name-to-source.tab.keystream.len | Bin 8 -> 0 bytes .../kotlin/class-fq-name-to-source.tab.len | Bin 8 -> 0 bytes .../class-fq-name-to-source.tab.values.at | Bin 1216 -> 0 bytes .../jvm/kotlin/class-fq-name-to-source.tab_i | Bin 32768 -> 0 bytes .../kotlin/class-fq-name-to-source.tab_i.len | Bin 8 -> 0 bytes .../jvm/kotlin/internal-name-to-source.tab | Bin 4096 -> 0 bytes .../internal-name-to-source.tab.keystream | Bin 4096 -> 0 bytes .../internal-name-to-source.tab.keystream.len | Bin 8 -> 0 bytes .../kotlin/internal-name-to-source.tab.len | Bin 8 -> 0 bytes .../internal-name-to-source.tab.values.at | Bin 17924 -> 0 bytes .../jvm/kotlin/internal-name-to-source.tab_i | Bin 32768 -> 0 bytes .../kotlin/internal-name-to-source.tab_i.len | Bin 8 -> 0 bytes .../caches-jvm/jvm/kotlin/package-parts.tab | Bin 4096 -> 0 bytes .../jvm/kotlin/package-parts.tab.keystream | Bin 4096 -> 0 bytes .../kotlin/package-parts.tab.keystream.len | Bin 8 -> 0 bytes .../jvm/kotlin/package-parts.tab.len | Bin 8 -> 0 bytes .../jvm/kotlin/package-parts.tab.values.at | Bin 115 -> 0 bytes .../caches-jvm/jvm/kotlin/package-parts.tab_i | Bin 32768 -> 0 bytes .../jvm/kotlin/package-parts.tab_i.len | Bin 8 -> 0 bytes .../caches-jvm/jvm/kotlin/proto.tab | Bin 4096 -> 0 bytes .../caches-jvm/jvm/kotlin/proto.tab.keystream | Bin 4096 -> 0 bytes .../jvm/kotlin/proto.tab.keystream.len | Bin 8 -> 0 bytes .../caches-jvm/jvm/kotlin/proto.tab.len | Bin 8 -> 0 bytes .../caches-jvm/jvm/kotlin/proto.tab.values.at | Bin 12571 -> 0 bytes .../caches-jvm/jvm/kotlin/proto.tab_i | Bin 32768 -> 0 bytes .../caches-jvm/jvm/kotlin/proto.tab_i.len | Bin 8 -> 0 bytes .../jvm/kotlin/source-to-classes.tab | Bin 4096 -> 0 bytes .../kotlin/source-to-classes.tab.keystream | Bin 4096 -> 0 bytes .../source-to-classes.tab.keystream.len | Bin 8 -> 0 bytes .../jvm/kotlin/source-to-classes.tab.len | Bin 8 -> 0 bytes .../kotlin/source-to-classes.tab.values.at | Bin 9628 -> 0 bytes .../jvm/kotlin/source-to-classes.tab_i | Bin 32768 -> 0 bytes .../jvm/kotlin/source-to-classes.tab_i.len | Bin 8 -> 0 bytes .../caches-jvm/lookups/counters.tab | 2 - .../caches-jvm/lookups/file-to-id.tab | Bin 4096 -> 0 bytes .../lookups/file-to-id.tab.keystream | Bin 4096 -> 0 bytes .../lookups/file-to-id.tab.keystream.len | Bin 8 -> 0 bytes .../caches-jvm/lookups/file-to-id.tab.len | Bin 8 -> 0 bytes .../lookups/file-to-id.tab.values.at | Bin 199 -> 0 bytes .../caches-jvm/lookups/file-to-id.tab_i | Bin 32768 -> 0 bytes .../caches-jvm/lookups/file-to-id.tab_i.len | Bin 8 -> 0 bytes .../caches-jvm/lookups/id-to-file.tab | Bin 4096 -> 0 bytes .../lookups/id-to-file.tab.keystream | Bin 4096 -> 0 bytes .../lookups/id-to-file.tab.keystream.len | Bin 8 -> 0 bytes .../caches-jvm/lookups/id-to-file.tab.len | Bin 8 -> 0 bytes .../lookups/id-to-file.tab.values.at | Bin 2402 -> 0 bytes .../caches-jvm/lookups/id-to-file.tab_i | Bin 32768 -> 0 bytes .../caches-jvm/lookups/id-to-file.tab_i.len | Bin 8 -> 0 bytes .../caches-jvm/lookups/lookups.tab | Bin 8192 -> 0 bytes .../caches-jvm/lookups/lookups.tab.keystream | Bin 8192 -> 0 bytes .../lookups/lookups.tab.keystream.len | Bin 8 -> 0 bytes .../caches-jvm/lookups/lookups.tab.len | Bin 8 -> 0 bytes .../caches-jvm/lookups/lookups.tab.values.at | Bin 12137 -> 0 bytes .../caches-jvm/lookups/lookups.tab_i | Bin 32768 -> 0 bytes .../caches-jvm/lookups/lookups.tab_i.len | Bin 8 -> 0 bytes .../build/kotlin/compileKotlin/last-build.bin | Bin 81 -> 0 bytes src/pixeval-backend/gradle.properties | 1 - .../gradle/wrapper/gradle-wrapper.jar | Bin 58695 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 - src/pixeval-backend/gradlew | 183 -- src/pixeval-backend/gradlew.bat | 100 - src/pixeval-backend/settings.gradle | 2 - src/pixeval-backend/src/main/java/Main.java | 27 - .../src/main/java/SamInterface.java | 4 - .../io/pixeval/statistics/GithubRelease.kt | 92 - .../io/pixeval/statistics/GithubTracker.kt | 25 - .../kotlin/io/pixeval/statistics/Listener.kt | 49 - .../io/pixeval/statistics/LocalTracker.kt | 26 - .../pixeval/statistics/helper/Properties.kt | 10 - 321 files changed, 156 insertions(+), 25219 deletions(-) create mode 100644 .idea/.idea.Pixeval/.idea/encodings.xml create mode 100644 .idea/.idea.Pixeval/.idea/indexLayout.xml create mode 100644 .idea/.idea.Pixeval/.idea/modules.xml create mode 100644 .idea/.idea.Pixeval/.idea/projectSettingsUpdater.xml rename {src/pixeval-backend => .idea/.idea.Pixeval}/.idea/vcs.xml (63%) create mode 100644 .idea/.idea.Pixeval/riderModule.iml rename {src/Pixeval.Updater => Pixeval.Updater}/App.xaml (100%) rename {src/Pixeval.Updater => Pixeval.Updater}/App.xaml.cs (100%) rename {src/Pixeval.Updater => Pixeval.Updater}/AssemblyInfo.cs (100%) rename {src/Pixeval.Updater => Pixeval.Updater}/ChecksumFailedException.cs (100%) rename {src/Pixeval.Updater => Pixeval.Updater}/Cipher.cs (100%) rename {src/Pixeval.Updater => Pixeval.Updater}/MainWindow.xaml (79%) rename {src/Pixeval.Updater => Pixeval.Updater}/MainWindow.xaml.cs (73%) rename {src/Pixeval.Updater => Pixeval.Updater}/Pixeval.Updater.csproj (100%) rename {src/Pixeval.Updater => Pixeval.Updater}/RelevantURL.cs (100%) rename {src/Pixeval.Updater => Pixeval.Updater}/Resources/pxlogo.ico (100%) rename {src/Pixeval.Updater => Pixeval.Updater}/build.ps1 (100%) rename {src/Pixeval.Updater => Pixeval.Updater}/pxlogo.ico (100%) delete mode 100644 src/Pixeval.Interchange/Pixeval.Interchange.csproj delete mode 100644 src/Pixeval.Interchange/Program.cs delete mode 100644 src/Pixeval.Interchange/Properties/launchSettings.json delete mode 100644 src/Pixeval.Interchange/build.ps1 delete mode 100644 src/Pixeval/Annotations.cs delete mode 100644 src/Pixeval/App.xaml delete mode 100644 src/Pixeval/App.xaml.cs delete mode 100644 src/Pixeval/AppContext.cs delete mode 100644 src/Pixeval/Core/AbstractPixivAsyncEnumerable.cs delete mode 100644 src/Pixeval/Core/AbstractPixivAsyncEnumerator.cs delete mode 100644 src/Pixeval/Core/BrowsingHistoryAccessor.cs delete mode 100644 src/Pixeval/Core/CreateNewFolderForUserDownloadPathProvider.cs delete mode 100644 src/Pixeval/Core/DefaultDownloadPathProvider.cs delete mode 100644 src/Pixeval/Core/DefaultIllustrationFileNameFormatter.cs delete mode 100644 src/Pixeval/Core/EnumeratingSchedule.cs delete mode 100644 src/Pixeval/Core/GalleryAsyncEnumerable.cs delete mode 100644 src/Pixeval/Core/ICancellable.cs delete mode 100644 src/Pixeval/Core/IDownloadPathProvider.cs delete mode 100644 src/Pixeval/Core/IPixivAsyncEnumerable.cs delete mode 100644 src/Pixeval/Core/IQualifier.cs delete mode 100644 src/Pixeval/Core/ITimelineService.cs delete mode 100644 src/Pixeval/Core/IllustrationQualification.cs delete mode 100644 src/Pixeval/Core/IllustrationQualifier.cs delete mode 100644 src/Pixeval/Core/Managers.cs delete mode 100644 src/Pixeval/Core/PixivClient.cs delete mode 100644 src/Pixeval/Core/PixivClientExtension.cs delete mode 100644 src/Pixeval/Core/PixivHelper.cs delete mode 100644 src/Pixeval/Core/PixivIO.cs delete mode 100644 src/Pixeval/Core/PluggableProtocolListener.cs delete mode 100644 src/Pixeval/Core/PluggableProtocolParser.cs delete mode 100644 src/Pixeval/Core/QueryAsyncEnumerable.cs delete mode 100644 src/Pixeval/Core/RankOption.cs delete mode 100644 src/Pixeval/Core/RankingAsyncEnumerable.cs delete mode 100644 src/Pixeval/Core/RecommendAsyncEnumerable.cs delete mode 100644 src/Pixeval/Core/RecommendIllustratorDeferrer.cs delete mode 100644 src/Pixeval/Core/RestrictPolicy.cs delete mode 100644 src/Pixeval/Core/SearchTagMatchOption.cs delete mode 100644 src/Pixeval/Core/SpotlightQueryAsyncEnumerable.cs delete mode 100644 src/Pixeval/Core/TrendsAsyncEnumerable.cs delete mode 100644 src/Pixeval/Core/UploadAsyncEnumerable.cs delete mode 100644 src/Pixeval/Core/UserFollowingAsyncEnumerable.cs delete mode 100644 src/Pixeval/Core/UserPreviewAsyncEnumerable.cs delete mode 100644 src/Pixeval/Core/UserUpdateAsyncEnumerable.cs delete mode 100644 src/Pixeval/Core/WindowsUserActivityManager.cs delete mode 100644 src/Pixeval/Data/IParser.cs delete mode 100644 src/Pixeval/Data/ViewModel/AutoCompletion.cs delete mode 100644 src/Pixeval/Data/ViewModel/BrowsingHistory.cs delete mode 100644 src/Pixeval/Data/ViewModel/ConditionString.cs delete mode 100644 src/Pixeval/Data/ViewModel/DownloadableIllustration.cs delete mode 100644 src/Pixeval/Data/ViewModel/I18nOption.cs delete mode 100644 src/Pixeval/Data/ViewModel/Illustration.cs delete mode 100644 src/Pixeval/Data/ViewModel/RankOptionModel.cs delete mode 100644 src/Pixeval/Data/ViewModel/SearchTagMatchOptionModel.cs delete mode 100644 src/Pixeval/Data/ViewModel/SpotlightArticle.cs delete mode 100644 src/Pixeval/Data/ViewModel/TrendingTag.cs delete mode 100644 src/Pixeval/Data/ViewModel/Trends.cs delete mode 100644 src/Pixeval/Data/ViewModel/User.cs delete mode 100644 src/Pixeval/Data/Web/Delegation/DnsResolvedHttpClientHandler.cs delete mode 100644 src/Pixeval/Data/Web/Delegation/DnsResolver.cs delete mode 100644 src/Pixeval/Data/Web/Delegation/HttpClientFactory.cs delete mode 100644 src/Pixeval/Data/Web/Delegation/IHttpRequestHandler.cs delete mode 100644 src/Pixeval/Data/Web/Delegation/PixivApiDnsResolver.cs delete mode 100644 src/Pixeval/Data/Web/Delegation/PixivApiHttpClientHandler.cs delete mode 100644 src/Pixeval/Data/Web/Delegation/PixivAuthenticationHttpRequestHandler.cs delete mode 100644 src/Pixeval/Data/Web/Delegation/PixivImageHttpClientHandler.cs delete mode 100644 src/Pixeval/Data/Web/HttpResponse.cs delete mode 100644 src/Pixeval/Data/Web/Protocol/IAppApiProtocol.cs delete mode 100644 src/Pixeval/Data/Web/Protocol/IResolveDnsProtocol.cs delete mode 100644 src/Pixeval/Data/Web/Protocol/ISauceNAOProtocol.cs delete mode 100644 src/Pixeval/Data/Web/Protocol/ITokenProtocol.cs delete mode 100644 src/Pixeval/Data/Web/Protocol/IWebApiProtocol.cs delete mode 100644 src/Pixeval/Data/Web/ProtocolBase.cs delete mode 100644 src/Pixeval/Data/Web/Request/AddBookmarkRequest.cs delete mode 100644 src/Pixeval/Data/Web/Request/AutoCompletionRequest.cs delete mode 100644 src/Pixeval/Data/Web/Request/DeleteBookmarkRequest.cs delete mode 100644 src/Pixeval/Data/Web/Request/DnsResolveRequest.cs delete mode 100644 src/Pixeval/Data/Web/Request/FollowArtistRequest.cs delete mode 100644 src/Pixeval/Data/Web/Request/PasswordTokenRequest.cs delete mode 100644 src/Pixeval/Data/Web/Request/RecommendIllustratorRequest.cs delete mode 100644 src/Pixeval/Data/Web/Request/RefreshTokenRequest.cs delete mode 100644 src/Pixeval/Data/Web/Request/ToggleR18StateRequest.cs delete mode 100644 src/Pixeval/Data/Web/Request/UnFollowArtistRequest.cs delete mode 100644 src/Pixeval/Data/Web/Request/UserInformationRequest.cs delete mode 100644 src/Pixeval/Data/Web/Response/AutoCompletionResponse.cs delete mode 100644 src/Pixeval/Data/Web/Response/DnsResolveResponse.cs delete mode 100644 src/Pixeval/Data/Web/Response/FollowingResponse.cs delete mode 100644 src/Pixeval/Data/Web/Response/GalleryResponse.cs delete mode 100644 src/Pixeval/Data/Web/Response/QueryWorksResponse.cs delete mode 100644 src/Pixeval/Data/Web/Response/RankingResponse.cs delete mode 100644 src/Pixeval/Data/Web/Response/RecommendIllustratorResponse.cs delete mode 100644 src/Pixeval/Data/Web/Response/RecommendResponse.cs delete mode 100644 src/Pixeval/Data/Web/Response/SingleWorkResponse.cs delete mode 100644 src/Pixeval/Data/Web/Response/SpotlightArticleResponse.cs delete mode 100644 src/Pixeval/Data/Web/Response/SpotlightResponse.cs delete mode 100644 src/Pixeval/Data/Web/Response/TokenResponse.cs delete mode 100644 src/Pixeval/Data/Web/Response/TrendingTagResponse.cs delete mode 100644 src/Pixeval/Data/Web/Response/UgoiraMetadataResponse.cs delete mode 100644 src/Pixeval/Data/Web/Response/UploadResponse.cs delete mode 100644 src/Pixeval/Data/Web/Response/UserInformationResponse.cs delete mode 100644 src/Pixeval/Data/Web/Response/UserNavResponse.cs delete mode 100644 src/Pixeval/Data/Web/Response/UserUpdateResponse.cs delete mode 100644 src/Pixeval/Data/Web/Response/WebApiUserDetailResponse.cs delete mode 100644 src/Pixeval/FodyWeavers.xml delete mode 100644 src/Pixeval/FodyWeavers.xsd delete mode 100644 src/Pixeval/Objects/Caching/CachingPolicy.cs delete mode 100644 src/Pixeval/Objects/Caching/FileCache.cs delete mode 100644 src/Pixeval/Objects/Caching/IWeakCacheProvider.cs delete mode 100644 src/Pixeval/Objects/Caching/MemoryCache.cs delete mode 100644 src/Pixeval/Objects/Caching/WeakEntry.cs delete mode 100644 src/Pixeval/Objects/Exceptions/AttributeNotFoundException.cs delete mode 100644 src/Pixeval/Objects/Exceptions/AuthenticateFailedException.cs delete mode 100644 src/Pixeval/Objects/Exceptions/Logger/ExceptionDumper.cs delete mode 100644 src/Pixeval/Objects/Exceptions/QueryNotRespondingException.cs delete mode 100644 src/Pixeval/Objects/Exceptions/TokenNotFoundException.cs delete mode 100644 src/Pixeval/Objects/Exceptions/TypeMismatchException.cs delete mode 100644 src/Pixeval/Objects/Generic/Enumerates.cs delete mode 100644 src/Pixeval/Objects/Generic/Functions.cs delete mode 100644 src/Pixeval/Objects/Generic/Observable.cs delete mode 100644 src/Pixeval/Objects/Generic/Tasks.cs delete mode 100644 src/Pixeval/Objects/I18n/ResourceLocator.cs delete mode 100644 src/Pixeval/Objects/I18n/StringResources.cs delete mode 100644 src/Pixeval/Objects/I18n/Xml/resx_en-us.xml delete mode 100644 src/Pixeval/Objects/I18n/Xml/resx_zh-cn.xml delete mode 100644 src/Pixeval/Objects/Native/WallpaperManager.cs delete mode 100644 src/Pixeval/Objects/Primitive/Attributes.cs delete mode 100644 src/Pixeval/Objects/Primitive/InternalIO.cs delete mode 100644 src/Pixeval/Objects/Primitive/Reflection.cs delete mode 100644 src/Pixeval/Objects/Primitive/Strings.cs delete mode 100644 src/Pixeval/Objects/Primitive/UIHelper.cs delete mode 100644 src/Pixeval/Objects/ValueConverters/BoolToCachingPolicyConverter.cs delete mode 100644 src/Pixeval/Objects/ValueConverters/DateTimeConverter.cs delete mode 100644 src/Pixeval/Objects/ValueConverters/DateTimeOffsetConverter.cs delete mode 100644 src/Pixeval/Objects/ValueConverters/DoubleToPercentConverter.cs delete mode 100644 src/Pixeval/Objects/ValueConverters/EnumToStringConverter.cs delete mode 100644 src/Pixeval/Objects/ValueConverters/IllustSubscriptConverter.cs delete mode 100644 src/Pixeval/Objects/ValueConverters/IllustrationMatchConditionMaskConverter.cs delete mode 100644 src/Pixeval/Objects/ValueConverters/InverseBooleanConverter.cs delete mode 100644 src/Pixeval/Objects/ValueConverters/MultiCultureConverter.cs delete mode 100644 src/Pixeval/Objects/ValueConverters/NumericConverter.cs delete mode 100644 src/Pixeval/Objects/ValueConverters/QueryR18ToggleButtonIsCheckedConverter.cs delete mode 100644 src/Pixeval/Objects/ValueConverters/StringSplitConverter.cs delete mode 100644 src/Pixeval/Objects/ValueConverters/TagMatchEnumToModelConverter.cs delete mode 100644 src/Pixeval/Objects/ValueConverters/TrendsStatConverter.cs delete mode 100644 src/Pixeval/Objects/ValueConverters/VisibilityConverter.cs delete mode 100644 src/Pixeval/Objects/Web/HttpsProxyServer.cs delete mode 100644 src/Pixeval/Objects/Web/PacFileServer.cs delete mode 100644 src/Pixeval/Persisting/Authentication.cs delete mode 100644 src/Pixeval/Persisting/Session.cs delete mode 100644 src/Pixeval/Persisting/Settings.cs delete mode 100644 src/Pixeval/Persisting/WebApi/BypassProxyRequestHandler.cs delete mode 100644 src/Pixeval/Persisting/WebApi/BypassProxyResourceRequestHandler.cs delete mode 100644 src/Pixeval/Persisting/WebApi/CertificateManager.cs delete mode 100644 src/Pixeval/Pixeval.csproj delete mode 100644 src/Pixeval/Properties/Annotations.cs delete mode 100644 src/Pixeval/Properties/launchSettings.json delete mode 100644 src/Pixeval/Resources/dqueue.ttf delete mode 100644 src/Pixeval/Resources/iconfont.ttf delete mode 100644 src/Pixeval/Resources/iconfontex.ttf delete mode 100644 src/Pixeval/Resources/interchange.zip delete mode 100644 src/Pixeval/Resources/logo-only.svg delete mode 100644 src/Pixeval/Resources/pixeval_ca.cer delete mode 100644 src/Pixeval/Resources/pixeval_server_cert.pfx delete mode 100644 src/Pixeval/Resources/pxlogo.ico delete mode 100644 src/Pixeval/Resources/saucenao.png delete mode 100644 src/Pixeval/UI/MainWindow.xaml delete mode 100644 src/Pixeval/UI/MainWindow.xaml.cs delete mode 100644 src/Pixeval/UI/SignIn.xaml delete mode 100644 src/Pixeval/UI/SignIn.xaml.cs delete mode 100644 src/Pixeval/UI/UserControls/DownloadQueue.xaml delete mode 100644 src/Pixeval/UI/UserControls/DownloadQueue.xaml.cs delete mode 100644 src/Pixeval/UI/UserControls/IllustPresenter.xaml delete mode 100644 src/Pixeval/UI/UserControls/IllustPresenter.xaml.cs delete mode 100644 src/Pixeval/UI/UserControls/IllustTransitioner.xaml delete mode 100644 src/Pixeval/UI/UserControls/IllustTransitioner.xaml.cs delete mode 100644 src/Pixeval/UI/UserControls/InputBoxControl.xaml delete mode 100644 src/Pixeval/UI/UserControls/InputBoxControl.xaml.cs delete mode 100644 src/Pixeval/UI/UserControls/PixevalSettingPage.xaml delete mode 100644 src/Pixeval/UI/UserControls/PixevalSettingPage.xaml.cs delete mode 100644 src/Pixeval/UI/UserControls/SauceNAOHomePage.xaml delete mode 100644 src/Pixeval/UI/UserControls/SauceNAOHomePage.xaml.cs delete mode 100644 src/Pixeval/UI/UserControls/TrendingTagControl.xaml delete mode 100644 src/Pixeval/UI/UserControls/TrendingTagControl.xaml.cs delete mode 100644 src/Pixeval/UI/UserControls/UserPreviewPopupContent.xaml delete mode 100644 src/Pixeval/UI/UserControls/UserPreviewPopupContent.xaml.cs delete mode 100644 src/Pixeval/app.manifest delete mode 100644 src/Pixeval/build.ps1 delete mode 100644 src/pixeval-backend/.gradle/6.1/executionHistory/executionHistory.bin delete mode 100644 src/pixeval-backend/.gradle/6.1/executionHistory/executionHistory.lock delete mode 100644 src/pixeval-backend/.gradle/6.1/fileChanges/last-build.bin delete mode 100644 src/pixeval-backend/.gradle/6.1/fileContent/fileContent.lock delete mode 100644 src/pixeval-backend/.gradle/6.1/fileHashes/fileHashes.bin delete mode 100644 src/pixeval-backend/.gradle/6.1/fileHashes/fileHashes.lock delete mode 100644 src/pixeval-backend/.gradle/6.1/gc.properties delete mode 100644 src/pixeval-backend/.gradle/buildOutputCleanup/buildOutputCleanup.lock delete mode 100644 src/pixeval-backend/.gradle/buildOutputCleanup/cache.properties delete mode 100644 src/pixeval-backend/.gradle/buildOutputCleanup/outputFiles.bin delete mode 100644 src/pixeval-backend/.gradle/checksums/checksums.lock delete mode 100644 src/pixeval-backend/.gradle/checksums/md5-checksums.bin delete mode 100644 src/pixeval-backend/.gradle/checksums/sha1-checksums.bin delete mode 100644 src/pixeval-backend/.gradle/vcs-1/gc.properties delete mode 100644 src/pixeval-backend/.idea/codeStyles/Project.xml delete mode 100644 src/pixeval-backend/.idea/codeStyles/codeStyleConfig.xml delete mode 100644 src/pixeval-backend/.idea/compiler.xml delete mode 100644 src/pixeval-backend/.idea/dictionaries/26532.xml delete mode 100644 src/pixeval-backend/.idea/gradle.xml delete mode 100644 src/pixeval-backend/.idea/jarRepositories.xml delete mode 100644 src/pixeval-backend/.idea/misc.xml delete mode 100644 src/pixeval-backend/.idea/workspace.xml delete mode 100644 src/pixeval-backend/build.gradle delete mode 100644 src/pixeval-backend/build/classes/kotlin/main/META-INF/pixeval-backend.kotlin_module delete mode 100644 src/pixeval-backend/build/classes/kotlin/main/io/pixeval/statistics/Asset.class delete mode 100644 src/pixeval-backend/build/classes/kotlin/main/io/pixeval/statistics/Author.class delete mode 100644 src/pixeval-backend/build/classes/kotlin/main/io/pixeval/statistics/GithubRelease.class delete mode 100644 src/pixeval-backend/build/classes/kotlin/main/io/pixeval/statistics/GithubReleaseKt.class delete mode 100644 src/pixeval-backend/build/classes/kotlin/main/io/pixeval/statistics/GithubTracker$getGithubReleaseTotalDownloads$$inlined$get$1.class delete mode 100644 src/pixeval-backend/build/classes/kotlin/main/io/pixeval/statistics/GithubTracker$getGithubReleaseTotalDownloads$1.class delete mode 100644 src/pixeval-backend/build/classes/kotlin/main/io/pixeval/statistics/GithubTracker$getGithubReleaseTotalDownloads$client$1$1.class delete mode 100644 src/pixeval-backend/build/classes/kotlin/main/io/pixeval/statistics/GithubTracker$getGithubReleaseTotalDownloads$client$1.class delete mode 100644 src/pixeval-backend/build/classes/kotlin/main/io/pixeval/statistics/GithubTracker.class delete mode 100644 src/pixeval-backend/build/classes/kotlin/main/io/pixeval/statistics/ListenerKt.class delete mode 100644 src/pixeval-backend/build/classes/kotlin/main/io/pixeval/statistics/helper/Properties.class delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/build-history.bin delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/inputs/source-to-output.tab delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/inputs/source-to-output.tab.keystream delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/inputs/source-to-output.tab.keystream.len delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/inputs/source-to-output.tab.len delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/inputs/source-to-output.tab.values.at delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/inputs/source-to-output.tab_i delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/inputs/source-to-output.tab_i.len delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i.len delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/internal-name-to-source.tab delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i.len delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/package-parts.tab delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/package-parts.tab.keystream delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/package-parts.tab.keystream.len delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/package-parts.tab.len delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/package-parts.tab.values.at delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/package-parts.tab_i delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/package-parts.tab_i.len delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/proto.tab delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/proto.tab.keystream delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/proto.tab.keystream.len delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/proto.tab.len delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/proto.tab.values.at delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/proto.tab_i delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/proto.tab_i.len delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/source-to-classes.tab delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/source-to-classes.tab.len delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/source-to-classes.tab_i delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/source-to-classes.tab_i.len delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/lookups/counters.tab delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/lookups/file-to-id.tab delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/lookups/file-to-id.tab.keystream delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/lookups/file-to-id.tab.keystream.len delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/lookups/file-to-id.tab.len delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/lookups/file-to-id.tab.values.at delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/lookups/file-to-id.tab_i delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/lookups/file-to-id.tab_i.len delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/lookups/id-to-file.tab delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/lookups/id-to-file.tab.keystream delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/lookups/id-to-file.tab.keystream.len delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/lookups/id-to-file.tab.len delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/lookups/id-to-file.tab.values.at delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/lookups/id-to-file.tab_i delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/lookups/id-to-file.tab_i.len delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/lookups/lookups.tab delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/lookups/lookups.tab.keystream delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/lookups/lookups.tab.keystream.len delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/lookups/lookups.tab.len delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/lookups/lookups.tab.values.at delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/lookups/lookups.tab_i delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/caches-jvm/lookups/lookups.tab_i.len delete mode 100644 src/pixeval-backend/build/kotlin/compileKotlin/last-build.bin delete mode 100644 src/pixeval-backend/gradle.properties delete mode 100644 src/pixeval-backend/gradle/wrapper/gradle-wrapper.jar delete mode 100644 src/pixeval-backend/gradle/wrapper/gradle-wrapper.properties delete mode 100644 src/pixeval-backend/gradlew delete mode 100644 src/pixeval-backend/gradlew.bat delete mode 100644 src/pixeval-backend/settings.gradle delete mode 100644 src/pixeval-backend/src/main/java/Main.java delete mode 100644 src/pixeval-backend/src/main/java/SamInterface.java delete mode 100644 src/pixeval-backend/src/main/kotlin/io/pixeval/statistics/GithubRelease.kt delete mode 100644 src/pixeval-backend/src/main/kotlin/io/pixeval/statistics/GithubTracker.kt delete mode 100644 src/pixeval-backend/src/main/kotlin/io/pixeval/statistics/Listener.kt delete mode 100644 src/pixeval-backend/src/main/kotlin/io/pixeval/statistics/LocalTracker.kt delete mode 100644 src/pixeval-backend/src/main/kotlin/io/pixeval/statistics/helper/Properties.kt diff --git a/.idea/.idea.Pixeval/.idea/encodings.xml b/.idea/.idea.Pixeval/.idea/encodings.xml new file mode 100644 index 00000000..df87cf95 --- /dev/null +++ b/.idea/.idea.Pixeval/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/.idea.Pixeval/.idea/indexLayout.xml b/.idea/.idea.Pixeval/.idea/indexLayout.xml new file mode 100644 index 00000000..27ba142e --- /dev/null +++ b/.idea/.idea.Pixeval/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.Pixeval/.idea/modules.xml b/.idea/.idea.Pixeval/.idea/modules.xml new file mode 100644 index 00000000..f475b6b6 --- /dev/null +++ b/.idea/.idea.Pixeval/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.Pixeval/.idea/projectSettingsUpdater.xml b/.idea/.idea.Pixeval/.idea/projectSettingsUpdater.xml new file mode 100644 index 00000000..7515e760 --- /dev/null +++ b/.idea/.idea.Pixeval/.idea/projectSettingsUpdater.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/src/pixeval-backend/.idea/vcs.xml b/.idea/.idea.Pixeval/.idea/vcs.xml similarity index 63% rename from src/pixeval-backend/.idea/vcs.xml rename to .idea/.idea.Pixeval/.idea/vcs.xml index b2bdec2d..94a25f7f 100644 --- a/src/pixeval-backend/.idea/vcs.xml +++ b/.idea/.idea.Pixeval/.idea/vcs.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/.idea/.idea.Pixeval/riderModule.iml b/.idea/.idea.Pixeval/riderModule.iml new file mode 100644 index 00000000..efa96e05 --- /dev/null +++ b/.idea/.idea.Pixeval/riderModule.iml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Pixeval.Updater/App.xaml b/Pixeval.Updater/App.xaml similarity index 100% rename from src/Pixeval.Updater/App.xaml rename to Pixeval.Updater/App.xaml diff --git a/src/Pixeval.Updater/App.xaml.cs b/Pixeval.Updater/App.xaml.cs similarity index 100% rename from src/Pixeval.Updater/App.xaml.cs rename to Pixeval.Updater/App.xaml.cs diff --git a/src/Pixeval.Updater/AssemblyInfo.cs b/Pixeval.Updater/AssemblyInfo.cs similarity index 100% rename from src/Pixeval.Updater/AssemblyInfo.cs rename to Pixeval.Updater/AssemblyInfo.cs diff --git a/src/Pixeval.Updater/ChecksumFailedException.cs b/Pixeval.Updater/ChecksumFailedException.cs similarity index 100% rename from src/Pixeval.Updater/ChecksumFailedException.cs rename to Pixeval.Updater/ChecksumFailedException.cs diff --git a/src/Pixeval.Updater/Cipher.cs b/Pixeval.Updater/Cipher.cs similarity index 100% rename from src/Pixeval.Updater/Cipher.cs rename to Pixeval.Updater/Cipher.cs diff --git a/src/Pixeval.Updater/MainWindow.xaml b/Pixeval.Updater/MainWindow.xaml similarity index 79% rename from src/Pixeval.Updater/MainWindow.xaml rename to Pixeval.Updater/MainWindow.xaml index bbd8c58b..a3ce51aa 100644 --- a/src/Pixeval.Updater/MainWindow.xaml +++ b/Pixeval.Updater/MainWindow.xaml @@ -1,9 +1,17 @@ - + xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" + Title="MainWindow" + Width="600" + Height="100" + AllowsTransparency="True" + Background="Transparent" + Icon="Resources/pxlogo.ico" + Loaded="MainWindow_OnLoaded" + MouseDown="MainWindow_OnMouseDown" + ResizeMode="NoResize" + WindowStyle="None"> - + - - - + - + - + \ No newline at end of file diff --git a/src/Pixeval.Updater/MainWindow.xaml.cs b/Pixeval.Updater/MainWindow.xaml.cs similarity index 73% rename from src/Pixeval.Updater/MainWindow.xaml.cs rename to Pixeval.Updater/MainWindow.xaml.cs index 8e5cc12c..10341aee 100644 --- a/src/Pixeval.Updater/MainWindow.xaml.cs +++ b/Pixeval.Updater/MainWindow.xaml.cs @@ -40,20 +40,23 @@ namespace Pixeval.Updater /// public partial class MainWindow { - private static readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource(); + private static readonly CancellationTokenSource CancellationTokenSource = new CancellationTokenSource(); - private static readonly string _currentDir = Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase!).LocalPath); + private static readonly string CurrentDir = Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase!).LocalPath); - private static readonly DirectoryInfo _pixevalDirectory = Directory.GetParent(_currentDir); + private static readonly DirectoryInfo PixevalDirectory = Directory.GetParent(CurrentDir); - private static readonly string _zipTmpPath = Path.Combine(_pixevalDirectory.FullName, "Pixeval.zip"); + private static readonly string ZipTmpPath = Path.Combine(PixevalDirectory.FullName, "Pixeval.zip"); - private static readonly string _extractedTmpPath = Path.Combine(_pixevalDirectory.FullName, "Pixeval"); + private static readonly string ExtractedTmpPath = Path.Combine(PixevalDirectory.FullName, "Pixeval"); public MainWindow() { InitializeComponent(); - if (!CheckIsPixevalDirectory(_pixevalDirectory)) Exit("Pixeval更新器必须位于Pixeval目录中"); + if (!CheckIsPixevalDirectory(PixevalDirectory)) + { + Exit("Pixeval更新器必须位于Pixeval目录中"); + } } private void MainWindow_OnMouseDown(object sender, MouseButtonEventArgs e) @@ -65,7 +68,7 @@ namespace Pixeval.Updater { try { - await using var memory = await Download(RelevantUrl.ZipArchive, new Progress(p => DownloadProgressIndicator.Value = p), _cancellationTokenSource.Token); + await using var memory = await Download(RelevantUrl.ZipArchive, new Progress(p => DownloadProgressIndicator.Value = p), CancellationTokenSource.Token); memory.Position = 0L; if (memory.Checksum() != (await GetRemoteChecksum()).ToLower()) { @@ -74,17 +77,17 @@ namespace Pixeval.Updater } RmFiles(); - await using (var fileStream = new FileStream(_zipTmpPath, FileMode.Create, FileAccess.ReadWrite, FileShare.None)) + await using (var fileStream = new FileStream(ZipTmpPath, FileMode.Create, FileAccess.ReadWrite, FileShare.None)) { memory.WriteTo(fileStream); } Extract(); - File.Delete(_zipTmpPath); - Directory.Delete(Path.Combine(_extractedTmpPath, "updater"), true); - FileSystem.CopyDirectory(_extractedTmpPath, _pixevalDirectory.FullName); - Directory.Delete(_extractedTmpPath, true); - Process.Start(Path.Combine(_pixevalDirectory.FullName, "Pixeval.exe")); + File.Delete(ZipTmpPath); + Directory.Delete(Path.Combine(ExtractedTmpPath, "updater"), true); + FileSystem.CopyDirectory(ExtractedTmpPath, PixevalDirectory.FullName); + Directory.Delete(ExtractedTmpPath, true); + Process.Start(Path.Combine(PixevalDirectory.FullName, "Pixeval.exe")); Exit(); } catch (TaskCanceledException) @@ -104,22 +107,31 @@ namespace Pixeval.Updater private static void RmFiles() { - var rmList = _pixevalDirectory.GetFileSystemInfos().Where(fs => fs.FullName != _currentDir); + var rmList = PixevalDirectory.GetFileSystemInfos().Where(fs => fs.FullName != CurrentDir); foreach (var fileSystemInfo in rmList) + { if (File.GetAttributes(fileSystemInfo.FullName).HasFlag(FileAttributes.Directory)) + { Directory.Delete(fileSystemInfo.FullName, true); + } else + { fileSystemInfo.Delete(); + } + } } private static void Extract() { - ZipFile.ExtractToDirectory(_zipTmpPath, _pixevalDirectory.FullName); + ZipFile.ExtractToDirectory(ZipTmpPath, PixevalDirectory.FullName); } private void Exit(string message = null) { - if (message != null) MessageBox.Show(message); + if (message != null) + { + MessageBox.Show(message); + } Close(); Environment.Exit(0); @@ -132,7 +144,7 @@ namespace Pixeval.Updater private void CancelButton_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { - _cancellationTokenSource.Cancel(); + CancellationTokenSource.Cancel(); } private static bool CheckIsPixevalDirectory(DirectoryInfo dir) @@ -145,7 +157,10 @@ namespace Pixeval.Updater using var response = await GetResponseHeader(new HttpClient(), url); var contentLength = response.Content.Headers.ContentLength; - if (!contentLength.HasValue) throw new InvalidOperationException("cannot retrieve the content length of the request uri"); + if (!contentLength.HasValue) + { + throw new InvalidOperationException("cannot retrieve the content length of the request uri"); + } response.EnsureSuccessStatusCode(); diff --git a/src/Pixeval.Updater/Pixeval.Updater.csproj b/Pixeval.Updater/Pixeval.Updater.csproj similarity index 100% rename from src/Pixeval.Updater/Pixeval.Updater.csproj rename to Pixeval.Updater/Pixeval.Updater.csproj diff --git a/src/Pixeval.Updater/RelevantURL.cs b/Pixeval.Updater/RelevantURL.cs similarity index 100% rename from src/Pixeval.Updater/RelevantURL.cs rename to Pixeval.Updater/RelevantURL.cs diff --git a/src/Pixeval.Updater/Resources/pxlogo.ico b/Pixeval.Updater/Resources/pxlogo.ico similarity index 100% rename from src/Pixeval.Updater/Resources/pxlogo.ico rename to Pixeval.Updater/Resources/pxlogo.ico diff --git a/src/Pixeval.Updater/build.ps1 b/Pixeval.Updater/build.ps1 similarity index 100% rename from src/Pixeval.Updater/build.ps1 rename to Pixeval.Updater/build.ps1 diff --git a/src/Pixeval.Updater/pxlogo.ico b/Pixeval.Updater/pxlogo.ico similarity index 100% rename from src/Pixeval.Updater/pxlogo.ico rename to Pixeval.Updater/pxlogo.ico diff --git a/Pixeval.sln b/Pixeval.sln index 5f74ff59..2254de47 100644 --- a/Pixeval.sln +++ b/Pixeval.sln @@ -3,11 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.30104.148 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pixeval", "src\Pixeval\Pixeval.csproj", "{3F5E9BB6-B8F1-453F-89E9-F719342D1E16}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pixeval", "Pixeval\Pixeval.csproj", "{3F5E9BB6-B8F1-453F-89E9-F719342D1E16}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pixeval.Updater", "src\Pixeval.Updater\Pixeval.Updater.csproj", "{D328EB05-39B1-46A9-B874-113F362DD589}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pixeval.Interchange", "src\Pixeval.Interchange\Pixeval.Interchange.csproj", "{AF5AF2B2-4C1D-4103-AA97-D219C4768564}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pixeval.Updater", "Pixeval.Updater\Pixeval.Updater.csproj", "{D328EB05-39B1-46A9-B874-113F362DD589}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{D044DAED-2EF7-43B0-9C75-7714DC021F3B}" EndProject @@ -42,18 +40,6 @@ Global {D328EB05-39B1-46A9-B874-113F362DD589}.Release|x64.Build.0 = Release|Any CPU {D328EB05-39B1-46A9-B874-113F362DD589}.Release|x86.ActiveCfg = Release|Any CPU {D328EB05-39B1-46A9-B874-113F362DD589}.Release|x86.Build.0 = Release|Any CPU - {AF5AF2B2-4C1D-4103-AA97-D219C4768564}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AF5AF2B2-4C1D-4103-AA97-D219C4768564}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AF5AF2B2-4C1D-4103-AA97-D219C4768564}.Debug|x64.ActiveCfg = Debug|Any CPU - {AF5AF2B2-4C1D-4103-AA97-D219C4768564}.Debug|x64.Build.0 = Debug|Any CPU - {AF5AF2B2-4C1D-4103-AA97-D219C4768564}.Debug|x86.ActiveCfg = Debug|Any CPU - {AF5AF2B2-4C1D-4103-AA97-D219C4768564}.Debug|x86.Build.0 = Debug|Any CPU - {AF5AF2B2-4C1D-4103-AA97-D219C4768564}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AF5AF2B2-4C1D-4103-AA97-D219C4768564}.Release|Any CPU.Build.0 = Release|Any CPU - {AF5AF2B2-4C1D-4103-AA97-D219C4768564}.Release|x64.ActiveCfg = Release|Any CPU - {AF5AF2B2-4C1D-4103-AA97-D219C4768564}.Release|x64.Build.0 = Release|Any CPU - {AF5AF2B2-4C1D-4103-AA97-D219C4768564}.Release|x86.ActiveCfg = Release|Any CPU - {AF5AF2B2-4C1D-4103-AA97-D219C4768564}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Pixeval/AppContext.cs b/Pixeval/AppContext.cs index a69ffcbe..8a74fcdb 100644 --- a/Pixeval/AppContext.cs +++ b/Pixeval/AppContext.cs @@ -32,7 +32,7 @@ namespace Pixeval { public const string AppIdentifier = "Pixeval"; - public const string CurrentVersion = "3.0.1"; + public const string CurrentVersion = "3.0.2"; public const string ConfigurationFileName = "pixeval_conf.json"; diff --git a/Pixeval/Pixeval.csproj b/Pixeval/Pixeval.csproj index eaec9e18..51326e58 100644 --- a/Pixeval/Pixeval.csproj +++ b/Pixeval/Pixeval.csproj @@ -18,6 +18,7 @@ Off app.manifest + 3.0.2 diff --git a/src/Pixeval.Interchange/Pixeval.Interchange.csproj b/src/Pixeval.Interchange/Pixeval.Interchange.csproj deleted file mode 100644 index 1fb28590..00000000 --- a/src/Pixeval.Interchange/Pixeval.Interchange.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - - WinExe - netcoreapp3.1 - - - - x64 - - - \ No newline at end of file diff --git a/src/Pixeval.Interchange/Program.cs b/src/Pixeval.Interchange/Program.cs deleted file mode 100644 index 94af2cd0..00000000 --- a/src/Pixeval.Interchange/Program.cs +++ /dev/null @@ -1,61 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Diagnostics; -using System.Linq; -using System.Net.Http; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading.Tasks; - -namespace Pixeval.Interchange -{ - public class Program - { - private const string IllustRegex = "pixeval://(www\\.)?pixiv\\.net/artworks/(?\\d+)"; - private const string UserRegex = "pixeval://(www\\.)?pixiv\\.net/users/(?\\d+)"; - private const string SpotlightRegex = "pixeval://(www\\.)?pixivision\\.net/\\w{2}/a/(?\\d+)"; - - private static readonly HttpClient _httpClient = new HttpClient(); - - public static async Task Main(string[] args) - { - using (_httpClient) - { - if (!args.Any()) return; - var url = args[0]; - // check protocol rationality - if (!(Regex.IsMatch(url, IllustRegex) || Regex.IsMatch(url, UserRegex) || Regex.IsMatch(url, SpotlightRegex))) return; - // check if there's an instance is running - if (PixevalInstanceRunning()) - // send Pixeval custom pluggable protocol if so - await _httpClient.PostAsync("http://127.0.0.1:12547/open", new StringContent(url, Encoding.UTF8)); - else - // otherwise execute Pixeval and pass the protocol as argument - Process.Start("Pixeval", url); - } - } - - private static bool PixevalInstanceRunning() - { - return Process.GetProcessesByName("Pixeval").Length > 0; - } - } -} \ No newline at end of file diff --git a/src/Pixeval.Interchange/Properties/launchSettings.json b/src/Pixeval.Interchange/Properties/launchSettings.json deleted file mode 100644 index 27286de8..00000000 --- a/src/Pixeval.Interchange/Properties/launchSettings.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "profiles": { - "Pixeval.Interchange": { - "commandName": "Project", - "nativeDebugging": false - }, - "newProfile1": { - "commandName": "Executable" - } - } -} \ No newline at end of file diff --git a/src/Pixeval.Interchange/build.ps1 b/src/Pixeval.Interchange/build.ps1 deleted file mode 100644 index 2829d1ed..00000000 --- a/src/Pixeval.Interchange/build.ps1 +++ /dev/null @@ -1 +0,0 @@ -dotnet publish /p:Platform=x64 Pixeval.Interchange.csproj -c Release -f netcoreapp3.1 --no-self-contained -r win-x64 \ No newline at end of file diff --git a/src/Pixeval/Annotations.cs b/src/Pixeval/Annotations.cs deleted file mode 100644 index 69145d10..00000000 --- a/src/Pixeval/Annotations.cs +++ /dev/null @@ -1,1383 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; - -// ReSharper disable InheritdocConsiderUsage - -#pragma warning disable 1591 -// ReSharper disable UnusedMember.Global -// ReSharper disable MemberCanBePrivate.Global -// ReSharper disable UnusedAutoPropertyAccessor.Global -// ReSharper disable IntroduceOptionalParameters.Global -// ReSharper disable MemberCanBeProtected.Global -// ReSharper disable InconsistentNaming - -namespace Pixeval -{ - /// - /// Indicates that the value of the marked element could be null sometimes, - /// so checking for null is required before its usage. - /// - /// - /// - /// [CanBeNull] object Test() => null; - /// - /// void UseTest() { - /// var p = Test(); - /// var s = p.ToString(); // Warning: Possible 'System.NullReferenceException' - /// } - /// - /// - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.GenericParameter)] - public sealed class CanBeNullAttribute : Attribute - { - } - - /// - /// Indicates that the value of the marked element can never be null. - /// - /// - /// - /// [NotNull] object Foo() { - /// return null; // Warning: Possible 'null' assignment - /// } - /// - /// - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.GenericParameter)] - public sealed class NotNullAttribute : Attribute - { - } - - /// - /// Can be applied to symbols of types derived from IEnumerable as well as to symbols of Task - /// and Lazy classes to indicate that the value of a collection item, of the Task.Result property - /// or of the Lazy.Value property can never be null. - /// - /// - /// - /// public void Foo([ItemNotNull]List<string> books) - /// { - /// foreach (var book in books) { - /// if (book != null) // Warning: Expression is always true - /// Console.WriteLine(book.ToUpper()); - /// } - /// } - /// - /// - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Delegate | AttributeTargets.Field)] - public sealed class ItemNotNullAttribute : Attribute - { - } - - /// - /// Can be applied to symbols of types derived from IEnumerable as well as to symbols of Task - /// and Lazy classes to indicate that the value of a collection item, of the Task.Result property - /// or of the Lazy.Value property can be null. - /// - /// - /// - /// public void Foo([ItemCanBeNull]List<string> books) - /// { - /// foreach (var book in books) - /// { - /// // Warning: Possible 'System.NullReferenceException' - /// Console.WriteLine(book.ToUpper()); - /// } - /// } - /// - /// - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Delegate | AttributeTargets.Field)] - public sealed class ItemCanBeNullAttribute : Attribute - { - } - - /// - /// Indicates that the marked method builds string by the format pattern and (optional) arguments. - /// The parameter, which contains the format string, should be given in constructor. The format string - /// should be in -like form. - /// - /// - /// - /// [StringFormatMethod("message")] - /// void ShowError(string message, params object[] args) { /* do something */ } - /// - /// void Foo() { - /// ShowError("Failed: {0}"); // Warning: Non-existing argument in format string - /// } - /// - /// - [AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Delegate)] - public sealed class StringFormatMethodAttribute : Attribute - { - /// - /// Specifies which parameter of an annotated method should be treated as the format string - /// - public StringFormatMethodAttribute([NotNull] - string formatParameterName) - { - FormatParameterName = formatParameterName; - } - - [NotNull] - public string FormatParameterName { get; } - } - - /// - /// Use this annotation to specify a type that contains static or const fields - /// with values for the annotated property/field/parameter. - /// The specified type will be used to improve completion suggestions. - /// - /// - /// - /// namespace TestNamespace - /// { - /// public class Constants - /// { - /// public static int INT_CONST = 1; - /// public const string STRING_CONST = "1"; - /// } - /// - /// public class Class1 - /// { - /// [ValueProvider("TestNamespace.Constants")] public int myField; - /// public void Foo([ValueProvider("TestNamespace.Constants")] string str) { } - /// - /// public void Test() - /// { - /// Foo(/*try completion here*/);// - /// myField = /*try completion here*/ - /// } - /// } - /// } - /// - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)] - public sealed class ValueProviderAttribute : Attribute - { - public ValueProviderAttribute([NotNull] - string name) - { - Name = name; - } - - [NotNull] - public string Name { get; } - } - - /// - /// Indicates that the function argument should be a string literal and match one - /// of the parameters of the caller function. For example, ReSharper annotates - /// the parameter of . - /// - /// - /// - /// void Foo(string param) { - /// if (param == null) - /// throw new ArgumentNullException("par"); // Warning: Cannot resolve symbol - /// } - /// - /// - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class InvokerParameterNameAttribute : Attribute - { - } - - /// - /// Indicates that the method is contained in a type that implements - /// System.ComponentModel.INotifyPropertyChanged interface and this method - /// is used to notify that some property value changed. - /// - /// - /// The method should be non-static and conform to one of the supported signatures: - /// - /// - /// NotifyChanged(string) - /// - /// - /// NotifyChanged(params string[]) - /// - /// - /// NotifyChanged{T}(Expression{Func{T}}) - /// - /// - /// NotifyChanged{T,U}(Expression{Func{T,U}}) - /// - /// - /// SetProperty{T}(ref T, T, string) - /// - /// - /// - /// - /// - /// public class Foo : INotifyPropertyChanged { - /// public event PropertyChangedEventHandler PropertyChanged; - /// - /// [NotifyPropertyChangedInvocator] - /// protected virtual void NotifyChanged(string propertyName) { ... } - /// - /// string _name; - /// - /// public string Name { - /// get { return _name; } - /// set { _name = value; NotifyChanged("LastName"); /* Warning */ } - /// } - /// } - /// - /// Examples of generated notifications: - /// - /// - /// NotifyChanged("Property") - /// - /// - /// NotifyChanged(() => Property) - /// - /// - /// NotifyChanged((VM x) => x.Property) - /// - /// - /// SetProperty(ref myField, value, "Property") - /// - /// - /// - [AttributeUsage(AttributeTargets.Method)] - public sealed class NotifyPropertyChangedInvocatorAttribute : Attribute - { - public NotifyPropertyChangedInvocatorAttribute() - { - } - - public NotifyPropertyChangedInvocatorAttribute([NotNull] - string parameterName) - { - ParameterName = parameterName; - } - - [CanBeNull] - public string ParameterName { get; } - } - - /// - /// Describes dependency between method input and output. - /// - /// - ///

Function Definition Table syntax:

- /// - /// FDT ::= FDTRow [;FDTRow]* - /// FDTRow ::= Input => Output | Output <= Input - /// Input ::= ParameterName: Value [, Input]* - /// Output ::= [ParameterName: Value]* {halt|stop|void|nothing|Value} - /// Value ::= true | false | null | notnull | canbenull - /// - /// If the method has a single input parameter, its name could be omitted.
- /// Using halt (or void/nothing, which is the same) for the method output - /// means that the method doesn't return normally (throws or terminates the process).
- /// Value canbenull is only applicable for output parameters.
- /// You can use multiple [ContractAnnotation] for each FDT row, or use single attribute - /// with rows separated by semicolon. There is no notion of order rows, all rows are checked - /// for applicability and applied per each program state tracked by the analysis engine.
- ///
- /// - /// - /// - /// - /// [ContractAnnotation("=> halt")] - /// public void TerminationMethod() - /// - /// - /// - /// - /// [ContractAnnotation("null <= param:null")] // reverse condition syntax - /// public string GetName(string surname) - /// - /// - /// - /// - /// [ContractAnnotation("s:null => true")] - /// public bool IsNullOrEmpty(string s) // string.IsNullOrEmpty() - /// - /// - /// - /// - /// // A method that returns null if the parameter is null, - /// // and not null if the parameter is not null - /// [ContractAnnotation("null => null; notnull => notnull")] - /// public object Transform(object data) - /// - /// - /// - /// - /// [ContractAnnotation("=> true, result: notnull; => false, result: null")] - /// public bool TryParse(string s, out Person result) - /// - /// - /// - /// - [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] - public sealed class ContractAnnotationAttribute : Attribute - { - public ContractAnnotationAttribute([NotNull] - string contract) : this(contract, false) - { - } - - public ContractAnnotationAttribute([NotNull] - string contract, bool forceFullStates) - { - Contract = contract; - ForceFullStates = forceFullStates; - } - - [NotNull] - public string Contract { get; } - - public bool ForceFullStates { get; } - } - - /// - /// Indicates whether the marked element should be localized. - /// - /// - /// - /// [LocalizationRequiredAttribute(true)] - /// class Foo { - /// string str = "my string"; // Warning: Localizable string - /// } - /// - /// - [AttributeUsage(AttributeTargets.All)] - public sealed class LocalizationRequiredAttribute : Attribute - { - public LocalizationRequiredAttribute() : this(true) - { - } - - public LocalizationRequiredAttribute(bool required) - { - Required = required; - } - - public bool Required { get; } - } - - /// - /// Indicates that the value of the marked type (or its derivatives) - /// cannot be compared using '==' or '!=' operators and Equals() - /// should be used instead. However, using '==' or '!=' for comparison - /// with null is always permitted. - /// - /// - /// - /// [CannotApplyEqualityOperator] - /// class NoEquality { } - /// - /// class UsesNoEquality { - /// void Test() { - /// var ca1 = new NoEquality(); - /// var ca2 = new NoEquality(); - /// if (ca1 != null) { // OK - /// bool condition = ca1 == ca2; // Warning - /// } - /// } - /// } - /// - /// - [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct)] - public sealed class CannotApplyEqualityOperatorAttribute : Attribute - { - } - - /// - /// When applied to a target attribute, specifies a requirement for any type marked - /// with the target attribute to implement or inherit specific type or types. - /// - /// - /// - /// [BaseTypeRequired(typeof(IComponent)] // Specify requirement - /// class ComponentAttribute : Attribute { } - /// - /// [Component] // ComponentAttribute requires implementing IComponent interface - /// class MyComponent : IComponent { } - /// - /// - [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] - [BaseTypeRequired(typeof(Attribute))] - public sealed class BaseTypeRequiredAttribute : Attribute - { - public BaseTypeRequiredAttribute([NotNull] - Type baseType) - { - BaseType = baseType; - } - - [NotNull] - public Type BaseType { get; } - } - - /// - /// Indicates that the marked symbol is used implicitly (e.g. via reflection, in external library), - /// so this symbol will not be reported as unused (as well as by other usage inspections). - /// - [AttributeUsage(AttributeTargets.All)] - public sealed class UsedImplicitlyAttribute : Attribute - { - public UsedImplicitlyAttribute() : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) - { - } - - public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags) : this(useKindFlags, ImplicitUseTargetFlags.Default) - { - } - - public UsedImplicitlyAttribute(ImplicitUseTargetFlags targetFlags) : this(ImplicitUseKindFlags.Default, targetFlags) - { - } - - public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) - { - UseKindFlags = useKindFlags; - TargetFlags = targetFlags; - } - - public ImplicitUseKindFlags UseKindFlags { get; } - - public ImplicitUseTargetFlags TargetFlags { get; } - } - - /// - /// Can be applied to attributes, type parameters, and parameters of a type assignable from - /// . - /// When applied to an attribute, the decorated attribute behaves the same as . - /// When applied to a type parameter or to a parameter of type , indicates that the - /// corresponding type - /// is used implicitly. - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.GenericParameter | AttributeTargets.Parameter)] - public sealed class MeansImplicitUseAttribute : Attribute - { - public MeansImplicitUseAttribute() : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) - { - } - - public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags) : this(useKindFlags, ImplicitUseTargetFlags.Default) - { - } - - public MeansImplicitUseAttribute(ImplicitUseTargetFlags targetFlags) : this(ImplicitUseKindFlags.Default, targetFlags) - { - } - - public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) - { - UseKindFlags = useKindFlags; - TargetFlags = targetFlags; - } - - [UsedImplicitly] - public ImplicitUseKindFlags UseKindFlags { get; } - - [UsedImplicitly] - public ImplicitUseTargetFlags TargetFlags { get; } - } - - /// - /// Specify the details of implicitly used symbol when it is marked - /// with or . - /// - [Flags] - public enum ImplicitUseKindFlags - { - Default = Access | Assign | InstantiatedWithFixedConstructorSignature, - - /// Only entity marked with attribute considered used. - Access = 1, - - /// Indicates implicit assignment to a member. - Assign = 2, - - /// - /// Indicates implicit instantiation of a type with fixed constructor signature. - /// That means any unused constructor parameters won't be reported as such. - /// - InstantiatedWithFixedConstructorSignature = 4, - - /// Indicates implicit instantiation of a type. - InstantiatedNoFixedConstructorSignature = 8 - } - - /// - /// Specify what is considered to be used implicitly when marked - /// with or . - /// - [Flags] - public enum ImplicitUseTargetFlags - { - Default = Itself, Itself = 1, - - /// Members of entity marked with attribute are considered used. - Members = 2, - - /// Entity marked with attribute and all its members considered used. - WithMembers = Itself | Members - } - - /// - /// This attribute is intended to mark publicly available API - /// which should not be removed and so is treated as used. - /// - [MeansImplicitUse(ImplicitUseTargetFlags.WithMembers)] - public sealed class PublicAPIAttribute : Attribute - { - public PublicAPIAttribute() - { - } - - public PublicAPIAttribute([NotNull] - string comment) - { - Comment = comment; - } - - [CanBeNull] - public string Comment { get; } - } - - /// - /// Tells code analysis engine if the parameter is completely handled when the invoked method is on stack. - /// If the parameter is a delegate, indicates that delegate is executed while the method is executed. - /// If the parameter is an enumerable, indicates that it is enumerated while the method is executed. - /// - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class InstantHandleAttribute : Attribute - { - } - - /// - /// Indicates that a method does not make any observable state changes. - /// The same as System.Diagnostics.Contracts.PureAttribute. - /// - /// - /// - /// [Pure] int Multiply(int x, int y) => x * y; - /// - /// void M() { - /// Multiply(123, 42); // Waring: Return value of pure method is not used - /// } - /// - /// - [AttributeUsage(AttributeTargets.Method)] - public sealed class PureAttribute : Attribute - { - } - - /// - /// Indicates that the return value of the method invocation must be used. - /// - /// - /// Methods decorated with this attribute (in contrast to pure methods) might change state, - /// but make no sense without using their return value.
- /// Similarly to , this attribute - /// will help detecting usages of the method when the return value in not used. - /// Additionally, you can optionally specify a custom message, which will be used when showing warnings, e.g. - /// [MustUseReturnValue("Use the return value to...")]. - ///
- [AttributeUsage(AttributeTargets.Method)] - public sealed class MustUseReturnValueAttribute : Attribute - { - public MustUseReturnValueAttribute() - { - } - - public MustUseReturnValueAttribute([NotNull] - string justification) - { - Justification = justification; - } - - [CanBeNull] - public string Justification { get; } - } - - /// - /// Indicates the type member or parameter of some type, that should be used instead of all other ways - /// to get the value of that type. This annotation is useful when you have some "context" value evaluated - /// and stored somewhere, meaning that all other ways to get this value must be consolidated with existing one. - /// - /// - /// - /// class Foo { - /// [ProvidesContext] IBarService _barService = ...; - /// - /// void ProcessNode(INode node) { - /// DoSomething(node, node.GetGlobalServices().Bar); - /// // ^ Warning: use value of '_barService' field - /// } - /// } - /// - /// - [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.GenericParameter)] - public sealed class ProvidesContextAttribute : Attribute - { - } - - /// - /// Indicates that a parameter is a path to a file or a folder within a web project. - /// Path can be relative or absolute, starting from web root (~). - /// - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class PathReferenceAttribute : Attribute - { - public PathReferenceAttribute() - { - } - - public PathReferenceAttribute([NotNull] [PathReference] - string basePath) - { - BasePath = basePath; - } - - [CanBeNull] - public string BasePath { get; } - } - - /// - /// An extension method marked with this attribute is processed by code completion - /// as a 'Source Template'. When the extension method is completed over some expression, its source code - /// is automatically expanded like a template at call site. - /// - /// - /// Template method body can contain valid source code and/or special comments starting with '$'. - /// Text inside these comments is added as source code when the template is applied. Template parameters - /// can be used either as additional method parameters or as identifiers wrapped in two '$' signs. - /// Use the attribute to specify macros for parameters. - /// - /// - /// In this example, the 'forEach' method is a source template available over all values - /// of enumerable types, producing ordinary C# 'foreach' statement and placing caret inside block: - /// - /// [SourceTemplate] - /// public static void forEach<T>(this IEnumerable<T> xs) { - /// foreach (var x in xs) { - /// //$ $END$ - /// } - /// } - /// - /// - [AttributeUsage(AttributeTargets.Method)] - public sealed class SourceTemplateAttribute : Attribute - { - } - - /// - /// Allows specifying a macro for a parameter of a source template. - /// - /// - /// You can apply the attribute on the whole method or on any of its additional parameters. The macro expression - /// is defined in the property. When applied on a method, the target - /// template parameter is defined in the property. To apply the macro silently - /// for the parameter, set the property value = -1. - /// - /// - /// Applying the attribute on a source template method: - /// - /// [SourceTemplate, Macro(Target = "item", Expression = "suggestVariableName()")] - /// public static void forEach<T>(this IEnumerable<T> collection) { - /// foreach (var item in collection) { - /// //$ $END$ - /// } - /// } - /// - /// Applying the attribute on a template method parameter: - /// - /// [SourceTemplate] - /// public static void something(this Entity x, [Macro(Expression = "guid()", Editable = -1)] string newguid) { - /// /*$ var $x$Id = "$newguid$" + x.ToString(); - /// x.DoSomething($x$Id); */ - /// } - /// - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method, AllowMultiple = true)] - public sealed class MacroAttribute : Attribute - { - /// - /// Allows specifying a macro that will be executed for a source template - /// parameter when the template is expanded. - /// - [CanBeNull] - public string Expression { get; set; } - - /// - /// Allows specifying which occurrence of the target parameter becomes editable when the template is deployed. - /// - /// - /// If the target parameter is used several times in the template, only one occurrence becomes editable; - /// other occurrences are changed synchronously. To specify the zero-based index of the editable occurrence, - /// use values >= 0. To make the parameter non-editable when the template is expanded, use -1. - /// - public int Editable { get; set; } - - /// - /// Identifies the target parameter of a source template if the - /// is applied on a template method. - /// - [CanBeNull] - public string Target { get; set; } - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] - public sealed class AspMvcAreaMasterLocationFormatAttribute : Attribute - { - public AspMvcAreaMasterLocationFormatAttribute([NotNull] - string format) - { - Format = format; - } - - [NotNull] - public string Format { get; } - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] - public sealed class AspMvcAreaPartialViewLocationFormatAttribute : Attribute - { - public AspMvcAreaPartialViewLocationFormatAttribute([NotNull] - string format) - { - Format = format; - } - - [NotNull] - public string Format { get; } - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] - public sealed class AspMvcAreaViewLocationFormatAttribute : Attribute - { - public AspMvcAreaViewLocationFormatAttribute([NotNull] - string format) - { - Format = format; - } - - [NotNull] - public string Format { get; } - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] - public sealed class AspMvcMasterLocationFormatAttribute : Attribute - { - public AspMvcMasterLocationFormatAttribute([NotNull] - string format) - { - Format = format; - } - - [NotNull] - public string Format { get; } - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] - public sealed class AspMvcPartialViewLocationFormatAttribute : Attribute - { - public AspMvcPartialViewLocationFormatAttribute([NotNull] - string format) - { - Format = format; - } - - [NotNull] - public string Format { get; } - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] - public sealed class AspMvcViewLocationFormatAttribute : Attribute - { - public AspMvcViewLocationFormatAttribute([NotNull] - string format) - { - Format = format; - } - - [NotNull] - public string Format { get; } - } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter - /// is an MVC action. If applied to a method, the MVC action name is calculated - /// implicitly from the context. Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcActionAttribute : Attribute - { - public AspMvcActionAttribute() - { - } - - public AspMvcActionAttribute([NotNull] - string anonymousProperty) - { - AnonymousProperty = anonymousProperty; - } - - [CanBeNull] - public string AnonymousProperty { get; } - } - - /// - /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC area. - /// Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcAreaAttribute : Attribute - { - public AspMvcAreaAttribute() - { - } - - public AspMvcAreaAttribute([NotNull] - string anonymousProperty) - { - AnonymousProperty = anonymousProperty; - } - - [CanBeNull] - public string AnonymousProperty { get; } - } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter is - /// an MVC controller. If applied to a method, the MVC controller name is calculated - /// implicitly from the context. Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcControllerAttribute : Attribute - { - public AspMvcControllerAttribute() - { - } - - public AspMvcControllerAttribute([NotNull] - string anonymousProperty) - { - AnonymousProperty = anonymousProperty; - } - - [CanBeNull] - public string AnonymousProperty { get; } - } - - /// - /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC Master. Use this attribute - /// for custom wrappers similar to System.Web.Mvc.Controller.View(String, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcMasterAttribute : Attribute - { - } - - /// - /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC model type. Use this attribute - /// for custom wrappers similar to System.Web.Mvc.Controller.View(String, Object). - /// - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class AspMvcModelTypeAttribute : Attribute - { - } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter is an MVC - /// partial view. If applied to a method, the MVC partial view name is calculated implicitly - /// from the context. Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.RenderPartialExtensions.RenderPartial(HtmlHelper, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcPartialViewAttribute : Attribute - { - } - - /// - /// ASP.NET MVC attribute. Allows disabling inspections for MVC views within a class or a method. - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] - public sealed class AspMvcSuppressViewErrorAttribute : Attribute - { - } - - /// - /// ASP.NET MVC attribute. Indicates that a parameter is an MVC display template. - /// Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.DisplayExtensions.DisplayForModel(HtmlHelper, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcDisplayTemplateAttribute : Attribute - { - } - - /// - /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC editor template. - /// Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.EditorExtensions.EditorForModel(HtmlHelper, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcEditorTemplateAttribute : Attribute - { - } - - /// - /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC template. - /// Use this attribute for custom wrappers similar to - /// System.ComponentModel.DataAnnotations.UIHintAttribute(System.String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcTemplateAttribute : Attribute - { - } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter - /// is an MVC view component. If applied to a method, the MVC view name is calculated implicitly - /// from the context. Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Controller.View(Object). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcViewAttribute : Attribute - { - } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter - /// is an MVC view component name. - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcViewComponentAttribute : Attribute - { - } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter - /// is an MVC view component view. If applied to a method, the MVC view component view name is default. - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcViewComponentViewAttribute : Attribute - { - } - - /// - /// ASP.NET MVC attribute. When applied to a parameter of an attribute, - /// indicates that this parameter is an MVC action name. - /// - /// - /// - /// [ActionName("Foo")] - /// public ActionResult Login(string returnUrl) { - /// ViewBag.ReturnUrl = Url.Action("Foo"); // OK - /// return RedirectToAction("Bar"); // Error: Cannot resolve action - /// } - /// - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property)] - public sealed class AspMvcActionSelectorAttribute : Attribute - { - } - - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field)] - public sealed class HtmlElementAttributesAttribute : Attribute - { - public HtmlElementAttributesAttribute() - { - } - - public HtmlElementAttributesAttribute([NotNull] - string name) - { - Name = name; - } - - [CanBeNull] - public string Name { get; } - } - - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class HtmlAttributeValueAttribute : Attribute - { - public HtmlAttributeValueAttribute([NotNull] - string name) - { - Name = name; - } - - [NotNull] - public string Name { get; } - } - - /// - /// Razor attribute. Indicates that the marked parameter or method is a Razor section. - /// Use this attribute for custom wrappers similar to - /// System.Web.WebPages.WebPageBase.RenderSection(String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)] - public sealed class RazorSectionAttribute : Attribute - { - } - - /// - /// Indicates how method, constructor invocation, or property access - /// over collection type affects the contents of the collection. - /// Use to specify the access type. - /// - /// - /// Using this attribute only makes sense if all collection methods are marked with this attribute. - /// - /// - /// - /// public class MyStringCollection : List<string> - /// { - /// [CollectionAccess(CollectionAccessType.Read)] - /// public string GetFirstString() - /// { - /// return this.ElementAt(0); - /// } - /// } - /// class Test - /// { - /// public void Foo() - /// { - /// // Warning: Contents of the collection is never updated - /// var col = new MyStringCollection(); - /// string x = col.GetFirstString(); - /// } - /// } - /// - /// - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Property)] - public sealed class CollectionAccessAttribute : Attribute - { - public CollectionAccessAttribute(CollectionAccessType collectionAccessType) - { - CollectionAccessType = collectionAccessType; - } - - public CollectionAccessType CollectionAccessType { get; } - } - - /// - /// Provides a value for the to define - /// how the collection method invocation affects the contents of the collection. - /// - [Flags] - public enum CollectionAccessType - { - /// Method does not use or modify content of the collection. - None = 0, - - /// Method only reads content of the collection but does not modify it. - Read = 1, - - /// Method can change content of the collection but does not add new elements. - ModifyExistingContent = 2, - - /// Method can add new elements to the collection. - UpdatedContent = ModifyExistingContent | 4 - } - - /// - /// Indicates that the marked method is assertion method, i.e. it halts the control flow if - /// one of the conditions is satisfied. To set the condition, mark one of the parameters with - /// attribute. - /// - [AttributeUsage(AttributeTargets.Method)] - public sealed class AssertionMethodAttribute : Attribute - { - } - - /// - /// Indicates the condition parameter of the assertion method. The method itself should be - /// marked by attribute. The mandatory argument of - /// the attribute is the assertion type. - /// - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class AssertionConditionAttribute : Attribute - { - public AssertionConditionAttribute(AssertionConditionType conditionType) - { - ConditionType = conditionType; - } - - public AssertionConditionType ConditionType { get; } - } - - /// - /// Specifies assertion type. If the assertion method argument satisfies the condition, - /// then the execution continues. Otherwise, execution is assumed to be halted. - /// - public enum AssertionConditionType - { - /// Marked parameter should be evaluated to true. - IS_TRUE = 0, - - /// Marked parameter should be evaluated to false. - IS_FALSE = 1, - - /// Marked parameter should be evaluated to null value. - IS_NULL = 2, - - /// Marked parameter should be evaluated to not null value. - IS_NOT_NULL = 3 - } - - /// - /// Indicates that the marked method unconditionally terminates control flow execution. - /// For example, it could unconditionally throw exception. - /// - [Obsolete("Use [ContractAnnotation('=> halt')] instead")] - [AttributeUsage(AttributeTargets.Method)] - public sealed class TerminatesProgramAttribute : Attribute - { - } - - /// - /// Indicates that method is pure LINQ method, with postponed enumeration (like Enumerable.Select, - /// .Where). This annotation allows inference of [InstantHandle] annotation for parameters - /// of delegate type by analyzing LINQ method chains. - /// - [AttributeUsage(AttributeTargets.Method)] - public sealed class LinqTunnelAttribute : Attribute - { - } - - /// - /// Indicates that IEnumerable passed as a parameter is not enumerated. - /// Use this annotation to suppress the 'Possible multiple enumeration of IEnumerable' inspection. - /// - /// - /// - /// static void ThrowIfNull<T>([NoEnumeration] T v, string n) where T : class - /// { - /// // custom check for null but no enumeration - /// } - /// - /// void Foo(IEnumerable<string> values) - /// { - /// ThrowIfNull(values, nameof(values)); - /// var x = values.ToList(); // No warnings about multiple enumeration - /// } - /// - /// - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class NoEnumerationAttribute : Attribute - { - } - - /// - /// Indicates that the marked parameter is a regular expression pattern. - /// - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class RegexPatternAttribute : Attribute - { - } - - /// - /// Prevents the Member Reordering feature from tossing members of the marked class. - /// - /// - /// The attribute must be mentioned in your member reordering patterns. - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.Enum)] - public sealed class NoReorderAttribute : Attribute - { - } - - /// - /// XAML attribute. Indicates the type that has ItemsSource property and should be treated - /// as ItemsControl-derived type, to enable inner items DataContext type resolve. - /// - [AttributeUsage(AttributeTargets.Class)] - public sealed class XamlItemsControlAttribute : Attribute - { - } - - /// - /// XAML attribute. Indicates the property of some BindingBase-derived type, that - /// is used to bind some item of ItemsControl-derived type. This annotation will - /// enable the DataContext type resolve for XAML bindings for such properties. - /// - /// - /// Property should have the tree ancestor of the ItemsControl type or - /// marked with the attribute. - /// - [AttributeUsage(AttributeTargets.Property)] - public sealed class XamlItemBindingOfItemsControlAttribute : Attribute - { - } - - [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] - public sealed class AspChildControlTypeAttribute : Attribute - { - public AspChildControlTypeAttribute([NotNull] - string tagName, [NotNull] - Type controlType) - { - TagName = tagName; - ControlType = controlType; - } - - [NotNull] - public string TagName { get; } - - [NotNull] - public Type ControlType { get; } - } - - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)] - public sealed class AspDataFieldAttribute : Attribute - { - } - - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)] - public sealed class AspDataFieldsAttribute : Attribute - { - } - - [AttributeUsage(AttributeTargets.Property)] - public sealed class AspMethodPropertyAttribute : Attribute - { - } - - [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] - public sealed class AspRequiredAttributeAttribute : Attribute - { - public AspRequiredAttributeAttribute([NotNull] - string attribute) - { - Attribute = attribute; - } - - [NotNull] - public string Attribute { get; } - } - - [AttributeUsage(AttributeTargets.Property)] - public sealed class AspTypePropertyAttribute : Attribute - { - public AspTypePropertyAttribute(bool createConstructorReferences) - { - CreateConstructorReferences = createConstructorReferences; - } - - public bool CreateConstructorReferences { get; } - } - - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - public sealed class RazorImportNamespaceAttribute : Attribute - { - public RazorImportNamespaceAttribute([NotNull] - string name) - { - Name = name; - } - - [NotNull] - public string Name { get; } - } - - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - public sealed class RazorInjectionAttribute : Attribute - { - public RazorInjectionAttribute([NotNull] - string type, [NotNull] - string fieldName) - { - Type = type; - FieldName = fieldName; - } - - [NotNull] - public string Type { get; } - - [NotNull] - public string FieldName { get; } - } - - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - public sealed class RazorDirectiveAttribute : Attribute - { - public RazorDirectiveAttribute([NotNull] - string directive) - { - Directive = directive; - } - - [NotNull] - public string Directive { get; } - } - - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - public sealed class RazorPageBaseTypeAttribute : Attribute - { - public RazorPageBaseTypeAttribute([NotNull] - string baseType) - { - BaseType = baseType; - } - - public RazorPageBaseTypeAttribute([NotNull] - string baseType, string pageName) - { - BaseType = baseType; - PageName = pageName; - } - - [NotNull] - public string BaseType { get; } - - [CanBeNull] - public string PageName { get; } - } - - [AttributeUsage(AttributeTargets.Method)] - public sealed class RazorHelperCommonAttribute : Attribute - { - } - - [AttributeUsage(AttributeTargets.Property)] - public sealed class RazorLayoutAttribute : Attribute - { - } - - [AttributeUsage(AttributeTargets.Method)] - public sealed class RazorWriteLiteralMethodAttribute : Attribute - { - } - - [AttributeUsage(AttributeTargets.Method)] - public sealed class RazorWriteMethodAttribute : Attribute - { - } - - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class RazorWriteMethodParameterAttribute : Attribute - { - } -} \ No newline at end of file diff --git a/src/Pixeval/App.xaml b/src/Pixeval/App.xaml deleted file mode 100644 index 11bd5e85..00000000 --- a/src/Pixeval/App.xaml +++ /dev/null @@ -1,307 +0,0 @@ - - - - - - - - - - - - - 2 - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Pixeval/App.xaml.cs b/src/Pixeval/App.xaml.cs deleted file mode 100644 index 9e634247..00000000 --- a/src/Pixeval/App.xaml.cs +++ /dev/null @@ -1,281 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -#if RELEASE -using Pixeval.Objects.Exceptions.Logger; -#endif -using System.Linq; -using System; -using System.Diagnostics; -using System.IO; -using System.IO.Compression; -using System.Net.NetworkInformation; -using System.Security.Cryptography.X509Certificates; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using CefSharp; -using CefSharp.Wpf; -using Microsoft.Win32; -using Pixeval.Core; -using Pixeval.Objects.I18n; -using Pixeval.Objects.Primitive; -using Pixeval.Persisting; -using Pixeval.Persisting.WebApi; - -namespace Pixeval -{ - public partial class App - { - public App() - { - if (Dispatcher != null) Dispatcher.UnhandledException += (sender, args) => DispatcherOnUnhandledException(args.Exception); - AppDomain.CurrentDomain.UnhandledException += (sender, args) => DispatcherOnUnhandledException((Exception) args.ExceptionObject); - TaskScheduler.UnobservedTaskException += (sender, args) => DispatcherOnUnhandledException(args.Exception); - } - - private static void DispatcherOnUnhandledException(Exception e) - { -#if RELEASE - ExceptionDumper.WriteException(e); -#elif DEBUG - throw e; -#endif - } - - protected override async void OnStartup(StartupEventArgs e) - { - // These initializations ensure Pixeval to run properly, they MUST be initialized before everything start - WriteToCurrentUserPathVariable(); - InitializeFolders(); - CheckCppRedistributable(); - CheckMultipleProcess(); - await InstallFakeCaCertificate(); - - // These initializations are for WEB API LOGIN - PortScan(out var proxy, out var pac); - AppContext.ProxyPort = proxy; - AppContext.PacPort = pac; - await WritePac(); - CefSharpInitialize(); - - // These initializations handle USER SESSION AND PIXEVAL UPDATE - await RestoreSettings(); - await CheckUpdate(); - - // These initializations are for PROCESS COMMUNICATION AND PLUGGABLE PROTOCOL - await InstallPluggableProtocolHandler(); - CreatePluggableProtocolRegistry(); - PluggableProtocolListener.StartServer(); - - - if (e.Args.Any()) await PluggableProtocolParser.Parse(e.Args[0]); - base.OnStartup(e); - } - - private static void PortScan(out int proxy, out int pac) - { - var unavailablePorts = IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpConnections().Select(t => t.LocalEndPoint.Port).ToArray(); - - var rd = new Random(); - proxy = RandPorts(); - pac = RandPorts(); - while (Array.BinarySearch(unavailablePorts, proxy) >= 0) proxy = RandPorts(); - - while (Array.BinarySearch(unavailablePorts, pac) >= 0) pac = RandPorts(); - - int RandPorts() - { - return rd.Next(3000, 65536); - } - } - - private static async Task InstallPluggableProtocolHandler() - { - var files = Directory.GetFiles(AppContext.InterchangeFolder); - if (!(files.Any(f => f[(f.LastIndexOf(@"\", StringComparison.Ordinal) + 1)..] == "Pixeval.Interchange.runtimeconfig.json") && files.Any(f => f[(f.LastIndexOf(@"\", StringComparison.Ordinal) + 1)..] == "Pixeval.Interchange.exe") && files.Any(f => f[(f.LastIndexOf(@"\", StringComparison.Ordinal) + 1)..] == "Pixeval.Interchange.dll"))) - { - foreach (var file in files) File.Delete(file); - if (GetResourceStream(new Uri("pack://application:,,,/Pixeval;component/Resources/interchange.zip")) is { } streamResourceInfo) - { - var interchange = Path.Combine(AppContext.InterchangeFolder, "interchange.zip"); - await using (var fs = new FileStream(interchange, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)) - { - await streamResourceInfo.Stream.CopyToAsync(fs); - } - - ZipFile.ExtractToDirectory(interchange, AppContext.InterchangeFolder, true); - File.Delete(Path.Combine(AppContext.InterchangeFolder, "interchange.zip")); - } - } - } - - private static void WriteToCurrentUserPathVariable() - { - var pathOld = Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.User); - if (pathOld == null) - { - Environment.SetEnvironmentVariable("PATH", "", EnvironmentVariableTarget.User); - pathOld = ""; - } - - var paths = pathOld.Split(';').ToList(); - var location = Path.GetDirectoryName(typeof(App).Assembly.Location); - if (paths.All(p => p != location)) - { - paths.RemoveAll(p => p.ToLower().Contains("pixeval")); - var newPath = paths.Join(';') + ';' + location; - Environment.SetEnvironmentVariable("PATH", newPath, EnvironmentVariableTarget.User); - } - } - - private static void InitializeFolders() - { - Directory.CreateDirectory(AppContext.ProjectFolder); - Directory.CreateDirectory(AppContext.SettingsFolder); - Directory.CreateDirectory(AppContext.ExceptionReportFolder); - Directory.CreateDirectory(AppContext.ResourceFolder); - Directory.CreateDirectory(AppContext.PermanentlyFolder); - Directory.CreateDirectory(AppContext.InterchangeFolder); - } - - private static void CreatePluggableProtocolRegistry() - { - var regKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Classes\\pixeval"); - if (regKey == null) - { - using var rootKey = Registry.CurrentUser.CreateSubKey("SOFTWARE\\Classes\\pixeval"); - if (rootKey == null) throw new InvalidOperationException(nameof(rootKey)); - rootKey.SetValue("", "URL:Pixeval Protocol"); - rootKey.SetValue("URL Protocol", ""); - using var shellKey = rootKey.CreateSubKey("shell\\open\\command"); - if (shellKey == null) throw new InvalidOperationException(nameof(shellKey)); - shellKey.SetValue("", $"{Path.Combine(AppContext.InterchangeFolder, "Pixeval.Interchange.exe")} %1"); - } - - regKey?.Dispose(); - } - - private static void CheckMultipleProcess() - { - if (Process.GetProcessesByName(AppContext.AppIdentifier).Length > 1) - { - MessageBox.Show(AkaI18N.MultiplePixevalInstanceDetected, AkaI18N.MultiplePixevalInstanceDetectedTitle, MessageBoxButton.OK, MessageBoxImage.Error); - Environment.Exit(-1); - } - } - - private static void CheckCppRedistributable() - { - if (!CppRedistributableInstalled()) - { - MessageBox.Show(AkaI18N.CppRedistributableRequired, AkaI18N.CppRedistributableRequiredTitle, MessageBoxButton.OK, MessageBoxImage.Exclamation); - Clipboard.SetDataObject("https://support.microsoft.com/zh-cn/help/2977003/the-latest-supported-visual-c-downloads"); - Environment.Exit(-1); - } - } - - private static async Task CheckUpdate() - { - if (await AppContext.UpdateAvailable() && MessageBox.Show(AkaI18N.PixevalUpdateAvailable, AkaI18N.PixevalUpdateAvailableTitle, MessageBoxButton.YesNo, MessageBoxImage.Information) == MessageBoxResult.Yes) - { - Process.Start(@"updater\Pixeval.Updater.exe"); - Environment.Exit(0); - } - } - - /// - /// Check if the required Visual C++ Redistributable is installed on the computer - /// - /// Cpp redistributable is installed - private static bool CppRedistributableInstalled() - { - using var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Wow6432Node\Microsoft\VisualStudio\14.0\VC\Runtimes\x64"); - if (key == null) return false; - - var success = int.TryParse(key.GetValue("Bld").ToString(), out var version); - // visual C++ redistributable Bld table: - // version v2015 v2017 v2019 - // ---------------------------------- - // Bid 23026 26020 27820 - const int vc2015Bld = 23026; - return success && version >= vc2015Bld; - } - - private static void CefSharpInitialize() - { - Cef.Initialize(new CefSettings {CefCommandLineArgs = {{"proxy-pac-url", $"http://127.0.0.1:{AppContext.PacPort}/pixeval_pac.pac"}}}, true, browserProcessHandler: null); - } - - private static async Task InstallFakeCaCertificate() - { - var certificateManager = new CertificateManager(await CertificateManager.GetFakeCaRootCertificate()); - if (!certificateManager.Query(StoreName.Root, StoreLocation.CurrentUser)) - { - if (MessageBox.Show(AkaI18N.CertificateInstallationIsRequired, AkaI18N.CertificateInstallationIsRequiredTitle, MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes) - certificateManager.Install(StoreName.Root, StoreLocation.CurrentUser); - else - Environment.Exit(-1); - } - } - - private static async Task RestoreSettings() - { - await Settings.Restore(); - BrowsingHistoryAccessor.GlobalLifeTimeScope = new BrowsingHistoryAccessor(200, AppContext.BrowseHistoryDatabase); - } - - /// - /// Write Proxy-Auto-Configuration file to ..\{Directory to Pixeval.dll}\Resource\pixeval_pac.pac, - /// this method is for login usage only, USE AT YOUR OWN RISK - /// - private static async Task WritePac() - { - var scriptBuilder = new StringBuilder(); - scriptBuilder.AppendLine("function FindProxyForURL(url, host) {"); - scriptBuilder.AppendLine(" if (shExpMatch(host, \"*.pixiv.net\")) {"); - scriptBuilder.AppendLine($" return 'PROXY 127.0.0.1:{AppContext.ProxyPort}';"); - scriptBuilder.AppendLine(" }"); - scriptBuilder.AppendLine(" return \"DIRECT\";"); - scriptBuilder.AppendLine("}"); - await File.WriteAllTextAsync(Path.Combine(AppContext.ResourceFolder, "pixeval_pac.pac"), scriptBuilder.ToString()); - } - - protected override async void OnExit(ExitEventArgs e) - { - CertificateManager.GetFakeCaRootCertificate().Dispose(); - CertificateManager.GetFakeServerCertificate().Dispose(); - await Settings.Global.Store(); - if (Session.Current != null && !Session.Current.AccessToken.IsNullOrEmpty() && !Session.Current.PhpSessionId.IsNullOrEmpty()) await Session.Current.Store(); - if (File.Exists(AppContext.BrowseHistoryDatabase)) - { - BrowsingHistoryAccessor.GlobalLifeTimeScope.SetWritable(); - BrowsingHistoryAccessor.GlobalLifeTimeScope.Rewrite(); - BrowsingHistoryAccessor.GlobalLifeTimeScope.Dispose(); - } - else - { - BrowsingHistoryAccessor.GlobalLifeTimeScope.EmergencyRewrite(); - } - - base.OnExit(e); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/AppContext.cs b/src/Pixeval/AppContext.cs deleted file mode 100644 index 2a895b80..00000000 --- a/src/Pixeval/AppContext.cs +++ /dev/null @@ -1,74 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections.ObjectModel; -using System.IO; -using System.Net.Http; -using System.Threading.Tasks; -using Pixeval.Core; -using Pixeval.Data.ViewModel; - -namespace Pixeval -{ - public static class AppContext - { - public const string AppIdentifier = "Pixeval"; - - public const string CurrentVersion = "2.2.5"; - - public const string ConfigurationFileName = "pixeval_conf.json"; - - public static readonly string ProjectFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), AppIdentifier.ToLower()); - - public static readonly string ConfFolder = ProjectFolder; - - public static readonly string SettingsFolder = ProjectFolder; - - public static readonly string ExceptionReportFolder = Path.Combine(ProjectFolder, "crash-reports"); - - public static readonly string InterchangeFolder = Path.Combine(ProjectFolder, "interchange"); - - public static readonly string CacheFolder = Path.Combine(ProjectFolder, "cache"); - - public static readonly string ResourceFolder = Path.Combine(Path.GetDirectoryName(typeof(App).Assembly.Location)!, "Resource"); - - public static readonly string PermanentlyFolder = Path.Combine(Path.GetDirectoryName(typeof(App).Assembly.Location)!, "Permanent"); - - public static readonly string BrowseHistoryDatabase = Path.Combine(ProjectFolder, "history.db"); - - public static readonly ObservableCollection TrendingTags = new ObservableCollection(); - - public static readonly IQualifier DefaultQualifier = new IllustrationQualifier(); - - public static readonly I18NOption[] AvailableCultures = {I18NOption.USEnglish, I18NOption.ChineseSimplified}; - - public static int ProxyPort { get; set; } - - public static int PacPort { get; set; } - - public static async Task UpdateAvailable() - { - const string url = "http://47.95.218.243/Pixeval/version.txt"; - var httpClient = new HttpClient(); - return await httpClient.GetStringAsync(url) != CurrentVersion; - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/AbstractPixivAsyncEnumerable.cs b/src/Pixeval/Core/AbstractPixivAsyncEnumerable.cs deleted file mode 100644 index cd6b7910..00000000 --- a/src/Pixeval/Core/AbstractPixivAsyncEnumerable.cs +++ /dev/null @@ -1,64 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Collections.Generic; -using System.Threading; - -namespace Pixeval.Core -{ - /// - /// Abstract implementation of , provides the default implementation of cancel a - /// running instance - /// - /// - public abstract class AbstractPixivAsyncEnumerable : IPixivAsyncEnumerable - { - protected bool IsCancelled { get; private set; } - - public abstract int RequestedPages { get; protected set; } - - public abstract IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default); - - public virtual bool VerifyRationality(T item, IList collection) - { - return item != null && !collection.Contains(item); - } - - public virtual void InsertionPolicy(T item, IList collection) - { - if (item != null) collection.Add(item); - } - - public void Cancel() - { - IsCancelled = true; - } - - public bool IsCancellationRequested() - { - return IsCancelled; - } - - public void ReportRequestedPages() - { - RequestedPages++; - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/AbstractPixivAsyncEnumerator.cs b/src/Pixeval/Core/AbstractPixivAsyncEnumerator.cs deleted file mode 100644 index 095b5cee..00000000 --- a/src/Pixeval/Core/AbstractPixivAsyncEnumerator.cs +++ /dev/null @@ -1,50 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace Pixeval.Core -{ - /// - /// Provide a set of functions that support iterate an - /// - /// the correspond data type - public abstract class AbstractPixivAsyncEnumerator : IAsyncEnumerator - { - protected IPixivAsyncEnumerable Enumerable; - - protected AbstractPixivAsyncEnumerator(IPixivAsyncEnumerable enumerable) - { - Enumerable = enumerable; - } - - public ValueTask DisposeAsync() - { - return default; - } - - public abstract ValueTask MoveNextAsync(); - - public abstract T Current { get; } - - protected abstract void UpdateEnumerator(); - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/BrowsingHistoryAccessor.cs b/src/Pixeval/Core/BrowsingHistoryAccessor.cs deleted file mode 100644 index 858fb011..00000000 --- a/src/Pixeval/Core/BrowsingHistoryAccessor.cs +++ /dev/null @@ -1,128 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.IO; -using System.Linq; -using Pixeval.Data.ViewModel; -using SQLite; - -namespace Pixeval.Core -{ - /// - /// Manages the global browsing history which lives inside application - /// the underlying implementation is sqlite database - /// - public class BrowsingHistoryAccessor : ITimelineService, IDisposable - { - public static BrowsingHistoryAccessor GlobalLifeTimeScope; - - // current browsing histories - private readonly ObservableCollection _delegation; - private readonly string _path; - private readonly SQLiteConnection _sqLiteConnection; - private readonly int _stackLimit; - private bool _writable; - - public BrowsingHistoryAccessor(int stackLimit, string path) - { - _stackLimit = stackLimit; - _path = path; - _sqLiteConnection = new SQLiteConnection(path, SQLiteOpenFlags.Create | SQLiteOpenFlags.ReadWrite); - _sqLiteConnection.CreateTable(); - _delegation = new ObservableCollection(_sqLiteConnection.Table()); - } - - public void Dispose() - { - _sqLiteConnection?.Dispose(); - } - - public bool VerifyRationality(BrowsingHistory browsingHistory) - { - // if current browsing history list has elements - if (_delegation.Any()) - { - var prev = _delegation[0]; - // check if the last one in the browsing history list is the same as the one to be insert, return false if so - if (prev.Type == browsingHistory.Type && prev.BrowseObjectId == browsingHistory.BrowseObjectId) return false; - } - - return true; - } - - public void Insert(BrowsingHistory browsingHistory) - { - // we can simply consider the browsing histories as a double-ended queue with limited capacity, we will pop the oldest one - // and insert a new one if the Deque is full - if (_delegation.Count >= _stackLimit) _delegation.Remove(_delegation.Last()); - - _delegation.Insert(0, browsingHistory); - } - - /// - /// If the database file is not present, we will urgently create one and - /// write all the browsing histories that we have into it - /// - public void EmergencyRewrite() - { - if (File.Exists(_path)) throw new InvalidOperationException(); - using var sql = new SQLiteConnection(_path); - sql.CreateTable(); - sql.InsertAll(Get()); - } - - /// - /// Returns currently maintained browsing histories - /// - /// - public IEnumerable Get() - { - return _delegation; - } - - /// - /// Rewrite the local database, you muse call - /// before call this method - /// - public void Rewrite() - { - if (!_writable) throw new InvalidOperationException(); - _sqLiteConnection.DropTable(); - _sqLiteConnection.CreateTable(); - _sqLiteConnection.InsertAll(_delegation); - } - - /// - /// Delete the local database - /// - public void DropDb() - { - if (File.Exists(_path)) File.Delete(_path); - } - - public void SetWritable() - { - _writable = true; - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/CreateNewFolderForUserDownloadPathProvider.cs b/src/Pixeval/Core/CreateNewFolderForUserDownloadPathProvider.cs deleted file mode 100644 index ebaa479d..00000000 --- a/src/Pixeval/Core/CreateNewFolderForUserDownloadPathProvider.cs +++ /dev/null @@ -1,51 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.IO; -using Pixeval.Objects.Primitive; -using Pixeval.Persisting; - -namespace Pixeval.Core -{ - public class CreateNewFolderForUserDownloadPathProvider : IDownloadPathProvider - { - public CreateNewFolderForUserDownloadPathProvider(string userName) - { - UserName = userName; - } - - public string UserName { get; set; } - - public string GetSpotlightPath(string title, DownloadOption option = null) - { - return option?.RootDirectory ?? Path.Combine(Settings.Global.DownloadLocation, "Spotlight", Strings.FormatPath(title)); - } - - public string GetIllustrationPath(DownloadOption option = null) - { - return option?.RootDirectory ?? Path.Combine(Settings.Global.DownloadLocation, UserName); - } - - public string GetMangaPath(string id, DownloadOption option = null) - { - return option?.RootDirectory ?? Path.Combine(Settings.Global.DownloadLocation, UserName, id); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/DefaultDownloadPathProvider.cs b/src/Pixeval/Core/DefaultDownloadPathProvider.cs deleted file mode 100644 index 7fc5e8d3..00000000 --- a/src/Pixeval/Core/DefaultDownloadPathProvider.cs +++ /dev/null @@ -1,44 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.IO; -using Pixeval.Objects.Primitive; -using Pixeval.Persisting; - -namespace Pixeval.Core -{ - public class DefaultDownloadPathProvider : IDownloadPathProvider - { - public string GetSpotlightPath(string title, DownloadOption option = null) - { - return option?.RootDirectory ?? Path.Combine(Settings.Global.DownloadLocation, "Spotlight", Strings.FormatPath(title)); - } - - public string GetIllustrationPath(DownloadOption option = null) - { - return option?.RootDirectory ?? Settings.Global.DownloadLocation; - } - - public string GetMangaPath(string id, DownloadOption option = null) - { - return option?.RootDirectory ?? Path.Combine(Settings.Global.DownloadLocation, id); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/DefaultIllustrationFileNameFormatter.cs b/src/Pixeval/Core/DefaultIllustrationFileNameFormatter.cs deleted file mode 100644 index fcddb8aa..00000000 --- a/src/Pixeval/Core/DefaultIllustrationFileNameFormatter.cs +++ /dev/null @@ -1,44 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.IO; -using Pixeval.Data.ViewModel; -using Pixeval.Objects.Primitive; - -namespace Pixeval.Core -{ - public class DefaultIllustrationFileNameFormatter : IIllustrationFileNameFormatter - { - public string Format(Illustration illustration) - { - return $"[{Strings.FormatPath(illustration.UserName)}]{illustration.Id}{Path.GetExtension(illustration.Origin.IsNullOrEmpty() ? illustration.Large : illustration.Origin)}"; - } - - public string FormatManga(Illustration illustration, int idx) - { - return $"[{Strings.FormatPath(illustration.UserName)}]{illustration.Id}_p{idx}{Path.GetExtension(illustration.Origin.IsNullOrEmpty() ? illustration.Large : illustration.Origin)}"; - } - - public string FormatGif(Illustration illustration) - { - return $"[{Strings.FormatPath(illustration.UserName)}]{illustration.Id}.gif"; - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/EnumeratingSchedule.cs b/src/Pixeval/Core/EnumeratingSchedule.cs deleted file mode 100644 index 66c9e127..00000000 --- a/src/Pixeval/Core/EnumeratingSchedule.cs +++ /dev/null @@ -1,47 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; - -namespace Pixeval.Core -{ - public class EnumeratingSchedule - { - private static object _currentItr; - - public static void StartNewInstance(IPixivAsyncEnumerable itr) - { - CancelCurrent(); - _currentItr = itr; - } - - public static IPixivAsyncEnumerable GetCurrentEnumerator() - { - return _currentItr as IPixivAsyncEnumerable; - } - - public static void CancelCurrent() - { - var iterator = _currentItr as ICancellable; - iterator?.Cancel(); - GC.Collect(); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/GalleryAsyncEnumerable.cs b/src/Pixeval/Core/GalleryAsyncEnumerable.cs deleted file mode 100644 index d1442a63..00000000 --- a/src/Pixeval/Core/GalleryAsyncEnumerable.cs +++ /dev/null @@ -1,157 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Pixeval.Data.ViewModel; -using Pixeval.Data.Web; -using Pixeval.Data.Web.Delegation; -using Pixeval.Data.Web.Response; -using Pixeval.Objects.Exceptions; -using Pixeval.Objects.Generic; -using Pixeval.Objects.I18n; -using Pixeval.Objects.Primitive; -using Pixeval.Persisting; - -namespace Pixeval.Core -{ - public abstract class AbstractGalleryAsyncEnumerable : AbstractPixivAsyncEnumerable - { - protected abstract string Uid { get; } - - protected abstract RestrictPolicy RestrictPolicy { get; } - - public override int RequestedPages { get; protected set; } - - public override bool VerifyRationality(Illustration item, IList collection) - { - return item != null && collection.All(t => t.Id != item.Id) && PixivHelper.VerifyIllustRational(Settings.Global.ExcludeTag, Settings.Global.IncludeTag, Settings.Global.MinBookmark, item); - } - - public override IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) - { - return new GalleryAsyncEnumerator(Uid, this, RestrictPolicy); - } - - public static AbstractGalleryAsyncEnumerable Of(string uid, RestrictPolicy restrictPolicy) - { - return restrictPolicy switch - { - RestrictPolicy.Public => new PublicGalleryAsyncEnumerable(uid), - RestrictPolicy.Private => new PrivateGalleryAsyncEnumerable(uid), - _ => throw new ArgumentOutOfRangeException(nameof(restrictPolicy), restrictPolicy, null) - }; - } - - private class GalleryAsyncEnumerator : AbstractPixivAsyncEnumerator - { - private readonly RestrictPolicy _restrictPolicy; - private readonly string _uid; - private GalleryResponse _entity; - - private IEnumerator _illustrationsEnumerator; - - public GalleryAsyncEnumerator(string uid, IPixivAsyncEnumerable outerInstance, RestrictPolicy restrictPolicy) : base(outerInstance) - { - _uid = uid; - _restrictPolicy = restrictPolicy; - } - - public override Illustration Current => _illustrationsEnumerator.Current; - - protected override void UpdateEnumerator() - { - _illustrationsEnumerator = _entity.Illusts.NonNull().Select(_ => _.Parse()).GetEnumerator(); - } - - public override async ValueTask MoveNextAsync() - { - if (_entity == null) - { - if (await TryGetResponse(_restrictPolicy switch - { - RestrictPolicy.Public => $"/v1/user/bookmarks/illust?user_id={_uid}&restrict=public&filter=for_ios", - RestrictPolicy.Private => $"/v1/user/bookmarks/illust?user_id={_uid}&restrict=private&filter=for_ios", - _ => throw new ArgumentOutOfRangeException() - }) is (true, var model)) - { - _entity = model; - UpdateEnumerator(); - } - else - { - throw new QueryNotRespondingException(); - } - - Enumerable.ReportRequestedPages(); - } - - if (_illustrationsEnumerator.MoveNext()) return true; - - if (_entity.NextUrl.IsNullOrEmpty()) return false; - - if (await TryGetResponse(_entity.NextUrl) is (true, var response)) - { - _entity = response; - UpdateEnumerator(); - Enumerable.ReportRequestedPages(); - return true; - } - - return false; - } - - private static async Task> TryGetResponse(string url) - { - var result = (await HttpClientFactory.AppApiHttpClient().Apply(h => h.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Language", AkaI18N.GetCultureAcceptLanguage())).GetStringAsync(url)).FromJson(); - - if (result is { } response && !response.Illusts.IsNullOrEmpty()) return HttpResponse.Wrap(true, response); - return HttpResponse.Wrap(false); - } - } - } - - public class PublicGalleryAsyncEnumerable : AbstractGalleryAsyncEnumerable - { - public PublicGalleryAsyncEnumerable(string uid) - { - Uid = uid; - } - - protected override string Uid { get; } - - protected override RestrictPolicy RestrictPolicy { get; } = RestrictPolicy.Public; - } - - public class PrivateGalleryAsyncEnumerable : AbstractGalleryAsyncEnumerable - { - public PrivateGalleryAsyncEnumerable(string uid) - { - Uid = uid; - } - - protected override string Uid { get; } - - protected override RestrictPolicy RestrictPolicy { get; } = RestrictPolicy.Private; - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/ICancellable.cs b/src/Pixeval/Core/ICancellable.cs deleted file mode 100644 index 813d5f63..00000000 --- a/src/Pixeval/Core/ICancellable.cs +++ /dev/null @@ -1,29 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -namespace Pixeval.Core -{ - public interface ICancellable - { - void Cancel(); - - bool IsCancellationRequested(); - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/IDownloadPathProvider.cs b/src/Pixeval/Core/IDownloadPathProvider.cs deleted file mode 100644 index 218701ed..00000000 --- a/src/Pixeval/Core/IDownloadPathProvider.cs +++ /dev/null @@ -1,49 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using Pixeval.Data.ViewModel; - -namespace Pixeval.Core -{ - public interface IIllustrationFileNameFormatter - { - string Format(Illustration illustration); - - string FormatManga(Illustration illustration, int idx); - - string FormatGif(Illustration illustration); - } - - public interface IDownloadPathProvider - { - string GetSpotlightPath(string title, DownloadOption option = null); - - string GetIllustrationPath(DownloadOption option = null); - - string GetMangaPath(string id, DownloadOption option = null); - } - - public class DownloadOption - { - public string RootDirectory { get; set; } - - public bool CreateNewWhenFromUser { get; set; } - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/IPixivAsyncEnumerable.cs b/src/Pixeval/Core/IPixivAsyncEnumerable.cs deleted file mode 100644 index 303bd2a8..00000000 --- a/src/Pixeval/Core/IPixivAsyncEnumerable.cs +++ /dev/null @@ -1,56 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Collections.Generic; - -namespace Pixeval.Core -{ - /// - /// A base class provides several functions to browse the Pixiv content - /// - /// the correspond data type - public interface IPixivAsyncEnumerable : IAsyncEnumerable, ICancellable - { - /// - /// Indicates how many pages have been requested - /// - int RequestedPages { get; } - - /// - /// Basically, this method SHOULD increase the value of - /// - void ReportRequestedPages(); - - /// - /// Tell the how to insert to a - /// - /// - /// - void InsertionPolicy(T item, IList collection); - - /// - /// Check if the has the rationality to be inserted to the - /// - /// - /// - /// - bool VerifyRationality(T item, IList collection); - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/IQualifier.cs b/src/Pixeval/Core/IQualifier.cs deleted file mode 100644 index 9f8166c3..00000000 --- a/src/Pixeval/Core/IQualifier.cs +++ /dev/null @@ -1,27 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -namespace Pixeval.Core -{ - public interface IQualifier - { - public bool Qualified(T condition, P pattern); - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/ITimelineService.cs b/src/Pixeval/Core/ITimelineService.cs deleted file mode 100644 index f18b353d..00000000 --- a/src/Pixeval/Core/ITimelineService.cs +++ /dev/null @@ -1,43 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using Pixeval.Data.ViewModel; - -namespace Pixeval.Core -{ - /// - /// Provides a set of functions that support a Browsing Timeline - /// - public interface ITimelineService - { - /// - /// Check if the has the rationality to be insert to timeline - /// - /// - /// - bool VerifyRationality(BrowsingHistory browsingHistory); - - /// - /// Insert a to timeline - /// - /// - void Insert(BrowsingHistory browsingHistory); - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/IllustrationQualification.cs b/src/Pixeval/Core/IllustrationQualification.cs deleted file mode 100644 index df60755f..00000000 --- a/src/Pixeval/Core/IllustrationQualification.cs +++ /dev/null @@ -1,53 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using Pixeval.Objects.Primitive; - -namespace Pixeval.Core -{ - public class IllustrationQualification - { - public IllustrationQualification(ConditionType type, string condition) - { - Type = type; - Condition = condition; - } - - public ConditionType Type { get; set; } - - public string Condition { get; set; } - - public static IllustrationQualification Parse(string input) - { - return new IllustrationQualification(input switch - { - _ when input.IsNumber() => ConditionType.Id, - _ when input.StartsWith("!") => ConditionType.ExcludeTag, - _ when !input.IsNullOrEmpty() => ConditionType.Tag, - _ => ConditionType.None - }, input); - } - } - - public enum ConditionType - { - Id, Tag, ExcludeTag, None - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/IllustrationQualifier.cs b/src/Pixeval/Core/IllustrationQualifier.cs deleted file mode 100644 index 7445e43e..00000000 --- a/src/Pixeval/Core/IllustrationQualifier.cs +++ /dev/null @@ -1,39 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Linq; -using Pixeval.Data.ViewModel; - -namespace Pixeval.Core -{ - public class IllustrationQualifier : IQualifier - { - public bool Qualified(Illustration condition, IllustrationQualification pattern) - { - return pattern switch - { - { Type: ConditionType.Id } => !condition.Id.Contains(pattern.Condition), - { Type: ConditionType.Tag } => !condition.Title.Contains(pattern.Condition) && !(condition.Tags != null && condition.Tags.Any(tag => tag?.Name != null && tag.Name.ToLower().Contains(pattern.Condition.ToLower()) || tag?.TranslatedName != null && tag.TranslatedName.ToLower().Contains(pattern.Condition.ToLower()))), - { Type: ConditionType.ExcludeTag } => condition.Tags != null && condition.Tags.Any(tag => tag?.Name != null && tag.Name.ToLower().Contains(pattern.Condition[1..].ToLower()) || tag?.TranslatedName != null && tag.TranslatedName.ToLower().Contains(pattern.Condition[1..].ToLower())), - _ => false - }; - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/Managers.cs b/src/Pixeval/Core/Managers.cs deleted file mode 100644 index 149dfb9a..00000000 --- a/src/Pixeval/Core/Managers.cs +++ /dev/null @@ -1,95 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using System.Threading.Tasks; -using System.Windows; -using Pixeval.Data.ViewModel; - -namespace Pixeval.Core -{ - public class DownloadManager - { - public static readonly ObservableCollection Downloading = new ObservableCollection(); - - public static readonly ObservableCollection Downloaded = new ObservableCollection(); - - public static void EnqueueDownloadItem(Illustration illustration, DownloadOption option = null) - { - if (Downloading.Any(i => illustration.Id == i.DownloadContent.Id)) return; - option ??= new DownloadOption(); - - static DownloadableIllustration CreateDownloadableIllustration(Illustration downloadContent, bool isFromMange, DownloadOption option, int index = -1) - { - var filePathProvider = option.CreateNewWhenFromUser ? new CreateNewFolderForUserDownloadPathProvider(downloadContent.UserName) : (IDownloadPathProvider) new DefaultDownloadPathProvider(); - var fileNameFormatter = new DefaultIllustrationFileNameFormatter(); - var model = new DownloadableIllustration(downloadContent, fileNameFormatter, filePathProvider, isFromMange, index) {Option = option}; - model.DownloadState.ValueChanged += (sender, args) => Application.Current.Dispatcher.Invoke(() => - { - switch (args.NewValue) - { - case DownloadStateEnum.Finished: - model.Freeze(); - Downloading.Remove(model); - if (Downloaded.All(i => model.DownloadContent.GetDownloadUrl() != i.DownloadContent.GetDownloadUrl())) Downloaded.Add(model); - break; - case DownloadStateEnum.Downloading: - Downloaded.Remove(model); - Downloading.Add(model); - break; - case var stat when stat == DownloadStateEnum.Canceled || stat == DownloadStateEnum.Queue || stat == DownloadStateEnum.Exceptional: - if (stat == DownloadStateEnum.Canceled) Downloading.Remove(model); - break; - default: throw new ArgumentOutOfRangeException(); - } - }); - return model; - } - - if (illustration.IsManga) - for (var j = 0; j < illustration.MangaMetadata.Length; j++) - { - var cpy = j; - Task.Run(() => CreateDownloadableIllustration(illustration.MangaMetadata[cpy], true, option, cpy).Download()); - } - else - Task.Run(() => CreateDownloadableIllustration(illustration, false, option).Download()); - } - } - - public class SearchingHistoryManager - { - private static readonly ObservableCollection _searchingHistory = new ObservableCollection(); - - public static void EnqueueSearchHistory(string keyword) - { - if (_searchingHistory.Count == 4) _searchingHistory.RemoveAt(_searchingHistory.Count - 1); - _searchingHistory.Insert(0, keyword); - } - - public static IEnumerable GetSearchingHistory() - { - return _searchingHistory; - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/PixivClient.cs b/src/Pixeval/Core/PixivClient.cs deleted file mode 100644 index eaf4c3f7..00000000 --- a/src/Pixeval/Core/PixivClient.cs +++ /dev/null @@ -1,43 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -namespace Pixeval.Core -{ - public sealed class PixivClient - { - private static volatile PixivClient _instance; - - private static readonly object _locker = new object(); - - public static PixivClient Instance - { - get - { - if (_instance == null) - lock (_locker) - { - _instance ??= new PixivClient(); - } - - return _instance; - } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/PixivClientExtension.cs b/src/Pixeval/Core/PixivClientExtension.cs deleted file mode 100644 index 8edfd13c..00000000 --- a/src/Pixeval/Core/PixivClientExtension.cs +++ /dev/null @@ -1,94 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using AngleSharp.Html.Parser; -using Pixeval.Data.ViewModel; -using Pixeval.Data.Web.Delegation; -using Pixeval.Data.Web.Request; - -namespace Pixeval.Core -{ - public static class PixivClientExtension - { - public static async void PostFavoriteAsync(this PixivClient _, Illustration illustration, RestrictPolicy restrictPolicy) - { - illustration.IsLiked = true; - await HttpClientFactory.AppApiService().AddBookmark(new AddBookmarkRequest {Id = illustration.Id, Restrict = restrictPolicy == RestrictPolicy.Public ? "public" : "private"}); - } - - public static async void RemoveFavoriteAsync(this PixivClient _, Illustration illustration) - { - illustration.IsLiked = false; - await HttpClientFactory.AppApiService().DeleteBookmark(new DeleteBookmarkRequest {IllustId = illustration.Id}); - } - - public static async Task> GetArticleWorks(this PixivClient _, string spotlightId) - { - var httpClient = new HttpClient(); - var html = await httpClient.GetStringAsync($"https://www.pixivision.net/en/a/{spotlightId}"); - - var doc = await new HtmlParser().ParseDocumentAsync(html); - - return doc.QuerySelectorAll(".am__body .am__work").Select(element => element.Children[1].Children[0].GetAttribute("href")).Select(url => Regex.Match(url, "https://www.pixiv.net/artworks/(?\\d+)").Groups["Id"].Value); - } - - public static async Task FollowArtist(this PixivClient _, User user, RestrictPolicy policy) - { - user.IsFollowed = true; - await HttpClientFactory.AppApiService().FollowArtist(new FollowArtistRequest {Id = user.Id, Restrict = policy == RestrictPolicy.Private ? "private" : "public"}); - } - - public static async Task UnFollowArtist(this PixivClient _, User user) - { - user.IsFollowed = false; - await HttpClientFactory.AppApiService().UnFollowArtist(new UnFollowArtistRequest {UserId = user.Id}); - } - - public static async Task> GetTrendingTags(this PixivClient _) - { - var result = await HttpClientFactory.AppApiService().GetTrendingTags(); - var list = new List(); - if (result is { } res) list.AddRange(res.TrendTags.Select(tag => new TrendingTag {Tag = tag.TagStr, TranslatedName = tag.TranslatedName, Thumbnail = tag.Illust.ImageUrls.SquareMedium})); - return list; - } - - public static async ValueTask ToggleWebApiR18State(this PixivClient _, bool isR18On) - { - try - { - var html = await HttpClientFactory.WebApiHttpClient().GetStringAsync("https://www.pixiv.net/setting_user.php"); - var doc = await new HtmlParser().ParseDocumentAsync(html); - - var tt = doc.QuerySelectorAll(".settingContent form input")[1].GetAttribute("value"); - await HttpClientFactory.WebApiService().ToggleR18State(new ToggleR18StateRequest {R18 = isR18On ? "show" : "hide", R18G = isR18On ? "2" : "1", Tt = tt}); - return true; - } - catch - { - return false; - } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/PixivHelper.cs b/src/Pixeval/Core/PixivHelper.cs deleted file mode 100644 index 93cd4139..00000000 --- a/src/Pixeval/Core/PixivHelper.cs +++ /dev/null @@ -1,129 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Pixeval.Data.ViewModel; -using Pixeval.Data.Web.Delegation; -using Pixeval.Data.Web.Response; -using Pixeval.Objects.Exceptions.Logger; -using Pixeval.Objects.Generic; -using Pixeval.Objects.Primitive; -using Refit; - -namespace Pixeval.Core -{ - public class PixivHelper - { - public static async Task IllustrationInfo(string id) - { - SingleWorkResponse.Illust response; - try - { - response = (await HttpClientFactory.AppApiService().GetSingle(id)).IllustInfo; - } - catch (ApiException e) - { - ExceptionDumper.WriteException(e); - return null; - } - catch (Exception) - { - return null; - } - - var illust = new Illustration - { - Bookmark = (int) response.TotalBookmarks, - Id = response.Id.ToString(), - IsLiked = response.IsBookmarked, - IsManga = response.PageCount != 1, - IsUgoira = response.Type == "ugoira", - Origin = response.ImageUrls.Original ?? response.MetaSinglePage.OriginalImageUrl, - Large = response.ImageUrls.Large, - Tags = response.Tags.Select(t => new Tag {Name = t.Name, TranslatedName = t.TranslatedName}), - Thumbnail = response.ImageUrls.Medium, - Title = response.Title, - UserName = response.User.Name, - UserId = response.User.Id.ToString(), - ViewCount = (int) response.TotalView, - Comments = (int) response.TotalComments, - Resolution = $"{response.Width}x{response.Height}", - PublishDate = response.CreateDate - }; - - if (illust.IsManga && response.MetaPages != null) - illust.MangaMetadata = response.MetaPages.Select(p => - { - var page = (Illustration) illust.Clone(); - page.Thumbnail = p.ImageUrls.Medium; - page.Origin = p.ImageUrls.Original; - page.Large = p.ImageUrls.Large; - return page; - }).ToArray(); - - return illust; - } - - public static async void Enumerate(IPixivAsyncEnumerable pixivIterator, IList container, int limit = -1) - { - EnumeratingSchedule.StartNewInstance(pixivIterator); - var enumerator = EnumeratingSchedule.GetCurrentEnumerator(); - - await foreach (var illust in enumerator) - { - if (enumerator.IsCancellationRequested() || limit != -1 && pixivIterator.RequestedPages > limit) break; - if (pixivIterator.VerifyRationality(illust, container)) pixivIterator.InsertionPolicy(illust, container); - } - } - - public static void RecordTimeline(ITimelineService service, BrowsingHistory browsingHistory) - { - if (service.VerifyRationality(browsingHistory)) service.Insert(browsingHistory); - } - - public static void RecordTimelineInternal(BrowsingHistory browsingHistory) - { - RecordTimeline(BrowsingHistoryAccessor.GlobalLifeTimeScope, browsingHistory); - if (CheckWindowsVersion()) RecordTimeline(WindowsUserActivityManager.GlobalLifeTimeScope, browsingHistory); - - static bool CheckWindowsVersion() - { - return Environment.OSVersion.Version - >= /* Windows 10 April 2018 Update(a.k.a. Redstone 4), which is the version that release Windows Timeline feature */ - new Version(10, 0, 17134); - } - } - - public static bool VerifyIllustRational(ISet excludeTag, ISet includeTag, int minBookmark, Illustration illustration) - { - if (illustration == null) return false; - bool excludeMatch = true, includeMatch = true; - if (!excludeTag.IsNullOrEmpty()) excludeMatch = excludeTag.All(x => x.IsNullOrEmpty() || illustration.Tags.All(i => !i.Name.EqualsIgnoreCase(x))); - - if (!includeTag.IsNullOrEmpty()) includeMatch = includeTag.All(x => x.IsNullOrEmpty() || illustration.Tags.Any(i => i.Name.EqualsIgnoreCase(x))); - - var minBookmarkMatch = illustration.Bookmark > minBookmark; - return excludeMatch && includeMatch && minBookmarkMatch; - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/PixivIO.cs b/src/Pixeval/Core/PixivIO.cs deleted file mode 100644 index 7eafd3ba..00000000 --- a/src/Pixeval/Core/PixivIO.cs +++ /dev/null @@ -1,98 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Buffers; -using System.IO; -using System.Threading; -using System.Threading.Tasks; -using System.Windows.Media.Imaging; -using Pixeval.Data.Web.Delegation; -using Pixeval.Objects.Generic; -using Pixeval.Objects.Primitive; - -namespace Pixeval.Core -{ - // ReSharper disable once InconsistentNaming - public static class PixivIO - { - public static async Task GetBytes(string url) - { - var client = HttpClientFactory.PixivImage(); - - byte[] res; - try - { - res = await client.GetByteArrayAsync(url); - } - catch - { - return null; - } - - return res; - } - - public static async Task FromUrl(string url) - { - return await FromByteArray(await GetBytes(url)); - } - - public static async Task FromByteArray(byte[] bArr) - { - if (bArr == null || bArr.Length == 0) return null; - await using var memoryStream = new MemoryStream(bArr); - return InternalIO.CreateBitmapImageFromStream(memoryStream); - } - - public static async Task GetResizedBase64UriOfImageFromUrl(string url, string type = null) - { - return $"data:image/{type ?? url[(url.LastIndexOf('.') + 1)..]};base64,{Convert.ToBase64String(await GetBytes(url))}"; - } - - public static async Task Download(string url, IProgress progress, CancellationToken cancellationToken = default) - { - using var response = await HttpClientFactory.GetResponseHeader(HttpClientFactory.PixivImage().Apply(_ => _.Timeout = TimeSpan.FromSeconds(30)), url); - - var contentLength = response.Content.Headers.ContentLength; - if (!contentLength.HasValue) return new MemoryStream(await GetBytes(url)); - - response.EnsureSuccessStatusCode(); - - long bytesRead, totalRead = 0L; - var byteBuffer = ArrayPool.Shared.Rent(4096); - - var memoryStream = new MemoryStream(); - await using var contentStream = await response.Content.ReadAsStreamAsync(); - while ((bytesRead = await contentStream.ReadAsync(byteBuffer, 0, byteBuffer.Length, cancellationToken)) != 0) - { - cancellationToken.ThrowIfCancellationRequested(); - totalRead += bytesRead; - await memoryStream.WriteAsync(byteBuffer, 0, (int) bytesRead, cancellationToken); - progress.Report(totalRead / (double) contentLength); - } - - cancellationToken.ThrowIfCancellationRequested(); - ArrayPool.Shared.Return(byteBuffer, true); - - return memoryStream; - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/PluggableProtocolListener.cs b/src/Pixeval/Core/PluggableProtocolListener.cs deleted file mode 100644 index 7af47e66..00000000 --- a/src/Pixeval/Core/PluggableProtocolListener.cs +++ /dev/null @@ -1,50 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Threading.Tasks; -using EmbedIO; -using EmbedIO.Routing; -using EmbedIO.WebApi; -using Pixeval.Objects.Primitive; -using Pixeval.UI; - -namespace Pixeval.Core -{ - public class TransferController : WebApiController - { - [Route(HttpVerbs.Post, "/open")] - public async Task DoOpen() - { - MainWindow.Instance.Dispatcher.Invoke(() => MainWindow.Instance.GlobalActivate()); - await PluggableProtocolParser.Parse(await HttpContext.GetRequestBodyAsStringAsync()); - } - } - - public class PluggableProtocolListener - { - private static WebServer _server; - - public static void StartServer() - { - _server = new WebServer(o => o.WithUrlPrefix("http://127.0.0.1:12547").WithMode(HttpListenerMode.Microsoft)).WithWebApi("/", m => m.WithController()); - _server.Start(); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/PluggableProtocolParser.cs b/src/Pixeval/Core/PluggableProtocolParser.cs deleted file mode 100644 index 13817c97..00000000 --- a/src/Pixeval/Core/PluggableProtocolParser.cs +++ /dev/null @@ -1,105 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Globalization; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using AngleSharp.Html.Parser; -using MahApps.Metro.Controls; -using Pixeval.Data.ViewModel; -using Pixeval.Data.Web.Delegation; -using Pixeval.Objects.Generic; -using Pixeval.UI; -using Refit; - -namespace Pixeval.Core -{ - public class PluggableProtocolParser - { - private const string IllustRegex = "pixeval://(www\\.)?pixiv\\.net/artworks/(?\\d+)"; - private const string UserRegex = "pixeval://(www\\.)?pixiv\\.net/users/(?\\d+)"; - private const string SpotlightRegex = "pixeval://(www\\.)?pixivision\\.net/\\w{2}/a/(?\\d+)"; - - public static async Task Parse(string url) - { - Match match; - if ((match = Regex.Match(url, IllustRegex)).Success) - { - var i = MainWindow.Instance; - await i.Invoke(async () => - { - if (i.IllustBrowserDialogHost.IsOpen) i.IllustBrowserDialogHost.CurrentSession.Close(); - i.OpenIllustBrowser(await PixivHelper.IllustrationInfo(match.Groups["id"].Value), false); - }); - } - else if ((match = Regex.Match(url, UserRegex)).Success) - { - var i = MainWindow.Instance; - i.Invoke(() => - { - i.SetUserBrowserContext(new User {Id = match.Groups["id"].Value}); - i.OpenUserBrowser(); - }); - } - else if ((match = Regex.Match(url, SpotlightRegex)).Success) - { - var articleId = match.Groups["id"].Value; - string title; - - // if the current culture is set to en-XX, then we will simply analyze the html and get the title - if (CultureInfo.CurrentCulture.Name.ToLower().StartsWith("en")) - title = await TryGetSpotlightEnTitle(articleId); - else // otherwise, we will try to access the spotlight web API, and analyze html if failed - try - { - title = (await HttpClientFactory.WebApiService().GetSpotlightArticles(articleId)).BodyList[0].Title; - } - catch (ApiException e) - { - if (e.StatusCode == HttpStatusCode.NotFound) - title = await TryGetSpotlightEnTitle(articleId); - else - throw; - } - - var tasks = await Tasks.Of(await PixivClient.Instance.GetArticleWorks(articleId)).Mapping(PixivHelper.IllustrationInfo).Construct().WhenAll(); - var result = tasks.Peek(i => - { - i.IsManga = true; - i.FromSpotlight = true; - i.SpotlightTitle = title; - }).ToArray(); - - MainWindow.Instance.Invoke(() => MainWindow.Instance.OpenIllustBrowser(result[0].Apply(r => r.MangaMetadata = result.ToArray()), false)); - - static async Task TryGetSpotlightEnTitle(string id) - { - var httpClient = new HttpClient(); - var html = await httpClient.GetStringAsync($"https://www.pixivision.net/en/a/{id}"); - var doc = await new HtmlParser().ParseDocumentAsync(html); - return doc.QuerySelectorAll(".am__title")[0].InnerHtml; - } - } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/QueryAsyncEnumerable.cs b/src/Pixeval/Core/QueryAsyncEnumerable.cs deleted file mode 100644 index 79e8643c..00000000 --- a/src/Pixeval/Core/QueryAsyncEnumerable.cs +++ /dev/null @@ -1,169 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Pixeval.Data.ViewModel; -using Pixeval.Data.Web; -using Pixeval.Data.Web.Delegation; -using Pixeval.Data.Web.Response; -using Pixeval.Objects.Exceptions; -using Pixeval.Objects.Generic; -using Pixeval.Objects.I18n; -using Pixeval.Objects.Primitive; -using Pixeval.Persisting; - -namespace Pixeval.Core -{ - public abstract class AbstractQueryAsyncEnumerable : AbstractPixivAsyncEnumerable - { - private readonly SearchTagMatchOption _matchOption; - private readonly int _start; - private readonly string _tag; - protected readonly bool IsPremium; - - protected AbstractQueryAsyncEnumerable(string tag, SearchTagMatchOption matchOption, bool isPremium, int start = 1) - { - _start = start < 1 ? 1 : start; - _tag = tag; - _matchOption = matchOption; - IsPremium = isPremium; - } - - public override int RequestedPages { get; protected set; } - - public abstract override void InsertionPolicy(Illustration item, IList collection); - - public override bool VerifyRationality(Illustration item, IList collection) - { - return item != null && collection.All(t => t.Id != item.Id) && PixivHelper.VerifyIllustRational(Settings.Global.ExcludeTag, Settings.Global.IncludeTag, Settings.Global.MinBookmark, item); - } - - public override IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) - { - return new QueryAsyncEnumerator(this, _tag, _matchOption, _start, IsPremium); - } - - private class QueryAsyncEnumerator : AbstractPixivAsyncEnumerator - { - private readonly int _current; - private readonly bool _isPremium; - private readonly string _keyword; - private readonly SearchTagMatchOption _matchOption; - - private QueryWorksResponse _entity; - - private IEnumerator _illustrationsEnumerator; - - public QueryAsyncEnumerator(IPixivAsyncEnumerable enumerable, string keyword, SearchTagMatchOption matchOption, int current, bool isPremium) : base(enumerable) - { - _keyword = keyword; - _matchOption = matchOption; - _current = current; - _isPremium = isPremium; - } - - public override Illustration Current => _illustrationsEnumerator.Current; - - protected override void UpdateEnumerator() - { - _illustrationsEnumerator = _entity.Illusts.NonNull().Select(_ => _.Parse()).GetEnumerator(); - } - - public override async ValueTask MoveNextAsync() - { - if (_entity == null) - { - if (await TryGetResponse($"/v1/search/illust?search_target={_matchOption.GetEnumAttribute().AliasAs}&sort={(_isPremium ? "date_desc" : "popular_desc")}&word={_keyword}&filter=for_android&offset={(_current - 1) * 30}") is (true, var model)) - { - _entity = model; - UpdateEnumerator(); - } - else - { - throw new QueryNotRespondingException(); - } - - Enumerable.ReportRequestedPages(); - } - - if (_illustrationsEnumerator.MoveNext()) return true; - - if (int.Parse(_entity.NextUrl[(_entity.NextUrl.LastIndexOf('=') + 1)..]) >= 5000) return false; - - if (await TryGetResponse(_entity.NextUrl) is (true, var res)) - { - _entity = res; - UpdateEnumerator(); - Enumerable.ReportRequestedPages(); - return true; - } - - return false; - } - - private static async Task> TryGetResponse(string url) - { - var res = (await HttpClientFactory.AppApiHttpClient().Apply(h => h.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Language", AkaI18N.GetCultureAcceptLanguage())).GetStringAsync(url)).FromJson(); - if (res is { } response && !response.Illusts.IsNullOrEmpty()) return HttpResponse.Wrap(true, response); - - return HttpResponse.Wrap(false); - } - } - } - - public class PopularityQueryAsyncEnumerable : AbstractQueryAsyncEnumerable - { - public PopularityQueryAsyncEnumerable(string tag, SearchTagMatchOption matchOption, bool isPremium, int start = 1) : base(tag, matchOption, isPremium, start) - { - } - - public override void InsertionPolicy(Illustration item, IList collection) - { - if (item != null) - { - if (IsPremium) - collection.Add(item); - else - collection.AddSorted(item, IllustrationPopularityComparator.Instance); - } - } - } - - public class PublishDateQueryAsyncEnumerable : AbstractQueryAsyncEnumerable - { - public PublishDateQueryAsyncEnumerable(string tag, SearchTagMatchOption matchOption, bool isPremium, int start = 1) : base(tag, matchOption, isPremium, start) - { - } - - public override void InsertionPolicy(Illustration item, IList collection) - { - if (item != null) - { - if (IsPremium) - collection.Add(item); - else - collection.AddSorted(item, IllustrationPopularityComparator.Instance); - } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/RankOption.cs b/src/Pixeval/Core/RankOption.cs deleted file mode 100644 index e22d1e0f..00000000 --- a/src/Pixeval/Core/RankOption.cs +++ /dev/null @@ -1,136 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using Pixeval.Objects.Primitive; - -namespace Pixeval.Core -{ - [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] - public class ForR18Only : Attribute - { - } - - public enum RankOption - { - /// - /// 日榜 - /// - [EnumAlias("day")] - [EnumLocalizedName("RankOptionDay")] - Day, - - /// - /// 周榜 - /// - [EnumAlias("week")] - [EnumLocalizedName("RankOptionWeek")] - Week, - - /// - /// 月榜 - /// - [EnumAlias("month")] - [EnumLocalizedName("RankOptionMonth")] - Month, - - /// - /// 男性向日榜 - /// - [EnumAlias("day_male")] - [EnumLocalizedName("RankOptionDayMale")] - DayMale, - - /// - /// 女性向日榜 - /// - [EnumAlias("day_female")] - [EnumLocalizedName("RankOptionDayFemale")] - DayFemale, - - /// - /// 多图日榜 - /// - [EnumAlias("day_manga")] - [EnumLocalizedName("RankOptionDayManga")] - DayManga, - - /// - /// 多图周榜 - /// - [EnumAlias("week_manga")] - [EnumLocalizedName("RankOptionWeekManga")] - WeekManga, - - /// - /// 原创 - /// - [EnumAlias("week_original")] - [EnumLocalizedName("RankOptionWeekOriginal")] - WeekOriginal, - - /// - /// 新人 - /// - [EnumAlias("week_rookie")] - [EnumLocalizedName("RankOptionWeekRookie")] - WeekRookie, - - /// - /// R18日榜 - /// - [ForR18Only] - [EnumAlias("day_r18")] - [EnumLocalizedName("RankOptionDayR18")] - DayR18, - - /// - /// 男性向R18日榜 - /// - [ForR18Only] - [EnumAlias("day_male_r18")] - [EnumLocalizedName("RankOptionDayMaleR18")] - DayMaleR18, - - /// - /// 女性向R18日榜 - /// - [ForR18Only] - [EnumAlias("day_female_r18")] - [EnumLocalizedName("RankOptionDayFemaleR18")] - DayFemaleR18, - - /// - /// R18周榜 - /// - [ForR18Only] - [EnumAlias("week_r18")] - [EnumLocalizedName("RankOptionWeekR18")] - WeekR18, - - /// - /// R18G周榜 - /// - [ForR18Only] - [EnumAlias("week_r18g")] - [EnumLocalizedName("RankOptionWeekR18G")] - WeekR18G - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/RankingAsyncEnumerable.cs b/src/Pixeval/Core/RankingAsyncEnumerable.cs deleted file mode 100644 index 9c8f5c3d..00000000 --- a/src/Pixeval/Core/RankingAsyncEnumerable.cs +++ /dev/null @@ -1,128 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Pixeval.Data.ViewModel; -using Pixeval.Data.Web; -using Pixeval.Data.Web.Delegation; -using Pixeval.Data.Web.Response; -using Pixeval.Objects.Exceptions; -using Pixeval.Objects.Generic; -using Pixeval.Objects.I18n; -using Pixeval.Objects.Primitive; -using Pixeval.Persisting; - -namespace Pixeval.Core -{ - public class RankingAsyncEnumerable : AbstractPixivAsyncEnumerable - { - private readonly DateTime _dateTime; - private readonly RankOption _rankOption; - - public RankingAsyncEnumerable(RankOption rankOption, DateTime dateTime) - { - _rankOption = rankOption; - _dateTime = dateTime; - } - - public override int RequestedPages { get; protected set; } - - public override bool VerifyRationality(Illustration item, IList collection) - { - return item != null && collection.All(t => t.Id != item.Id) && PixivHelper.VerifyIllustRational(Settings.Global.ExcludeTag, Settings.Global.IncludeTag, Settings.Global.MinBookmark, item); - } - - public override void InsertionPolicy(Illustration item, IList collection) - { - collection.Add(item); - } - - public override IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) - { - return new RankingAsyncEnumerator(this, _rankOption, _dateTime); - } - - private class RankingAsyncEnumerator : AbstractPixivAsyncEnumerator - { - private readonly string _dateTimeParameter; - private readonly string _rankOptionParameter; - private RankingResponse _entity; - - private IEnumerator _illustrationEnumerator; - - public RankingAsyncEnumerator(IPixivAsyncEnumerable enumerable, RankOption rankOption, DateTime dateTime) : base(enumerable) - { - _rankOptionParameter = rankOption.GetEnumAttribute().AliasAs; - _dateTimeParameter = dateTime.ToString("yyyy-MM-dd"); - } - - public override Illustration Current => _illustrationEnumerator.Current; - - protected override void UpdateEnumerator() - { - _illustrationEnumerator = _entity.Illusts.NonNull().Select(_ => _.Parse()).GetEnumerator(); - } - - public override async ValueTask MoveNextAsync() - { - if (_entity == null) - { - if (await TryGetResponse($"/v1/illust/ranking?filter=for_android&mode={_rankOptionParameter}&date={_dateTimeParameter}") is (true, var result)) - { - _entity = result; - UpdateEnumerator(); - } - else - { - throw new QueryNotRespondingException(); - } - - Enumerable.ReportRequestedPages(); - } - - if (_illustrationEnumerator.MoveNext()) return true; - - if (_entity.NextUrl.IsNullOrEmpty()) return false; - - if (await TryGetResponse(_entity.NextUrl) is (true, var model)) - { - _entity = model; - UpdateEnumerator(); - Enumerable.ReportRequestedPages(); - return true; - } - - return false; - } - - private static async Task> TryGetResponse(string url) - { - var result = (await HttpClientFactory.AppApiHttpClient().Apply(h => h.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Language", AkaI18N.GetCultureAcceptLanguage())).GetStringAsync(url)).FromJson(); - - if (result is { } response && !response.Illusts.IsNullOrEmpty()) return HttpResponse.Wrap(true, response); - return HttpResponse.Wrap(false); - } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/RecommendAsyncEnumerable.cs b/src/Pixeval/Core/RecommendAsyncEnumerable.cs deleted file mode 100644 index b0cbd70f..00000000 --- a/src/Pixeval/Core/RecommendAsyncEnumerable.cs +++ /dev/null @@ -1,127 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Pixeval.Data.ViewModel; -using Pixeval.Data.Web; -using Pixeval.Data.Web.Delegation; -using Pixeval.Data.Web.Response; -using Pixeval.Objects.Exceptions; -using Pixeval.Objects.Generic; -using Pixeval.Objects.I18n; -using Pixeval.Objects.Primitive; -using Pixeval.Persisting; - -namespace Pixeval.Core -{ - public abstract class AbstractRecommendAsyncEnumerable : AbstractPixivAsyncEnumerable - { - public override int RequestedPages { get; protected set; } - - public abstract override void InsertionPolicy(Illustration item, IList collection); - - public override bool VerifyRationality(Illustration item, IList collection) - { - return item != null && collection.All(t => t.Id != item.Id) && PixivHelper.VerifyIllustRational(Settings.Global.ExcludeTag, Settings.Global.IncludeTag, Settings.Global.MinBookmark, item); - } - - public override IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) - { - return new RecommendAsyncEnumerator(this); - } - - private class RecommendAsyncEnumerator : AbstractPixivAsyncEnumerator - { - private RecommendResponse _entity; - - private IEnumerator _illustrationEnumerator; - - public RecommendAsyncEnumerator(IPixivAsyncEnumerable enumerable) : base(enumerable) - { - } - - public override Illustration Current => _illustrationEnumerator.Current; - - protected override void UpdateEnumerator() - { - _illustrationEnumerator = _entity.Illusts.NonNull().Select(_ => _.Parse()).GetEnumerator(); - } - - public override async ValueTask MoveNextAsync() - { - if (_entity == null) - { - if (await TryGetResponse("/v1/illust/recommended") is (true, var model)) - { - _entity = model; - UpdateEnumerator(); - } - else - { - throw new QueryNotRespondingException(); - } - - Enumerable.ReportRequestedPages(); - } - - if (_illustrationEnumerator.MoveNext()) return true; - - if (_entity.NextUrl.IsNullOrEmpty()) return false; - - if (await TryGetResponse(_entity.NextUrl) is (true, var res)) - { - _entity = res; - UpdateEnumerator(); - Enumerable.ReportRequestedPages(); - return true; - } - - return false; - } - - private static async Task> TryGetResponse(string url) - { - var res = (await HttpClientFactory.AppApiHttpClient().Apply(h => h.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Language", AkaI18N.GetCultureAcceptLanguage())).GetStringAsync(url)).FromJson(); - if (res is { } response && !response.Illusts.IsNullOrEmpty()) return HttpResponse.Wrap(true, response); - - return HttpResponse.Wrap(false); - } - } - } - - public class PopularityRecommendAsyncEnumerable : AbstractRecommendAsyncEnumerable - { - public override void InsertionPolicy(Illustration item, IList collection) - { - if (item != null) collection.AddSorted(item, IllustrationPopularityComparator.Instance); - } - } - - public class PublishDateRecommendAsyncEnumerable : AbstractRecommendAsyncEnumerable - { - public override void InsertionPolicy(Illustration item, IList collection) - { - if (item != null) collection.AddSorted(item, IllustrationPublishDateComparator.Instance); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/RecommendIllustratorDeferrer.cs b/src/Pixeval/Core/RecommendIllustratorDeferrer.cs deleted file mode 100644 index cd7450cb..00000000 --- a/src/Pixeval/Core/RecommendIllustratorDeferrer.cs +++ /dev/null @@ -1,68 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Pixeval.Data.ViewModel; -using Pixeval.Data.Web.Delegation; -using Pixeval.Data.Web.Request; - -namespace Pixeval.Core -{ - public class RecommendIllustratorDeferrer - { - public static readonly RecommendIllustratorDeferrer Instance = new RecommendIllustratorDeferrer(); - - private readonly List _currentIllustrators = new List(); - - private int _index; - - private int _requestTimes; - - public async Task> Acquire(int count) - { - if (30 % count != 0) throw new ArgumentException("count must be divisible by 30"); - - if (_currentIllustrators.Count < _index + count) - { - if (_requestTimes >= 9) - { - _index = 0; - _requestTimes = 0; - _currentIllustrators.Clear(); - } - - await Request(); - } - - var illustrators = _currentIllustrators.Skip(_index).Take(count); - _index += count; - return illustrators; - } - - private async Task Request() - { - var newIllustrators = await HttpClientFactory.AppApiService().GetRecommendIllustrators(new RecommendIllustratorRequest {Offset = _requestTimes++ * 30}); - _currentIllustrators.AddRange(newIllustrators.UserPreviews.Select(i => i.Parse())); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/RestrictPolicy.cs b/src/Pixeval/Core/RestrictPolicy.cs deleted file mode 100644 index 6d47b0a2..00000000 --- a/src/Pixeval/Core/RestrictPolicy.cs +++ /dev/null @@ -1,27 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -namespace Pixeval.Core -{ - public enum RestrictPolicy - { - Public, Private - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/SearchTagMatchOption.cs b/src/Pixeval/Core/SearchTagMatchOption.cs deleted file mode 100644 index 3c321824..00000000 --- a/src/Pixeval/Core/SearchTagMatchOption.cs +++ /dev/null @@ -1,48 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using Pixeval.Objects.Primitive; - -namespace Pixeval.Core -{ - public enum SearchTagMatchOption - { - /// - /// 部分一致 - /// - [EnumAlias("partial_match_for_tags")] - [EnumLocalizedName("TagMatchingPartialMatch")] - PartialMatchForTags, - - /// - /// 完全一致 - /// - [EnumAlias("exact_match_for_tags")] - [EnumLocalizedName("TagMatchingExactMatch")] - ExactMatchForTags, - - /// - /// 标题和说明文 - /// - [EnumAlias("title_and_caption")] - [EnumLocalizedName("TagMatchingTitleAndCaption")] - TitleAndCaption - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/SpotlightQueryAsyncEnumerable.cs b/src/Pixeval/Core/SpotlightQueryAsyncEnumerable.cs deleted file mode 100644 index 922b1c52..00000000 --- a/src/Pixeval/Core/SpotlightQueryAsyncEnumerable.cs +++ /dev/null @@ -1,112 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using Pixeval.Data.ViewModel; -using Pixeval.Data.Web; -using Pixeval.Data.Web.Delegation; -using Pixeval.Data.Web.Response; -using Pixeval.Objects.Exceptions; -using Pixeval.Objects.Generic; -using Pixeval.Objects.Primitive; - -namespace Pixeval.Core -{ - public class SpotlightQueryAsyncEnumerable : AbstractPixivAsyncEnumerable - { - private readonly int _start; - - public SpotlightQueryAsyncEnumerable(int start) - { - _start = start < 1 ? 1 : start; - } - - public override int RequestedPages { get; protected set; } - - public override IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) - { - return new SpotlightArticleAsyncEnumerator(this, _start); - } - - private class SpotlightArticleAsyncEnumerator : AbstractPixivAsyncEnumerator - { - private int _current; - - private SpotlightResponse _entity; - - private IEnumerator _spotlightArticleEnumerator; - - public SpotlightArticleAsyncEnumerator(IPixivAsyncEnumerable enumerable, int current) : base(enumerable) - { - _current = current; - } - - public override SpotlightArticle Current => _spotlightArticleEnumerator.Current; - - protected override void UpdateEnumerator() - { - _spotlightArticleEnumerator = _entity.SpotlightArticles.NonNull().GetEnumerator(); - } - - public override async ValueTask MoveNextAsync() - { - if (_entity == null) - { - if (await TryGetResponse() is (true, var model)) - { - _entity = model; - UpdateEnumerator(); - } - else - { - throw new QueryNotRespondingException(); - } - - Enumerable.ReportRequestedPages(); - } - - if (_spotlightArticleEnumerator.MoveNext()) return true; - - if (_entity.NextUrl.IsNullOrEmpty()) return false; - - if (await TryGetResponse() is (true, var res)) - { - _entity = res; - UpdateEnumerator(); - Enumerable.ReportRequestedPages(); - return true; - } - - return false; - } - - private async Task> TryGetResponse() - { - var res = await HttpClientFactory.AppApiService().GetSpotlights(_current++ * 10); - - if (res is { } response && !response.SpotlightArticles.IsNullOrEmpty()) return HttpResponse.Wrap(true, response); - - return HttpResponse.Wrap(false); - } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/TrendsAsyncEnumerable.cs b/src/Pixeval/Core/TrendsAsyncEnumerable.cs deleted file mode 100644 index e702a456..00000000 --- a/src/Pixeval/Core/TrendsAsyncEnumerable.cs +++ /dev/null @@ -1,229 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Text.RegularExpressions; -using System.Threading; -using System.Threading.Tasks; -using Newtonsoft.Json.Linq; -using Pixeval.Data.ViewModel; -using Pixeval.Data.Web; -using Pixeval.Data.Web.Delegation; -using Pixeval.Objects.Exceptions; -using Pixeval.Objects.Generic; -using Pixeval.Objects.I18n; -using Pixeval.Objects.Primitive; - -namespace Pixeval.Core -{ - /// - /// This class is piece of shit - /// - public class TrendsAsyncEnumerable : AbstractPixivAsyncEnumerable - { - public override int RequestedPages { get; protected set; } - - public override IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) - { - return new TrendsAsyncEnumerator(this); - } - - private class TrendsAsyncEnumerator : AbstractPixivAsyncEnumerator - { - private TrendsRequestContext _requestContext; - private IEnumerator _trendsEnumerable; - private string _tt; - - public TrendsAsyncEnumerator(IPixivAsyncEnumerable enumerable) : base(enumerable) - { - } - - public override Trends Current => _trendsEnumerable.Current; - - public override async ValueTask MoveNextAsync() - { - if (_requestContext == null) - { - if (await GetResponse(BuildRequestUrl()) is (true, var result)) - { - _tt = Regex.Match(result, "tt: \"(?.*)\"").Groups["tt"].Value; - _trendsEnumerable = (await ParsePreloadJsonFromHtml(result)).NonNull().GetEnumerator(); - _requestContext = ExtractRequestParametersFromHtml(result); - } - else - { - throw new QueryNotRespondingException(); - } - - Enumerable.ReportRequestedPages(); - } - - if (_trendsEnumerable.MoveNext()) return true; - - if (_requestContext.IsLastPage) return false; - - if (await GetResponse(BuildRequestUrl()) is (true, var json)) - { - _trendsEnumerable = (await ParseRawJson(json)).NonNull().GetEnumerator(); - _requestContext = ExtractRequestParametersFromRawJson(json); - Enumerable.ReportRequestedPages(); - return true; - } - - return false; - } - - private string BuildRequestUrl() - { - return _requestContext == null ? "/stacc?mode=unify" : $"/stacc/my/home/all/activity/{_requestContext.Sid}/.json?mode={_requestContext.Mode}&unify_token={_requestContext.UnifyToken}&tt={_tt}"; - } - - private static TrendsRequestContext ExtractRequestParametersFromHtml(string html) - { - var json = JObject.Parse(ExtractPreloadJsonSnippet(html)); - return new TrendsRequestContext {Mode = json["param"]?["mode"]?.Value(), UnifyToken = json["param"]?["unify_token"]?.Value(), Sid = json["next_max_sid"]?.Value().ToString(), IsLastPage = json["is_last_page"]?.Value() == 1}; - } - - private static TrendsRequestContext ExtractRequestParametersFromRawJson(string json) - { - var obj = JObject.Parse(json); - return new TrendsRequestContext {Mode = obj["stacc"]?["param"]?["mode"]?.Value(), UnifyToken = obj["stacc"]?["param"]?["unify_token"]?.Value(), Sid = obj["stacc"]?["next_max_sid"]?.Value().ToString(), IsLastPage = obj["stacc"]?["is_last_page"]?.Value() == 1}; - } - - private static Task> ParsePreloadJsonFromHtml(string html) - { - return ParsePreloadJson(ExtractPreloadJsonSnippet(html)); - } - - private static string ExtractPreloadJsonSnippet(string html) - { - var match = Regex.Match(html, "pixiv\\.stacc\\.env\\.preload\\.stacc \\= (?.*);"); - if (!match.Success) throw new QueryNotRespondingException(); - return match.Groups["json"].Value; - } - - private static Task> ParseRawJson(string json) - { - var stacc = JObject.Parse(json)["stacc"]?.ToString(); - return ParsePreloadJson(stacc); - } - - private static async Task> ParsePreloadJson(string json) - { - var tasks = new List>(); - var stacc = JObject.Parse(json); - var status = stacc["status"]; - var timeline = stacc["timeline"]; - var user = stacc["user"]; - var illust = stacc["illust"]; - foreach (var timelineChild in timeline!) - { - var task = Task.Run(() => - { - var timelineProp = timelineChild.First; - var statusObj = status?.FirstOrDefault(sChild => sChild.First?["id"]?.Value() == timelineProp?["id"]?.Value()); - if (statusObj?.First == null) return null; - var statusObjProp = statusObj.First; - var trendsObj = new Trends - { - PostDate = DateTime.Parse(statusObjProp?["post_date"]?.Value()!, CultureInfo.CurrentCulture), - PostUserId = statusObjProp["post_user"]?["id"]?.Value(), - TrendObjectId = statusObjProp["type"]?.Value() switch - { - var type when type == "add_illust" || type == "add_bookmark" => statusObjProp["ref_illust"]?["id"]?.Value(), - "add_favorite" => statusObjProp["ref_user"]?["id"]?.Value(), - _ => null - } - }; - var matchingPostUser = user?.FirstOrDefault(uChild => uChild.First?["id"]?.Value() == trendsObj.PostUserId); - if (matchingPostUser != null) - { - trendsObj.PostUserThumbnail = matchingPostUser.First?["profile_image"]?.First?.First?["url"]?["m"]?.Value(); - trendsObj.PostUserName = matchingPostUser.First?["name"]?.Value(); - } - else - { - return null; - } - - trendsObj.Type = statusObjProp["type"]?.Value() switch - { - "add_illust" => TrendType.AddIllust, - "add_bookmark" => TrendType.AddBookmark, - "add_favorite" => TrendType.AddFavorite, - _ => (TrendType) (-1) - }; - trendsObj.TrendObjectThumbnail = trendsObj.Type switch - { - var type when type == TrendType.AddBookmark || type == TrendType.AddIllust => illust?.FirstOrDefault(iChild => iChild.First?["id"]?.Value() == trendsObj.TrendObjectId)?.First?["url"]?["m"]?.Value(), - TrendType.AddFavorite => user.FirstOrDefault(uChild => uChild.First?["id"]?.Value() == trendsObj.TrendObjectId)?.First?["profile_image"]?.First?.First?["url"]?["s"]?.Value(), - (TrendType) (-1) => null, - _ => throw new ArgumentOutOfRangeException() - }; - if (trendsObj.Type != TrendType.AddFavorite) - { - var illustration = illust.FirstOrDefault(iChild => iChild.First?["id"]?.Value() == trendsObj.TrendObjectId); - if (illustration != null) - { - trendsObj.ByName = user.FirstOrDefault(uChild => uChild.First?["id"]?.Value() == illustration.First?["post_user"]?["id"]?.Value())?.First["name"].Value(); - trendsObj.TrendObjName = illustration.First["title"].Value(); - } - } - else - { - trendsObj.TrendObjName = user.FirstOrDefault(uChild => uChild.First?["id"]?.Value() == trendsObj.TrendObjectId)?.First["name"].Value(); - trendsObj.IsReferToUser = true; - } - - return trendsObj; - }); - tasks.Add(task); - } - - return await Task.WhenAll(tasks); - } - - protected override void UpdateEnumerator() - { - throw new NotImplementedException(); - } - - private static async Task> GetResponse(string url) - { - var result = await HttpClientFactory.WebApiHttpClient().Apply(h => h.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Language", AkaI18N.GetCultureAcceptLanguage())).GetStringAsync(url); - return !result.IsNullOrEmpty() ? HttpResponse.Wrap(true, result) : HttpResponse.Wrap(false); - } - } - - private class TrendsRequestContext - { - public string UnifyToken { get; set; } - - public string Sid { get; set; } - - public string Mode { get; set; } - - public bool IsLastPage { get; set; } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/UploadAsyncEnumerable.cs b/src/Pixeval/Core/UploadAsyncEnumerable.cs deleted file mode 100644 index 9c8c58c5..00000000 --- a/src/Pixeval/Core/UploadAsyncEnumerable.cs +++ /dev/null @@ -1,124 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Pixeval.Data.ViewModel; -using Pixeval.Data.Web; -using Pixeval.Data.Web.Delegation; -using Pixeval.Data.Web.Response; -using Pixeval.Objects.Exceptions; -using Pixeval.Objects.Generic; -using Pixeval.Objects.I18n; -using Pixeval.Objects.Primitive; -using Pixeval.Persisting; - -namespace Pixeval.Core -{ - public class UploadAsyncEnumerable : AbstractPixivAsyncEnumerable - { - private readonly string _uid; - - public UploadAsyncEnumerable(string uid) - { - _uid = uid; - } - - public override int RequestedPages { get; protected set; } - - public override void InsertionPolicy(Illustration item, IList collection) - { - if (item != null) collection.AddSorted(item, IllustrationPublishDateComparator.Instance); - } - - public override bool VerifyRationality(Illustration item, IList collection) - { - return item != null && collection.All(t => t.Id != item.Id) && PixivHelper.VerifyIllustRational(Settings.Global.ExcludeTag, Settings.Global.IncludeTag, Settings.Global.MinBookmark, item); - } - - public override IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) - { - return new UploadAsyncEnumerator(this, _uid); - } - - private class UploadAsyncEnumerator : AbstractPixivAsyncEnumerator - { - private readonly string _uid; - - private UploadResponse _entity; - - private IEnumerator _illustrationEnumerator; - - public UploadAsyncEnumerator(IPixivAsyncEnumerable enumerable, string uid) : base(enumerable) - { - _uid = uid; - } - - public override Illustration Current => _illustrationEnumerator.Current; - - protected override void UpdateEnumerator() - { - _illustrationEnumerator = _entity.Illusts.NonNull().Select(_ => _.Parse()).GetEnumerator(); - } - - public override async ValueTask MoveNextAsync() - { - if (_entity == null) - { - if (await TryGetResponse($"/v1/user/illusts?user_id={_uid}&filter=for_android&type=illust") is (true, var model)) - { - _entity = model; - UpdateEnumerator(); - } - else - { - throw new QueryNotRespondingException(); - } - - Enumerable.ReportRequestedPages(); - } - - if (_illustrationEnumerator.MoveNext()) return true; - - if (_entity.NextUrl.IsNullOrEmpty()) return false; - - if (await TryGetResponse(_entity.NextUrl) is (true, var res)) - { - _entity = res; - UpdateEnumerator(); - Enumerable.ReportRequestedPages(); - return true; - } - - return false; - } - - private static async Task> TryGetResponse(string url) - { - var res = (await HttpClientFactory.AppApiHttpClient().Apply(h => h.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Language", AkaI18N.GetCultureAcceptLanguage())).GetStringAsync(url)).FromJson(); - if (res is { } response && !response.Illusts.IsNullOrEmpty()) return HttpResponse.Wrap(true, response); - - return HttpResponse.Wrap(false); - } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/UserFollowingAsyncEnumerable.cs b/src/Pixeval/Core/UserFollowingAsyncEnumerable.cs deleted file mode 100644 index d1ad0c2d..00000000 --- a/src/Pixeval/Core/UserFollowingAsyncEnumerable.cs +++ /dev/null @@ -1,151 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Pixeval.Data.ViewModel; -using Pixeval.Data.Web; -using Pixeval.Data.Web.Delegation; -using Pixeval.Data.Web.Response; -using Pixeval.Objects.Exceptions; -using Pixeval.Objects.Generic; -using Pixeval.Objects.Primitive; - -namespace Pixeval.Core -{ - public abstract class AbstractUserFollowingAsyncEnumerable : AbstractPixivAsyncEnumerable - { - protected abstract string Uid { get; } - - protected abstract RestrictPolicy RestrictPolicy { get; } - - public override int RequestedPages { get; protected set; } - - public override IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) - { - return new UserFollowingAsyncEnumerator(this, Uid, RestrictPolicy); - } - - public static AbstractUserFollowingAsyncEnumerable Of(string uid, RestrictPolicy restrictPolicy) - { - return restrictPolicy switch - { - RestrictPolicy.Public => new PublicUserFollowingAsyncEnumerable(uid), - RestrictPolicy.Private => new PrivateUserFollowingAsyncEnumerable(uid), - _ => throw new ArgumentOutOfRangeException(nameof(restrictPolicy), restrictPolicy, null) - }; - } - - private class UserFollowingAsyncEnumerator : AbstractPixivAsyncEnumerator - { - private readonly RestrictPolicy _restrictPolicy; - private readonly string _userId; - - private FollowingResponse _entity; - - private IEnumerator _followerEnumerator; - - public UserFollowingAsyncEnumerator(IPixivAsyncEnumerable enumerable, string userId, RestrictPolicy restrictPolicy) : base(enumerable) - { - _userId = userId; - _restrictPolicy = restrictPolicy; - } - - public override User Current => _followerEnumerator.Current; - - protected override void UpdateEnumerator() - { - _followerEnumerator = _entity.UserPreviews.NonNull().Select(u => new User {Thumbnails = u.Illusts.NonNull().Select(_ => _.ImageUrls.SquareMedium).ToArray(), Id = u.User.Id.ToString(), Name = u.User.Name, Avatar = u.User.ProfileImageUrls.Medium}).GetEnumerator(); - } - - public override async ValueTask MoveNextAsync() - { - if (_entity == null) - { - if (await TryGetResponse(_restrictPolicy switch - { - RestrictPolicy.Public => $"/v1/user/following?user_id={_userId}&restrict=public", - RestrictPolicy.Private => $"/v1/user/following?user_id={_userId}&restrict=private", - _ => throw new ArgumentOutOfRangeException() - }) is (true, var model)) - { - _entity = model; - UpdateEnumerator(); - } - else - { - throw new QueryNotRespondingException(); - } - - Enumerable.ReportRequestedPages(); - } - - if (_followerEnumerator.MoveNext()) return true; - - if (_entity.NextUrl.IsNullOrEmpty()) return false; - - if (await TryGetResponse(_entity.NextUrl) is (true, var res)) - { - _entity = res; - UpdateEnumerator(); - Enumerable.ReportRequestedPages(); - return true; - } - - return false; - } - - private static async Task> TryGetResponse(string url) - { - var res = (await HttpClientFactory.AppApiHttpClient().GetStringAsync(url)).FromJson(); - if (res is { } response && !response.UserPreviews.IsNullOrEmpty()) return HttpResponse.Wrap(true, response); - - return HttpResponse.Wrap(false); - } - } - } - - public class PublicUserFollowingAsyncEnumerable : AbstractUserFollowingAsyncEnumerable - { - public PublicUserFollowingAsyncEnumerable(string uid) - { - Uid = uid; - } - - protected override string Uid { get; } - - protected override RestrictPolicy RestrictPolicy { get; } = RestrictPolicy.Public; - } - - public class PrivateUserFollowingAsyncEnumerable : AbstractUserFollowingAsyncEnumerable - { - public PrivateUserFollowingAsyncEnumerable(string uid) - { - Uid = uid; - } - - protected override string Uid { get; } - - protected override RestrictPolicy RestrictPolicy { get; } = RestrictPolicy.Private; - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/UserPreviewAsyncEnumerable.cs b/src/Pixeval/Core/UserPreviewAsyncEnumerable.cs deleted file mode 100644 index e6af8585..00000000 --- a/src/Pixeval/Core/UserPreviewAsyncEnumerable.cs +++ /dev/null @@ -1,111 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Pixeval.Data.ViewModel; -using Pixeval.Data.Web; -using Pixeval.Data.Web.Delegation; -using Pixeval.Data.Web.Response; -using Pixeval.Objects.Exceptions; -using Pixeval.Objects.Generic; -using Pixeval.Objects.Primitive; - -namespace Pixeval.Core -{ - public class UserPreviewAsyncEnumerable : AbstractPixivAsyncEnumerable - { - private readonly string _keyword; - - public UserPreviewAsyncEnumerable(string keyword) - { - _keyword = keyword; - } - - public override int RequestedPages { get; protected set; } - - public override IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) - { - return new UserPreviewAsyncEnumerator(this, _keyword); - } - - private class UserPreviewAsyncEnumerator : AbstractPixivAsyncEnumerator - { - private readonly string _keyword; - private UserNavResponse _entity; - - private IEnumerator _userPreviewEnumerator; - - public UserPreviewAsyncEnumerator(IPixivAsyncEnumerable enumerable, string keyword) : base(enumerable) - { - _keyword = keyword; - } - - public override User Current => _userPreviewEnumerator.Current; - - protected override void UpdateEnumerator() - { - _userPreviewEnumerator = _entity.UserPreviews.NonNull().Select(u => new User {Avatar = u.User.ProfileImageUrls.Medium, Thumbnails = u.Illusts.NonNull().Select(_ => _.ImageUrl.SquareMedium).ToArray(), Id = u.User.Id.ToString(), Name = u.User.Name}).GetEnumerator(); - } - - public override async ValueTask MoveNextAsync() - { - if (_entity == null) - { - if (await TryGetResponse($"https://app-api.pixiv.net/v1/search/user?filter=for_android&word={_keyword}") is (true, var model)) - { - _entity = model; - UpdateEnumerator(); - } - else - { - throw new QueryNotRespondingException(); - } - - Enumerable.ReportRequestedPages(); - } - - if (_userPreviewEnumerator.MoveNext()) return true; - - if (_entity.NextUrl.IsNullOrEmpty()) return false; - - if (await TryGetResponse(_entity.NextUrl) is (true, var res)) - { - _entity = res; - UpdateEnumerator(); - Enumerable.ReportRequestedPages(); - return true; - } - - return false; - } - - private static async Task> TryGetResponse(string url) - { - var res = (await HttpClientFactory.AppApiHttpClient().GetStringAsync(url)).FromJson(); - if (res is { } response && !response.UserPreviews.IsNullOrEmpty()) return HttpResponse.Wrap(true, response); - - return HttpResponse.Wrap(false); - } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/UserUpdateAsyncEnumerable.cs b/src/Pixeval/Core/UserUpdateAsyncEnumerable.cs deleted file mode 100644 index b7ce0968..00000000 --- a/src/Pixeval/Core/UserUpdateAsyncEnumerable.cs +++ /dev/null @@ -1,109 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Pixeval.Data.ViewModel; -using Pixeval.Data.Web; -using Pixeval.Data.Web.Delegation; -using Pixeval.Data.Web.Response; -using Pixeval.Objects.Exceptions; -using Pixeval.Objects.Generic; -using Pixeval.Objects.I18n; -using Pixeval.Objects.Primitive; -using Pixeval.Persisting; - -namespace Pixeval.Core -{ - public class UserUpdateAsyncEnumerable : AbstractPixivAsyncEnumerable - { - public override int RequestedPages { get; protected set; } - - public override IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) - { - return new UserUpdateAsyncEnumerator(this); - } - - public override bool VerifyRationality(Illustration item, IList collection) - { - return item != null && collection.All(t => t.Id != item.Id) && PixivHelper.VerifyIllustRational(Settings.Global.ExcludeTag, Settings.Global.IncludeTag, Settings.Global.MinBookmark, item); - } - - private class UserUpdateAsyncEnumerator : AbstractPixivAsyncEnumerator - { - private UserUpdateResponse _entity; - - private IEnumerator _illustrationEnumerator; - - public UserUpdateAsyncEnumerator(IPixivAsyncEnumerable enumerable) : base(enumerable) - { - } - - public override Illustration Current => _illustrationEnumerator.Current; - - protected override void UpdateEnumerator() - { - _illustrationEnumerator = _entity.Illusts.NonNull().Select(_ => _.Parse()).GetEnumerator(); - } - - public override async ValueTask MoveNextAsync() - { - if (_entity == null) - { - if (await TryGetResponse("https://app-api.pixiv.net/v2/illust/follow?restrict=public") is (true, var model)) - { - _entity = model; - UpdateEnumerator(); - } - else - { - throw new QueryNotRespondingException(); - } - - Enumerable.ReportRequestedPages(); - } - - if (_illustrationEnumerator.MoveNext()) return true; - - if (_entity.NextUrl.IsNullOrEmpty()) return false; - - if (await TryGetResponse(_entity.NextUrl) is (true, var res)) - { - _entity = res; - UpdateEnumerator(); - Enumerable.ReportRequestedPages(); - return true; - } - - return false; - } - - private static async Task> TryGetResponse(string url) - { - var res = (await HttpClientFactory.AppApiHttpClient().Apply(h => h.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Language", AkaI18N.GetCultureAcceptLanguage())).GetStringAsync(url)).FromJson(); - if (res is { } response && !response.Illusts.IsNullOrEmpty()) return HttpResponse.Wrap(true, response); - - return HttpResponse.Wrap(false); - } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Core/WindowsUserActivityManager.cs b/src/Pixeval/Core/WindowsUserActivityManager.cs deleted file mode 100644 index 8ad45703..00000000 --- a/src/Pixeval/Core/WindowsUserActivityManager.cs +++ /dev/null @@ -1,135 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Threading.Tasks; -using Windows.ApplicationModel.UserActivities; -using Windows.UI.Shell; -using AdaptiveCards; -using Newtonsoft.Json; -using Pixeval.Data.ViewModel; -using Pixeval.Objects.Generic; - -namespace Pixeval.Core -{ - /// - /// Provides a set of functions to create a Windows 10 Timeline Activity, - /// for more information and underlying implementation, see - /// - /// - public class WindowsUserActivityManager : ITimelineService - { - public static readonly WindowsUserActivityManager GlobalLifeTimeScope = new WindowsUserActivityManager(); - private readonly Uri _iconUri = new Uri("http://qa23pqcql.bkt.clouddn.com/pxlogo.ico"); - private UserActivitySession _userActivitySession; - - public bool VerifyRationality(BrowsingHistory browsingHistory) - { - return true; - } - - public async void Insert(BrowsingHistory browsingHistory) - { - var userActivityChannel = UserActivityChannel.GetDefault(); - var model = await GetPixevalTimelineModel(browsingHistory); - var userActivity = await userActivityChannel.GetOrCreateUserActivityAsync($"Pixeval-{model.Id}-{DateTime.Now:s}"); - userActivity.VisualElements.DisplayText = model.Title; - userActivity.VisualElements.Content = AdaptiveCardBuilder.CreateAdaptiveCardFromJson(BuildAdaptiveCard(model)); - userActivity.VisualElements.Attribution = new UserActivityAttribution(_iconUri); - userActivity.VisualElements.AttributionDisplayText = "Pixeval"; - userActivity.ActivationUri = new Uri(browsingHistory.Type switch - { - "illust" => $"pixeval://www.pixiv.net/artworks/{model.Id}", - "user" => $"pixeval://www.pixiv.net/users/{model.Id}", - "spotlight" => $"pixeval://www.pixivision.net/en/a/{model.Id}", - _ => throw new ArgumentException(nameof(browsingHistory.Type)) - }); - await userActivity.SaveAsync(); - _userActivitySession?.Dispose(); - _userActivitySession = userActivity.CreateSession(); - } - - private static async Task GetPixevalTimelineModel(BrowsingHistory history) - { - var p = new PixevalTimelineModel {Background = await PixivIO.GetResizedBase64UriOfImageFromUrl(history.BrowseObjectThumbnail), Id = history.BrowseObjectId, Title = history.BrowseObjectState}; - switch (history.Type) - { - case "illust": - p.Author = history.IllustratorName; - return p; - case "user": - case "spotlight": return p; - } - - throw new ArgumentException(nameof(history.Type)); - } - - private static string BuildAdaptiveCard(PixevalTimelineModel pixevalTimelineModel) - { - var card = new StringifyBackgroundAdaptiveCard("1.0") {StringifyUrl = pixevalTimelineModel.Background}; - card.Body.Add(new AdaptiveTextBlock - { - Text = pixevalTimelineModel.Title, - Weight = AdaptiveTextWeight.Bolder, - Wrap = true, - Size = AdaptiveTextSize.Large, - MaxLines = 3 - }); - if (!pixevalTimelineModel.Author.IsNullOrEmpty()) - card.Body.Add(new AdaptiveTextBlock - { - Text = pixevalTimelineModel.Author, - Weight = AdaptiveTextWeight.Bolder, - Wrap = true, - Size = AdaptiveTextSize.Small, - MaxLines = 3, - Spacing = AdaptiveSpacing.Small - }); - - return card.ToJson(); - } - - private class PixevalTimelineModel - { - public string Id { get; set; } - - public string Title { get; set; } - - public string Author { get; set; } - - public string Background { get; set; } - } - - // https://stackoverflow.com/questions/55663963/adaptive-cards-serving-images-in-bytes - private class StringifyBackgroundAdaptiveCard : AdaptiveCard - { - public StringifyBackgroundAdaptiveCard(AdaptiveSchemaVersion schemaVersion) : base(schemaVersion) - { - } - - public StringifyBackgroundAdaptiveCard(string schemaVersion) : base(schemaVersion) - { - } - - [JsonProperty("backgroundImage")] - public string StringifyUrl { get; set; } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/IParser.cs b/src/Pixeval/Data/IParser.cs deleted file mode 100644 index 62834e61..00000000 --- a/src/Pixeval/Data/IParser.cs +++ /dev/null @@ -1,27 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -namespace Pixeval.Data -{ - public interface IParser - { - T Parse(); - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/ViewModel/AutoCompletion.cs b/src/Pixeval/Data/ViewModel/AutoCompletion.cs deleted file mode 100644 index 77381f04..00000000 --- a/src/Pixeval/Data/ViewModel/AutoCompletion.cs +++ /dev/null @@ -1,32 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using PropertyChanged; - -namespace Pixeval.Data.ViewModel -{ - [AddINotifyPropertyChangedInterface] - public class AutoCompletion - { - public string Tag { get; set; } - - public string TranslatedName { get; set; } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/ViewModel/BrowsingHistory.cs b/src/Pixeval/Data/ViewModel/BrowsingHistory.cs deleted file mode 100644 index f666cc7e..00000000 --- a/src/Pixeval/Data/ViewModel/BrowsingHistory.cs +++ /dev/null @@ -1,61 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using PropertyChanged; -using SQLite; - -namespace Pixeval.Data.ViewModel -{ - [AddINotifyPropertyChangedInterface] - public class BrowsingHistory - { - [PrimaryKey] - [AutoIncrement] - public int Index { get; set; } - - /// - /// represents the string form of the , by default, it is the name/title - /// - public string BrowseObjectState { get; set; } - - public string BrowseObjectThumbnail { get; set; } - - /// - /// get the illustrator of the illust which the current BrowsingHistory is representing, - /// this property will be valid only if the property is set - /// to true - /// - public string IllustratorName { get; set; } - - public bool IsReferToUser { get; set; } - - public bool IsReferToIllust { get; set; } - - public bool IsReferToSpotlight { get; set; } - - /// - /// represents the string form of the identification of current BrowsingHistory, by default - /// it is illust id/user id/spotlight id - /// - public string BrowseObjectId { get; set; } - - public string Type { get; set; } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/ViewModel/ConditionString.cs b/src/Pixeval/Data/ViewModel/ConditionString.cs deleted file mode 100644 index e37b6848..00000000 --- a/src/Pixeval/Data/ViewModel/ConditionString.cs +++ /dev/null @@ -1,33 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using PropertyChanged; - -namespace Pixeval.Data.ViewModel -{ - [AddINotifyPropertyChangedInterface] - public class ConditionString - { - [DoNotNotify] - public static ConditionString Shared = new ConditionString(); - - public string Condition { get; set; } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/ViewModel/DownloadableIllustration.cs b/src/Pixeval/Data/ViewModel/DownloadableIllustration.cs deleted file mode 100644 index 591f62ca..00000000 --- a/src/Pixeval/Data/ViewModel/DownloadableIllustration.cs +++ /dev/null @@ -1,200 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.IO; -using System.Linq; -using System.Text.RegularExpressions; -using System.Threading; -using System.Threading.Tasks; -using Pixeval.Core; -using Pixeval.Data.Web.Delegation; -using Pixeval.Objects.Generic; -using Pixeval.Objects.Primitive; -using PropertyChanged; - -namespace Pixeval.Data.ViewModel -{ - [AddINotifyPropertyChangedInterface] - public class DownloadableIllustration - { - [DoNotNotify] - private CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource(); - - private bool _modifiable = true; - - private bool _retried; - - public DownloadableIllustration(Illustration downloadContent, IIllustrationFileNameFormatter fileNameFormatter, IDownloadPathProvider downloadPathProvider, bool isFromManga, int mangaIndex = -1) - { - DownloadContent = downloadContent; - FileNameFormatter = fileNameFormatter; - DownloadPathProvider = downloadPathProvider; - IsFromManga = isFromManga; - MangaIndex = mangaIndex; - } - - public Illustration DownloadContent { get; set; } - - public IIllustrationFileNameFormatter FileNameFormatter { get; set; } - - public IDownloadPathProvider DownloadPathProvider { get; set; } - - public bool IsFromManga { get; set; } - - public int MangaIndex { get; set; } - - public bool DownloadFailed { get; set; } - - public double Progress { get; set; } - - public string ReasonPhase { get; set; } - - public Observable DownloadState { get; set; } = new Observable(DownloadStateEnum.Queue); - - public DownloadOption Option { get; set; } - - public string GetPath() - { - if (DownloadContent.IsUgoira) return Path.Combine(Directory.CreateDirectory(DownloadPathProvider.GetIllustrationPath(Option)).FullName, FileNameFormatter.FormatGif(DownloadContent)); - if (DownloadContent.FromSpotlight) return IsFromManga ? Path.Combine(Directory.CreateDirectory(DownloadPathProvider.GetSpotlightPath(DownloadContent.SpotlightTitle, Option)).FullName, DownloadContent.Id, FileNameFormatter.FormatManga(DownloadContent, MangaIndex)) : Path.Combine(Directory.CreateDirectory(DownloadPathProvider.GetSpotlightPath(DownloadContent.SpotlightTitle, Option)).FullName, FileNameFormatter.Format(DownloadContent)); - return IsFromManga ? Path.Combine(Directory.CreateDirectory(DownloadPathProvider.GetMangaPath(DownloadContent.Id, Option)).FullName, FileNameFormatter.FormatManga(DownloadContent, MangaIndex)) : Path.Combine(Directory.CreateDirectory(DownloadPathProvider.GetIllustrationPath(Option)).FullName, FileNameFormatter.Format(DownloadContent)); - } - - - public void Freeze() - { - _modifiable = false; - } - - public void Cancel() - { - if (_modifiable) - { - _cancellationTokenSource.Cancel(); - _cancellationTokenSource = new CancellationTokenSource(); - Progress = 0; - ReasonPhase = null; - DownloadFailed = false; - DownloadState.Value = DownloadStateEnum.Canceled; - } - } - - public void Restart() - { - if (_modifiable) - { - _cancellationTokenSource.Cancel(); - _cancellationTokenSource = new CancellationTokenSource(); - Progress = 0; - ReasonPhase = null; - DownloadFailed = false; - Download(); - } - } - - public async void Download() - { - if (!_modifiable) return; - - DownloadState.Value = DownloadStateEnum.Downloading; - var downloadPath = GetPath(); - if (DownloadContent.IsUgoira) - { - DownloadGif(); - return; - } - - try - { - await using var memory = await PixivIO.Download(DownloadContent.GetDownloadUrl(), new Progress(d => Progress = d), _cancellationTokenSource.Token); - if (_cancellationTokenSource.IsCancellationRequested) return; - await using var fileStream = new FileStream(downloadPath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None); - memory.WriteTo(fileStream); - DownloadState.Value = DownloadStateEnum.Finished; - } - catch (OperationCanceledException) - { - if (downloadPath != null && File.Exists(downloadPath)) File.Delete(downloadPath); - } - catch (Exception e) - { - if (!_retried) - { - Restart(); - _retried = true; - } - else - { - HandleError(e, downloadPath); - } - } - } - - private async void DownloadGif() - { - var downloadPath = GetPath(); - try - { - var metadata = await HttpClientFactory.AppApiService().GetUgoiraMetadata(DownloadContent.Id); - var ugoiraUrl = metadata.UgoiraMetadataInfo.ZipUrls.Medium; - ugoiraUrl = !ugoiraUrl.EndsWith("ugoira1920x1080.zip") ? Regex.Replace(ugoiraUrl, "ugoira(\\d+)x(\\d+).zip", "ugoira1920x1080.zip") : ugoiraUrl; - var delay = metadata.UgoiraMetadataInfo.Frames.Select(f => f.Delay / 10).ToArray(); - if (_cancellationTokenSource.IsCancellationRequested) return; - await using var memory = await PixivIO.Download(ugoiraUrl, new Progress(d => Progress = d), _cancellationTokenSource.Token); - await using var gifStream = (MemoryStream) InternalIO.MergeGifStream(InternalIO.ReadGifZipEntries(memory), delay); - if (_cancellationTokenSource.IsCancellationRequested) return; - await using var fileStream = new FileStream(downloadPath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None); - gifStream.WriteTo(fileStream); - DownloadState.Value = DownloadStateEnum.Finished; - } - catch (TaskCanceledException) - { - if (downloadPath != null && File.Exists(downloadPath)) File.Delete(downloadPath); - } - catch (Exception e) - { - if (!_retried) - { - Restart(); - _retried = true; - } - else - { - HandleError(e, downloadPath); - } - } - } - - private void HandleError(Exception e, string path) - { - DownloadState.Value = DownloadStateEnum.Exceptional; - DownloadFailed = true; - ReasonPhase = e.Message; - if (path != null && File.Exists(path)) File.Delete(path); - } - } - - [Flags] - public enum DownloadStateEnum - { - Queue, Downloading, Exceptional, Finished, Canceled - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/ViewModel/I18nOption.cs b/src/Pixeval/Data/ViewModel/I18nOption.cs deleted file mode 100644 index e02c41ed..00000000 --- a/src/Pixeval/Data/ViewModel/I18nOption.cs +++ /dev/null @@ -1,46 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using PropertyChanged; - -namespace Pixeval.Data.ViewModel -{ - [AddINotifyPropertyChangedInterface] - public class I18NOption - { - public static readonly I18NOption USEnglish = new I18NOption("English(US)", "en-us"); - - public static readonly I18NOption ChineseSimplified = new I18NOption("简体中文(中国)", "zh-cn"); - - public I18NOption(string localizedName, string name) - { - LocalizedName = localizedName; - Name = name; - } - - public I18NOption() - { - } - - public string LocalizedName { get; set; } - - public string Name { get; set; } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/ViewModel/Illustration.cs b/src/Pixeval/Data/ViewModel/Illustration.cs deleted file mode 100644 index fd1e4669..00000000 --- a/src/Pixeval/Data/ViewModel/Illustration.cs +++ /dev/null @@ -1,114 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text.RegularExpressions; -using Pixeval.Objects.Primitive; -using PropertyChanged; - -namespace Pixeval.Data.ViewModel -{ - [AddINotifyPropertyChangedInterface] - public class Illustration : ICloneable - { - public string Id { get; set; } - - public bool IsUgoira { get; set; } - - public bool IsR18 => Tags?.Any(x => Regex.IsMatch(x?.Name ?? string.Empty, "[Rr][-]?18[Gg]?") || Regex.IsMatch(x?.TranslatedName ?? string.Empty, "[Rr][-]?18[Gg]?")) ?? false; - - public string Origin { get; set; } - - public string Large { get; set; } - - public string Thumbnail { get; set; } - - public int Bookmark { get; set; } - - public bool IsLiked { get; set; } - - public bool IsManga { get; set; } - - public string Title { get; set; } - - public string UserName { get; set; } - - public string UserId { get; set; } - - public IEnumerable Tags { get; set; } - - public Illustration[] MangaMetadata { get; set; } - - public DateTimeOffset PublishDate { get; set; } - - public int ViewCount { get; set; } - - public string Resolution { get; set; } - - public int Comments { get; set; } - - public bool FromSpotlight { get; set; } - - public string SpotlightTitle { get; set; } - - public object Clone() - { - return MemberwiseClone(); - } - - public string GetDownloadUrl() - { - return Origin.IsNullOrEmpty() ? Large : Origin; - } - } - - public class Tag - { - public string Name { get; set; } - - public string TranslatedName { get; set; } - } - - public class IllustrationPopularityComparator : IComparer - { - public static readonly IllustrationPopularityComparator Instance = new IllustrationPopularityComparator(); - - // reverse-ordered(a.k.a. descend order) - public int Compare(Illustration x, Illustration y) - { - if (x == null || y == null) return 0; - - return x.Bookmark < y.Bookmark ? 1 : x.Bookmark == y.Bookmark ? 0 : -1; - } - } - - public class IllustrationPublishDateComparator : IComparer - { - public static readonly IllustrationPublishDateComparator Instance = new IllustrationPublishDateComparator(); - - public int Compare(Illustration x, Illustration y) - { - if (x == null || y == null) return 0; - return x.PublishDate < y.PublishDate ? 1 : x.PublishDate == y.PublishDate ? 0 : -1; - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/ViewModel/RankOptionModel.cs b/src/Pixeval/Data/ViewModel/RankOptionModel.cs deleted file mode 100644 index 282226c9..00000000 --- a/src/Pixeval/Data/ViewModel/RankOptionModel.cs +++ /dev/null @@ -1,60 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Linq; -using Pixeval.Core; -using Pixeval.Objects.Generic; -using Pixeval.Objects.I18n; -using Pixeval.Objects.Primitive; -using PropertyChanged; - -namespace Pixeval.Data.ViewModel -{ - [AddINotifyPropertyChangedInterface] - public class RankOptionModel - { - [DoNotNotify] - public static readonly RankOptionModel[] RegularRankOptions = Enum.GetValues(typeof(RankOption)).Cast().Select(rank => new RankOptionModel(rank)).ToArray().Apply(models => models[0].IsSelected = true); - - [DoNotNotify] - public static readonly DateTime MaxRankDateTime = DateTime.Today - TimeSpan.FromDays(2); - - [DoNotNotify] - public static readonly DateTime InvalidRankDateTimeStart = DateTime.Today - TimeSpan.FromDays(1); - - public RankOptionModel(RankOption option) - { - Corresponding = option; - Name = AkaI18N.GetResource(option.GetEnumAttribute().Name); - } - - public string Name { get; set; } - - public bool IsSelected { get; set; } - - public RankOption Corresponding { get; set; } - - public override string ToString() - { - return Name; - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/ViewModel/SearchTagMatchOptionModel.cs b/src/Pixeval/Data/ViewModel/SearchTagMatchOptionModel.cs deleted file mode 100644 index 4a30895c..00000000 --- a/src/Pixeval/Data/ViewModel/SearchTagMatchOptionModel.cs +++ /dev/null @@ -1,50 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Collections.Generic; -using Pixeval.Core; -using Pixeval.Objects.I18n; -using Pixeval.Objects.Primitive; -using PropertyChanged; - -namespace Pixeval.Data.ViewModel -{ - [AddINotifyPropertyChangedInterface] - public class SearchTagMatchOptionModel - { - public static readonly SearchTagMatchOptionModel PartialMatchModel = new SearchTagMatchOptionModel(SearchTagMatchOption.PartialMatchForTags); - - public static readonly SearchTagMatchOptionModel ExactMatchModel = new SearchTagMatchOptionModel(SearchTagMatchOption.ExactMatchForTags); - - public static readonly SearchTagMatchOptionModel TitleAndCaptionModel = new SearchTagMatchOptionModel(SearchTagMatchOption.TitleAndCaption); - - public static readonly IEnumerable AllPossibleMatchOptions = new[] {PartialMatchModel, ExactMatchModel, TitleAndCaptionModel}; - - public SearchTagMatchOptionModel(SearchTagMatchOption corresponding) - { - Description = AkaI18N.GetResource(corresponding.GetEnumAttribute().Name); - Corresponding = corresponding; - } - - public string Description { get; set; } - - public SearchTagMatchOption Corresponding { get; set; } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/ViewModel/SpotlightArticle.cs b/src/Pixeval/Data/ViewModel/SpotlightArticle.cs deleted file mode 100644 index afb1beea..00000000 --- a/src/Pixeval/Data/ViewModel/SpotlightArticle.cs +++ /dev/null @@ -1,69 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using Newtonsoft.Json; -using Pixeval.Core; -using Pixeval.Objects.Generic; -using PropertyChanged; - -namespace Pixeval.Data.ViewModel -{ - [AddINotifyPropertyChangedInterface] - public class SpotlightArticle - { - [JsonProperty("id")] - public long Id { get; set; } - - [JsonProperty("title")] - public string Title { get; set; } - - [JsonProperty("pure_title")] - public string PureTitle { get; set; } - - [JsonProperty("thumbnail")] - public string Thumbnail { get; set; } - - [JsonProperty("article_url")] - public string ArticleUrl { get; set; } - - [JsonProperty("publish_date")] - public DateTimeOffset PublishDate { get; set; } - - [JsonProperty("category")] - public string Category { get; set; } - - [JsonProperty("subcategory_label")] - public string SubcategoryLabel { get; set; } - - public async void Download() - { - var result = await Tasks.Of(await PixivClient.Instance.GetArticleWorks(Id.ToString())).Mapping(async i => - { - var res = await PixivHelper.IllustrationInfo(i); - res.SpotlightTitle = Title; - res.FromSpotlight = true; - return res; - }).Construct().WhenAll(); - - foreach (var illustration in result) DownloadManager.EnqueueDownloadItem(illustration); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/ViewModel/TrendingTag.cs b/src/Pixeval/Data/ViewModel/TrendingTag.cs deleted file mode 100644 index 582da49b..00000000 --- a/src/Pixeval/Data/ViewModel/TrendingTag.cs +++ /dev/null @@ -1,34 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using PropertyChanged; - -namespace Pixeval.Data.ViewModel -{ - [AddINotifyPropertyChangedInterface] - public class TrendingTag - { - public string Tag { get; set; } - - public string TranslatedName { get; set; } - - public string Thumbnail { get; set; } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/ViewModel/Trends.cs b/src/Pixeval/Data/ViewModel/Trends.cs deleted file mode 100644 index f7f8018c..00000000 --- a/src/Pixeval/Data/ViewModel/Trends.cs +++ /dev/null @@ -1,67 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using PropertyChanged; - -namespace Pixeval.Data.ViewModel -{ - [AddINotifyPropertyChangedInterface] - public class Trends - { - public string PostUserId { get; set; } - - public string PostUserName { get; set; } - - public string TrendObjectId { get; set; } - - public DateTime PostDate { get; set; } - - public TrendType Type { get; set; } - - public string ByName { get; set; } - - public bool IsReferToUser { get; set; } - - public string TrendObjName { get; set; } - - public string TrendObjectThumbnail { get; set; } - - public string PostUserThumbnail { get; set; } - } - - public enum TrendType - { - /// - /// Bookmark - /// - AddBookmark, - - /// - /// New illust - /// - AddIllust, - - /// - /// New follow - /// - AddFavorite - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/ViewModel/User.cs b/src/Pixeval/Data/ViewModel/User.cs deleted file mode 100644 index 8d520bbc..00000000 --- a/src/Pixeval/Data/ViewModel/User.cs +++ /dev/null @@ -1,46 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using PropertyChanged; - -namespace Pixeval.Data.ViewModel -{ - [AddINotifyPropertyChangedInterface] - public class User - { - public string Name { get; set; } - - public string Id { get; set; } - - public bool IsFollowed { get; set; } - - public string Avatar { get; set; } - - public string Introduction { get; set; } - - public string Background { get; set; } - - public int Follows { get; set; } - - public bool IsPremium { get; set; } - - public string[] Thumbnails { get; set; } = new string[3]; - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Delegation/DnsResolvedHttpClientHandler.cs b/src/Pixeval/Data/Web/Delegation/DnsResolvedHttpClientHandler.cs deleted file mode 100644 index b850a412..00000000 --- a/src/Pixeval/Data/Web/Delegation/DnsResolvedHttpClientHandler.cs +++ /dev/null @@ -1,89 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Net; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Threading; -using System.Threading.Tasks; -using Pixeval.Persisting; - -namespace Pixeval.Data.Web.Delegation -{ - public abstract class DnsResolvedHttpClientHandler : HttpClientHandler - { - private readonly bool _directConnect; - private readonly IHttpRequestHandler _requestHandler; - - static DnsResolvedHttpClientHandler() - { - System.AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", false); - } - - protected DnsResolvedHttpClientHandler(IHttpRequestHandler requestHandler = null, bool directConnect = true) - { - _requestHandler = requestHandler; - _directConnect = directConnect; - ServerCertificateCustomValidationCallback = DangerousAcceptAnyServerCertificateValidator; - } - - protected abstract DnsResolver DnsResolver { get; set; } - - protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) - { - _requestHandler?.Handle(request); - - if (_directConnect) - { - var host = request.RequestUri.DnsSafeHost; - - var isSslSession = request.RequestUri.ToString().StartsWith("https://"); - - request.RequestUri = new Uri($"{(isSslSession ? "https://" : "http://")}{DnsResolver.Lookup()[0]}{request.RequestUri.PathAndQuery}"); - request.Headers.Host = host; - } - - HttpResponseMessage result; - try - { - result = await base.SendAsync(request, cancellationToken); - } - catch (HttpRequestException e) - { - if (e.InnerException != null && e.InnerException.Message.ToLower().Contains("winhttp")) return new HttpResponseMessage(HttpStatusCode.OK); - throw; - } - - if (result.StatusCode == HttpStatusCode.BadRequest && (await result.Content.ReadAsStringAsync()).Contains("OAuth")) - { - using var semaphore = new SemaphoreSlim(1); - await semaphore.WaitAsync(cancellationToken); - await Authentication.AppApiAuthenticate(Session.Current.Account, Session.Current.Password); - var token = request.Headers.Authorization; - if (token != null) request.Headers.Authorization = new AuthenticationHeaderValue(token.Scheme, Session.Current.AccessToken); - - return await base.SendAsync(request, cancellationToken); - } - - return result; - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Delegation/DnsResolver.cs b/src/Pixeval/Data/Web/Delegation/DnsResolver.cs deleted file mode 100644 index d32a0fd9..00000000 --- a/src/Pixeval/Data/Web/Delegation/DnsResolver.cs +++ /dev/null @@ -1,135 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Net; -using System.Net.Http; -using System.Security.Authentication; -using System.Threading; -using System.Threading.Tasks; -using Pixeval.Data.Web.Protocol; -using Pixeval.Data.Web.Request; -using Pixeval.Data.Web.Response; -using Refit; - -namespace Pixeval.Data.Web.Delegation -{ - public abstract class DnsResolver - { - public static readonly ThreadLocal>> DnsCache = new ThreadLocal>>(() => new Dictionary>()); - - protected async Task GetDnsJson(string hostname) - { - return await RestService.For(new HttpClient(new HttpClientHandler {SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls}) {BaseAddress = new Uri(ProtocolBase.DnsServer), Timeout = TimeSpan.FromSeconds(5)}).ResolveDns(new DnsResolveRequest - { - Ct = "application/dns-json", - Cd = "false", - Do = "false", - Name = hostname, - Type = "A" - }); - } - - /*public async Task> Lookup(string hostname) - { - const string OAuthUrl = "oauth.secure.pixiv.net"; - if (hostname == OAuthUrl) - { - CacheDns(hostname, UseDefaultDns()); - return DnsCache.Value[hostname]; - } - - if (DnsCache.Value.ContainsKey(hostname)) return DnsCache.Value[hostname].ToImmutableList(); - - var ipList = new HashSet(new IpAddressEqualityComparer()); - if (_dnsQueryFailed) - { - CacheDns(hostname, UseDefaultDns()); - return DnsCache.Value[hostname]; - } - - DnsResolveResponse response; - try - { - response = await GetDnsJson(hostname); - } - catch (Exception) - { - _dnsQueryFailed = true; - CacheDns(hostname, UseDefaultDns()); - return DnsCache.Value[hostname]; - } - - if (response != null) - { - var answer = response.Answers; - if (!answer.IsNullOrEmpty()) - { - foreach (var queriedIp in answer) - if (IPAddress.TryParse(queriedIp.Data, out var address)) - ipList.Add(address); - } - else - { - ipList.AddRange(await Dns.GetHostAddressesAsync(hostname)); - if (ipList.IsNullOrEmpty()) ipList.AddRange(UseDefaultDns()); - } - - CacheDns(hostname, ipList); - return ipList.ToImmutableList(); - } - - ipList.AddRange(UseDefaultDns()); - CacheDns(hostname, ipList); - return ipList.ToImmutableList(); - }*/ - - public IReadOnlyList Lookup() - { - return UseDefaultDns().ToImmutableList(); - } - - // private static void CacheDns(string hostname, IEnumerable ipList) - // { - // if (DnsCache.Value.ContainsKey(hostname)) - // DnsCache.Value[hostname].AddRange(ipList); - // else - // DnsCache.Value[hostname] = new List(ipList); - // } - - protected abstract IEnumerable UseDefaultDns(); - - private class IpAddressEqualityComparer : IEqualityComparer - { - public bool Equals(IPAddress x, IPAddress y) - { - if (x == null || y == null) return false; - return x.ToString() == y.ToString(); - } - - public int GetHashCode(IPAddress obj) - { - return obj.GetHashCode(); - } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Delegation/HttpClientFactory.cs b/src/Pixeval/Data/Web/Delegation/HttpClientFactory.cs deleted file mode 100644 index e85122dd..00000000 --- a/src/Pixeval/Data/Web/Delegation/HttpClientFactory.cs +++ /dev/null @@ -1,72 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Net.Http; -using System.Threading.Tasks; -using Pixeval.Data.Web.Protocol; -using Pixeval.Objects.Generic; -using Pixeval.Persisting; -using Refit; - -namespace Pixeval.Data.Web.Delegation -{ - public class HttpClientFactory - { - public static HttpClient AppApiHttpClient() - { - return PixivApi(ProtocolBase.AppApiBaseUrl, Settings.Global.DirectConnect).Apply(h => h.DefaultRequestHeaders.Add("Authorization", "Bearer")); - } - - public static HttpClient WebApiHttpClient() - { - return PixivApi(ProtocolBase.WebApiBaseUrl, Settings.Global.DirectConnect); - } - - public static IAppApiProtocol AppApiService() - { - return RestService.For(PixivApi(ProtocolBase.AppApiBaseUrl, Settings.Global.DirectConnect)); - } - - public static IWebApiProtocol WebApiService() - { - return RestService.For(PixivApi(ProtocolBase.WebApiBaseUrl, Settings.Global.DirectConnect)); - } - - public static HttpClient PixivApi(string baseAddress, bool directConnect) - { - return new HttpClient(PixivApiHttpClientHandler.Instance(directConnect)) {BaseAddress = new Uri(baseAddress)}; - } - - public static HttpClient PixivImage() - { - return new HttpClient(PixivImageHttpClientHandler.Instance).Apply(client => - { - client.DefaultRequestHeaders.TryAddWithoutValidation("Referer", "http://www.pixiv.net"); - client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "PixivIOSApp/5.8.7"); - }); - } - - public static Task GetResponseHeader(HttpClient client, string uri) - { - return client.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Delegation/IHttpRequestHandler.cs b/src/Pixeval/Data/Web/Delegation/IHttpRequestHandler.cs deleted file mode 100644 index 8ff85ae1..00000000 --- a/src/Pixeval/Data/Web/Delegation/IHttpRequestHandler.cs +++ /dev/null @@ -1,29 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Net.Http; - -namespace Pixeval.Data.Web.Delegation -{ - public interface IHttpRequestHandler - { - void Handle(HttpRequestMessage httpRequestMessage); - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Delegation/PixivApiDnsResolver.cs b/src/Pixeval/Data/Web/Delegation/PixivApiDnsResolver.cs deleted file mode 100644 index 40a72f6b..00000000 --- a/src/Pixeval/Data/Web/Delegation/PixivApiDnsResolver.cs +++ /dev/null @@ -1,37 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Collections.Generic; -using System.Net; - -namespace Pixeval.Data.Web.Delegation -{ - public class PixivApiDnsResolver : DnsResolver - { - public static readonly DnsResolver Instance = new PixivApiDnsResolver(); - - protected override IEnumerable UseDefaultDns() - { - yield return IPAddress.Parse("210.140.131.219"); - yield return IPAddress.Parse("210.140.131.223"); - yield return IPAddress.Parse("210.140.131.226"); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Delegation/PixivApiHttpClientHandler.cs b/src/Pixeval/Data/Web/Delegation/PixivApiHttpClientHandler.cs deleted file mode 100644 index 8839303f..00000000 --- a/src/Pixeval/Data/Web/Delegation/PixivApiHttpClientHandler.cs +++ /dev/null @@ -1,38 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Net.Http; - -namespace Pixeval.Data.Web.Delegation -{ - public class PixivApiHttpClientHandler : DnsResolvedHttpClientHandler - { - private PixivApiHttpClientHandler(bool directConnect) : base(PixivAuthenticationHttpRequestHandler.Instance, directConnect) - { - } - - protected override DnsResolver DnsResolver { get; set; } = PixivApiDnsResolver.Instance; - - public static HttpMessageHandler Instance(bool directConnect) - { - return new PixivApiHttpClientHandler(directConnect); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Delegation/PixivAuthenticationHttpRequestHandler.cs b/src/Pixeval/Data/Web/Delegation/PixivAuthenticationHttpRequestHandler.cs deleted file mode 100644 index a0415626..00000000 --- a/src/Pixeval/Data/Web/Delegation/PixivAuthenticationHttpRequestHandler.cs +++ /dev/null @@ -1,62 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Net.Http; -using System.Net.Http.Headers; -using Pixeval.Objects.Exceptions; -using Pixeval.Objects.I18n; -using Pixeval.Objects.Primitive; -using Pixeval.Persisting; - -namespace Pixeval.Data.Web.Delegation -{ - public class PixivAuthenticationHttpRequestHandler : IHttpRequestHandler - { - public static readonly PixivAuthenticationHttpRequestHandler Instance = new PixivAuthenticationHttpRequestHandler(); - - protected PixivAuthenticationHttpRequestHandler() - { - } - - public virtual void Handle(HttpRequestMessage httpRequestMessage) - { - switch (httpRequestMessage.RequestUri.DnsSafeHost) - { - case "app-api.pixiv.net": - var token = httpRequestMessage.Headers.Authorization; - if (token != null) - { - if (Session.Current.AccessToken.IsNullOrEmpty()) throw new TokenNotFoundException($"{nameof(Session.Current.AccessToken)} is empty, this exception should never be thrown, if you see this message, please send issue on github or contact me (decem0730@gmail.com)"); - - httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue(token.Scheme, Session.Current.AccessToken); - } - - break; - case var x when x == "pixiv.net" || x == "www.pixiv.net": - if (Session.Current.PhpSessionId.IsNullOrEmpty()) throw new TokenNotFoundException($"{nameof(Session.Current.PhpSessionId)} is empty, this exception should never be thrown, if you see this message, please send issue on github or contact me (decem0730@gmail.com)"); - - httpRequestMessage.Headers.TryAddWithoutValidation("Cookie", $"PHPSESSID={Session.Current.PhpSessionId}"); - break; - } - - if (!httpRequestMessage.Headers.Contains("Accept-Language")) httpRequestMessage.Headers.TryAddWithoutValidation("Accept-Language", AkaI18N.GetCultureAcceptLanguage()); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Delegation/PixivImageHttpClientHandler.cs b/src/Pixeval/Data/Web/Delegation/PixivImageHttpClientHandler.cs deleted file mode 100644 index 9f32a333..00000000 --- a/src/Pixeval/Data/Web/Delegation/PixivImageHttpClientHandler.cs +++ /dev/null @@ -1,35 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Net.Http; - -namespace Pixeval.Data.Web.Delegation -{ - public class PixivImageHttpClientHandler : DnsResolvedHttpClientHandler - { - public static readonly HttpMessageHandler Instance = new PixivImageHttpClientHandler(); - - private PixivImageHttpClientHandler() : base(PixivAuthenticationHttpRequestHandler.Instance, false) - { - } - - protected override DnsResolver DnsResolver { get; set; } = null; - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/HttpResponse.cs b/src/Pixeval/Data/Web/HttpResponse.cs deleted file mode 100644 index b3ea1460..00000000 --- a/src/Pixeval/Data/Web/HttpResponse.cs +++ /dev/null @@ -1,47 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; - -namespace Pixeval.Data.Web -{ - public class HttpResponse : Tuple - { - private HttpResponse(bool status, T response) : base(status, response) - { - } - - public static HttpResponse Wrap(bool status) - { - return new HttpResponse(status, default); - } - - public static HttpResponse Wrap(bool status, T response) - { - return new HttpResponse(status, response); - } - - public void Deconstruct(out bool status, out T response) - { - status = Item1; - response = Item2; - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Protocol/IAppApiProtocol.cs b/src/Pixeval/Data/Web/Protocol/IAppApiProtocol.cs deleted file mode 100644 index 242c6c97..00000000 --- a/src/Pixeval/Data/Web/Protocol/IAppApiProtocol.cs +++ /dev/null @@ -1,64 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Threading.Tasks; -using Pixeval.Data.Web.Request; -using Pixeval.Data.Web.Response; -using Refit; - -namespace Pixeval.Data.Web.Protocol -{ - [Headers("Authorization: Bearer")] - public interface IAppApiProtocol - { - [Post("/v1/illust/bookmark/delete")] - Task DeleteBookmark([Body(BodySerializationMethod.UrlEncoded)] DeleteBookmarkRequest deleteBookmarkRequest); - - [Get("/v1/user/detail")] - Task GetUserInformation(UserInformationRequest userInformationRequest); - - [Get("/v1/spotlight/articles?category=all")] - Task GetSpotlights(int offset); - - [Post("/v1/user/follow/add")] - Task FollowArtist([Body(BodySerializationMethod.UrlEncoded)] FollowArtistRequest followArtistRequest); - - [Post("/v1/user/follow/delete")] - Task UnFollowArtist([Body(BodySerializationMethod.UrlEncoded)] UnFollowArtistRequest unFollowArtistRequest); - - [Get("/v1/ugoira/metadata")] - Task GetUgoiraMetadata([AliasAs("illust_id")] string id); - - [Post("/v2/illust/bookmark/add")] - Task AddBookmark([Body(BodySerializationMethod.UrlEncoded)] AddBookmarkRequest addBookmarkRequest); - - [Get("/v2/search/autocomplete")] - Task GetAutoCompletion(AutoCompletionRequest autoCompletionRequest); - - [Get("/v1/illust/detail")] - Task GetSingle([AliasAs("illust_id")] string id); - - [Get("/v1/user/recommended?filter=for_android")] - Task GetRecommendIllustrators(RecommendIllustratorRequest recommendIllustratorRequest); - - [Get("/v1/trending-tags/illust?filter=for_android")] - Task GetTrendingTags(); - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Protocol/IResolveDnsProtocol.cs b/src/Pixeval/Data/Web/Protocol/IResolveDnsProtocol.cs deleted file mode 100644 index 90d3a2cb..00000000 --- a/src/Pixeval/Data/Web/Protocol/IResolveDnsProtocol.cs +++ /dev/null @@ -1,33 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Threading.Tasks; -using Pixeval.Data.Web.Request; -using Pixeval.Data.Web.Response; -using Refit; - -namespace Pixeval.Data.Web.Protocol -{ - public interface IResolveDnsProtocol - { - [Get("/dns-query")] - Task ResolveDns(DnsResolveRequest dnsResolverRequest); - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Protocol/ISauceNAOProtocol.cs b/src/Pixeval/Data/Web/Protocol/ISauceNAOProtocol.cs deleted file mode 100644 index 62956097..00000000 --- a/src/Pixeval/Data/Web/Protocol/ISauceNAOProtocol.cs +++ /dev/null @@ -1,35 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Net.Http; -using System.Threading.Tasks; -using Refit; - -namespace Pixeval.Data.Web.Protocol -{ - // ReSharper disable once InconsistentNaming - public interface ISauceNAOProtocol - { - [Multipart] - [Post("/search.php")] - Task GetSauce([AliasAs("file")] - StreamPart stream); - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Protocol/ITokenProtocol.cs b/src/Pixeval/Data/Web/Protocol/ITokenProtocol.cs deleted file mode 100644 index 91e51ac7..00000000 --- a/src/Pixeval/Data/Web/Protocol/ITokenProtocol.cs +++ /dev/null @@ -1,37 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Threading.Tasks; -using Pixeval.Data.Web.Request; -using Pixeval.Data.Web.Response; -using Refit; - -namespace Pixeval.Data.Web.Protocol -{ - [Headers("User-Agent: PixivAndroidApp/5.0.64 (Android 6.0)", "Content-Type: application/x-www-form-urlencoded")] - public interface ITokenProtocol - { - [Post("/auth/token")] - Task GetTokenByPassword([Body(BodySerializationMethod.UrlEncoded)] PasswordTokenRequest body, [Header("X-Client-Time")] string clientTime, [Header("X-Client-Hash")] string clientHash); - - [Post("/auth/token")] - Task RefreshToken([Body(BodySerializationMethod.UrlEncoded)] RefreshTokenRequest body); - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Protocol/IWebApiProtocol.cs b/src/Pixeval/Data/Web/Protocol/IWebApiProtocol.cs deleted file mode 100644 index 0f0af6a4..00000000 --- a/src/Pixeval/Data/Web/Protocol/IWebApiProtocol.cs +++ /dev/null @@ -1,41 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Net.Http; -using System.Threading.Tasks; -using Pixeval.Data.Web.Request; -using Pixeval.Data.Web.Response; -using Refit; - -namespace Pixeval.Data.Web.Protocol -{ - [Headers("User-Agent: PixivAndroidApp/5.0.64 (Android 6.0)", "Content-Type: application/x-www-form-urlencoded")] - public interface IWebApiProtocol - { - [Post("/setting_user.php")] - Task ToggleR18State([Body(BodySerializationMethod.UrlEncoded)] ToggleR18StateRequest toggleR18StateRequest); - - [Get("/ajax/showcase/article")] - Task GetSpotlightArticles([AliasAs("article_id")] string articleId); - - [Get("/touch/ajax/user/details")] - Task GetWebApiUserDetail(string id); - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/ProtocolBase.cs b/src/Pixeval/Data/Web/ProtocolBase.cs deleted file mode 100644 index 03b8ac2b..00000000 --- a/src/Pixeval/Data/Web/ProtocolBase.cs +++ /dev/null @@ -1,37 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -namespace Pixeval.Data.Web -{ - public class ProtocolBase - { - public const string PublicApiBaseUrl = "https://public-api.secure.pixiv.net/v1"; - - public const string AppApiBaseUrl = "https://app-api.pixiv.net"; - - public const string DnsServer = "https://1.0.0.1"; - - public const string SauceNaoUrl = "https://saucenao.com/"; - - public const string OAuthBaseUrl = "https://oauth.secure.pixiv.net"; - - public const string WebApiBaseUrl = "https://www.pixiv.net"; - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Request/AddBookmarkRequest.cs b/src/Pixeval/Data/Web/Request/AddBookmarkRequest.cs deleted file mode 100644 index fe7d3e85..00000000 --- a/src/Pixeval/Data/Web/Request/AddBookmarkRequest.cs +++ /dev/null @@ -1,33 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using Refit; - -namespace Pixeval.Data.Web.Request -{ - public class AddBookmarkRequest - { - [AliasAs("restrict")] - public string Restrict { get; set; } = "public"; - - [AliasAs("illust_id")] - public string Id { get; set; } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Request/AutoCompletionRequest.cs b/src/Pixeval/Data/Web/Request/AutoCompletionRequest.cs deleted file mode 100644 index f9216668..00000000 --- a/src/Pixeval/Data/Web/Request/AutoCompletionRequest.cs +++ /dev/null @@ -1,33 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using Refit; - -namespace Pixeval.Data.Web.Request -{ - public class AutoCompletionRequest - { - [AliasAs("merge_plain_keyword_results=true")] - public bool MergePlainKeywordResult { get; set; } = true; - - [AliasAs("word")] - public string Word { get; set; } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Request/DeleteBookmarkRequest.cs b/src/Pixeval/Data/Web/Request/DeleteBookmarkRequest.cs deleted file mode 100644 index 4f94ac2b..00000000 --- a/src/Pixeval/Data/Web/Request/DeleteBookmarkRequest.cs +++ /dev/null @@ -1,30 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using Refit; - -namespace Pixeval.Data.Web.Request -{ - public class DeleteBookmarkRequest - { - [AliasAs("illust_id")] - public string IllustId { get; set; } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Request/DnsResolveRequest.cs b/src/Pixeval/Data/Web/Request/DnsResolveRequest.cs deleted file mode 100644 index b560cc95..00000000 --- a/src/Pixeval/Data/Web/Request/DnsResolveRequest.cs +++ /dev/null @@ -1,42 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using Refit; - -namespace Pixeval.Data.Web.Request -{ - public class DnsResolveRequest - { - [AliasAs("ct")] - public string Ct { get; set; } - - [AliasAs("name")] - public string Name { get; set; } - - [AliasAs("type")] - public string Type { get; set; } - - [AliasAs("do")] - public string Do { get; set; } - - [AliasAs("cd")] - public string Cd { get; set; } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Request/FollowArtistRequest.cs b/src/Pixeval/Data/Web/Request/FollowArtistRequest.cs deleted file mode 100644 index ed93b4d2..00000000 --- a/src/Pixeval/Data/Web/Request/FollowArtistRequest.cs +++ /dev/null @@ -1,33 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using Refit; - -namespace Pixeval.Data.Web.Request -{ - public class FollowArtistRequest - { - [AliasAs("user_id")] - public string Id { get; set; } - - [AliasAs("restrict")] - public string Restrict { get; set; } = "public"; - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Request/PasswordTokenRequest.cs b/src/Pixeval/Data/Web/Request/PasswordTokenRequest.cs deleted file mode 100644 index 432f1e59..00000000 --- a/src/Pixeval/Data/Web/Request/PasswordTokenRequest.cs +++ /dev/null @@ -1,45 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using Refit; - -namespace Pixeval.Data.Web.Request -{ - public class PasswordTokenRequest - { - [AliasAs("username")] - public string Name { get; set; } - - [AliasAs("password")] - public string Password { get; set; } - - [AliasAs("grant_type")] - public string GrantType => "password"; - - [AliasAs("client_id")] - public string ClientId => "MOBrBDS8blbauoSck0ZfDbtuzpyT"; - - [AliasAs("client_secret")] - public string ClientSecret => "lsACyCD94FhDUtGTXi3QzcFE2uU1hqtDaKeqrdwj"; - - [AliasAs("get_secure_url")] - public string GetSecureUrl => "1"; - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Request/RecommendIllustratorRequest.cs b/src/Pixeval/Data/Web/Request/RecommendIllustratorRequest.cs deleted file mode 100644 index 8e3dfb1c..00000000 --- a/src/Pixeval/Data/Web/Request/RecommendIllustratorRequest.cs +++ /dev/null @@ -1,33 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using Refit; - -namespace Pixeval.Data.Web.Request -{ - public class RecommendIllustratorRequest - { - [AliasAs("filter")] - public string Filter { get; } = "for_android"; - - [AliasAs("offset")] - public int Offset { get; set; } = 0; - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Request/RefreshTokenRequest.cs b/src/Pixeval/Data/Web/Request/RefreshTokenRequest.cs deleted file mode 100644 index 8a2b3d28..00000000 --- a/src/Pixeval/Data/Web/Request/RefreshTokenRequest.cs +++ /dev/null @@ -1,42 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using Refit; - -namespace Pixeval.Data.Web.Request -{ - public class RefreshTokenRequest - { - [AliasAs("refresh_token")] - public string RefreshToken { get; set; } - - [AliasAs("grant_type")] - public string GrantType => "refresh_token"; - - [AliasAs("client_id")] - public string ClientId => "MOBrBDS8blbauoSck0ZfDbtuzpyT"; - - [AliasAs("client_secret")] - public string ClientSecret => "lsACyCD94FhDUtGTXi3QzcFE2uU1hqtDaKeqrdwj"; - - [AliasAs("get_secure_url")] - public string GetSecureUrl => "1"; - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Request/ToggleR18StateRequest.cs b/src/Pixeval/Data/Web/Request/ToggleR18StateRequest.cs deleted file mode 100644 index 1e2b7f35..00000000 --- a/src/Pixeval/Data/Web/Request/ToggleR18StateRequest.cs +++ /dev/null @@ -1,45 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using Refit; - -namespace Pixeval.Data.Web.Request -{ - public class ToggleR18StateRequest - { - [AliasAs("mode")] - public string Mode { get; } = "mod"; - - [AliasAs("user_language")] - public string UserLang { get; } = "zh"; - - [AliasAs("r18")] - public string R18 { get; set; } - - [AliasAs("r18g")] - public string R18G { get; set; } - - [AliasAs("submit")] - public string Submit { get; } = "保存"; - - [AliasAs("tt")] - public string Tt { get; set; } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Request/UnFollowArtistRequest.cs b/src/Pixeval/Data/Web/Request/UnFollowArtistRequest.cs deleted file mode 100644 index e74f6223..00000000 --- a/src/Pixeval/Data/Web/Request/UnFollowArtistRequest.cs +++ /dev/null @@ -1,30 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using Refit; - -namespace Pixeval.Data.Web.Request -{ - public class UnFollowArtistRequest - { - [AliasAs("user_id")] - public string UserId { get; set; } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Request/UserInformationRequest.cs b/src/Pixeval/Data/Web/Request/UserInformationRequest.cs deleted file mode 100644 index 18576702..00000000 --- a/src/Pixeval/Data/Web/Request/UserInformationRequest.cs +++ /dev/null @@ -1,33 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using Refit; - -namespace Pixeval.Data.Web.Request -{ - public class UserInformationRequest - { - [AliasAs("user_id")] - public string Id { get; set; } - - [AliasAs("filter")] - public string Filter { get; set; } = "for_android"; - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Response/AutoCompletionResponse.cs b/src/Pixeval/Data/Web/Response/AutoCompletionResponse.cs deleted file mode 100644 index ff04ceb6..00000000 --- a/src/Pixeval/Data/Web/Response/AutoCompletionResponse.cs +++ /dev/null @@ -1,40 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace Pixeval.Data.Web.Response -{ - public class AutoCompletionResponse - { - [JsonProperty("tags")] - public List Tags { get; set; } - - public class Tag - { - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("translated_name")] - public string TranslatedName { get; set; } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Response/DnsResolveResponse.cs b/src/Pixeval/Data/Web/Response/DnsResolveResponse.cs deleted file mode 100644 index 86bf24b9..00000000 --- a/src/Pixeval/Data/Web/Response/DnsResolveResponse.cs +++ /dev/null @@ -1,76 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace Pixeval.Data.Web.Response -{ - public class DnsResolveResponse - { - [JsonProperty("Status")] - public long Status { get; set; } - - [JsonProperty("TC")] - public bool Tc { get; set; } - - [JsonProperty("RD")] - public bool Rd { get; set; } - - [JsonProperty("RA")] - public bool Ra { get; set; } - - [JsonProperty("AD")] - public bool Ad { get; set; } - - [JsonProperty("CD")] - public bool Cd { get; set; } - - [JsonProperty("Question")] - public List Questions { get; set; } - - [JsonProperty("Answer")] - public List Answers { get; set; } - - public class Answer - { - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("type")] - public long Type { get; set; } - - [JsonProperty("TTL")] - public long Ttl { get; set; } - - [JsonProperty("data")] - public string Data { get; set; } - } - - public class Question - { - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("type")] - public long Type { get; set; } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Response/FollowingResponse.cs b/src/Pixeval/Data/Web/Response/FollowingResponse.cs deleted file mode 100644 index ab350afb..00000000 --- a/src/Pixeval/Data/Web/Response/FollowingResponse.cs +++ /dev/null @@ -1,263 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace Pixeval.Data.Web.Response -{ - public class FollowingResponse - { - [JsonProperty("user_previews")] - public List UserPreviews { get; set; } - - [JsonProperty("next_url")] - public string NextUrl { get; set; } - - public class UserPreview - { - [JsonProperty("user")] - public User User { get; set; } - - [JsonProperty("illusts")] - public List Illusts { get; set; } - - [JsonProperty("novels")] - public List Novels { get; set; } - - [JsonProperty("is_muted")] - public bool IsMuted { get; set; } - } - - public class Illust - { - [JsonProperty("id")] - public long Id { get; set; } - - [JsonProperty("title")] - public string Title { get; set; } - - [JsonProperty("type")] - public string Type { get; set; } - - [JsonProperty("image_urls")] - public ImageUrls ImageUrls { get; set; } - - [JsonProperty("caption")] - public string Caption { get; set; } - - [JsonProperty("restrict")] - public long Restrict { get; set; } - - [JsonProperty("user")] - public User User { get; set; } - - [JsonProperty("tags")] - public List Tags { get; set; } - - [JsonProperty("tools")] - public List Tools { get; set; } - - [JsonProperty("create_date")] - public DateTimeOffset CreateDate { get; set; } - - [JsonProperty("page_count")] - public long PageCount { get; set; } - - [JsonProperty("width")] - public long Width { get; set; } - - [JsonProperty("height")] - public long Height { get; set; } - - [JsonProperty("sanity_level")] - public long SanityLevel { get; set; } - - [JsonProperty("x_restrict")] - public long XRestrict { get; set; } - - [JsonProperty("series")] - public Series Series { get; set; } - - [JsonProperty("meta_single_page")] - public MetaSinglePage MetaSinglePage { get; set; } - - [JsonProperty("meta_pages")] - public List MetaPages { get; set; } - - [JsonProperty("total_view")] - public long TotalView { get; set; } - - [JsonProperty("total_bookmarks")] - public long TotalBookmarks { get; set; } - - [JsonProperty("is_bookmarked")] - public bool IsBookmarked { get; set; } - - [JsonProperty("visible")] - public bool Visible { get; set; } - - [JsonProperty("is_muted")] - public bool IsMuted { get; set; } - } - - public class ImageUrls - { - [JsonProperty("square_medium")] - public string SquareMedium { get; set; } - - [JsonProperty("medium")] - public string Medium { get; set; } - - [JsonProperty("large")] - public string Large { get; set; } - - [JsonProperty("original", NullValueHandling = NullValueHandling.Ignore)] - public Uri Original { get; set; } - } - - public class MetaPage - { - [JsonProperty("image_urls")] - public ImageUrls ImageUrls { get; set; } - } - - public class MetaSinglePage - { - [JsonProperty("original_image_url", NullValueHandling = NullValueHandling.Ignore)] - public Uri OriginalImageUrl { get; set; } - } - - public class Series - { - [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)] - public long? Id { get; set; } - - [JsonProperty("title", NullValueHandling = NullValueHandling.Ignore)] - public string Title { get; set; } - } - - public class IllustTag - { - [JsonProperty("name")] - public string Name { get; set; } - } - - public class User - { - [JsonProperty("id")] - public long Id { get; set; } - - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("account")] - public string Account { get; set; } - - [JsonProperty("profile_image_urls")] - public ProfileImageUrls ProfileImageUrls { get; set; } - - [JsonProperty("is_followed")] - public bool IsFollowed { get; set; } - } - - public class ProfileImageUrls - { - [JsonProperty("medium")] - public string Medium { get; set; } - } - - public class Novel - { - [JsonProperty("id")] - public long Id { get; set; } - - [JsonProperty("title")] - public string Title { get; set; } - - [JsonProperty("caption")] - public string Caption { get; set; } - - [JsonProperty("restrict")] - public long Restrict { get; set; } - - [JsonProperty("x_restrict")] - public long XRestrict { get; set; } - - [JsonProperty("is_original")] - public bool IsOriginal { get; set; } - - [JsonProperty("image_urls")] - public ImageUrls ImageUrls { get; set; } - - [JsonProperty("create_date")] - public DateTimeOffset CreateDate { get; set; } - - [JsonProperty("tags")] - public List Tags { get; set; } - - [JsonProperty("page_count")] - public long PageCount { get; set; } - - [JsonProperty("text_length")] - public long TextLength { get; set; } - - [JsonProperty("user")] - public User User { get; set; } - - [JsonProperty("series")] - public Series Series { get; set; } - - [JsonProperty("is_bookmarked")] - public bool IsBookmarked { get; set; } - - [JsonProperty("total_bookmarks")] - public long TotalBookmarks { get; set; } - - [JsonProperty("total_view")] - public long TotalView { get; set; } - - [JsonProperty("visible")] - public bool Visible { get; set; } - - [JsonProperty("total_comments")] - public long TotalComments { get; set; } - - [JsonProperty("is_muted")] - public bool IsMuted { get; set; } - - [JsonProperty("is_mypixiv_only")] - public bool IsMypixivOnly { get; set; } - - [JsonProperty("is_x_restricted")] - public bool IsXRestricted { get; set; } - } - - public class NovelTag - { - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("added_by_uploaded_user")] - public bool AddedByUploadedUser { get; set; } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Response/GalleryResponse.cs b/src/Pixeval/Data/Web/Response/GalleryResponse.cs deleted file mode 100644 index 62e2bf2a..00000000 --- a/src/Pixeval/Data/Web/Response/GalleryResponse.cs +++ /dev/null @@ -1,204 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using Newtonsoft.Json; -using Pixeval.Data.ViewModel; -using Pixeval.Objects.Generic; -using Pixeval.Objects.Primitive; - -namespace Pixeval.Data.Web.Response -{ - public class GalleryResponse - { - [JsonProperty("illusts")] - public List Illusts { get; set; } - - [JsonProperty("next_url")] - public string NextUrl { get; set; } - - public class Illust : IParser - { - [JsonProperty("id")] - public long Id { get; set; } - - [JsonProperty("title")] - public string Title { get; set; } - - [JsonProperty("type")] - public string Type { get; set; } - - [JsonProperty("image_urls")] - public ImageUrls ImageUrls { get; set; } - - [JsonProperty("caption")] - public string Caption { get; set; } - - [JsonProperty("restrict")] - public long Restrict { get; set; } - - [JsonProperty("user")] - public User User { get; set; } - - [JsonProperty("tags")] - public List Tags { get; set; } - - [JsonProperty("tools")] - public List Tools { get; set; } - - [JsonProperty("create_date")] - public DateTimeOffset CreateDate { get; set; } - - [JsonProperty("page_count")] - public long PageCount { get; set; } - - [JsonProperty("width")] - public long Width { get; set; } - - [JsonProperty("height")] - public long Height { get; set; } - - [JsonProperty("sanity_level")] - public long SanityLevel { get; set; } - - [JsonProperty("x_restrict")] - public long XRestrict { get; set; } - - [JsonProperty("meta_single_page")] - public MetaSinglePage MetaSinglePage { get; set; } - - [JsonProperty("meta_pages")] - public List MetaPages { get; set; } - - [JsonProperty("total_view")] - public long TotalView { get; set; } - - [JsonProperty("total_bookmarks")] - public long TotalBookmarks { get; set; } - - [JsonProperty("is_bookmarked")] - public bool IsBookmarked { get; set; } - - [JsonProperty("visible")] - public bool Visible { get; set; } - - [JsonProperty("is_muted")] - public bool IsMuted { get; set; } - - public Illustration Parse() - { - return new Illustration - { - Bookmark = (int) TotalBookmarks, - Id = Id.ToString(), - IsLiked = IsBookmarked, - IsManga = PageCount != 1, - IsUgoira = Type == "ugoira", - Origin = MetaSinglePage.OriginalImageUrl, - Large = ImageUrls.Large, - Tags = Tags.Select(t => new ViewModel.Tag {Name = t.Name, TranslatedName = t.TranslatedName}), - Thumbnail = ImageUrls.Medium.IsNullOrEmpty() ? ImageUrls.SquareMedium : ImageUrls.Medium, - Title = Title, - UserId = User.Id.ToString(), - UserName = User.Name, - Resolution = $"{Width}x{Height}", - ViewCount = (int) TotalView, - PublishDate = CreateDate - }.Apply(i => - { - if (i.IsManga) - { - i.MangaMetadata = MetaPages.Select(p => - { - var page = (Illustration) i.Clone(); - page.Thumbnail = p.ImageUrls.Medium; - page.Origin = p.ImageUrls.Original; - page.Large = p.ImageUrls.Large; - return page; - }).ToArray(); - foreach (var illustration in i.MangaMetadata) illustration.MangaMetadata = i.MangaMetadata; - } - }); - } - } - - public class ImageUrls - { - [JsonProperty("square_medium")] - public string SquareMedium { get; set; } - - [JsonProperty("medium")] - public string Medium { get; set; } - - [JsonProperty("large")] - public string Large { get; set; } - - [JsonProperty("original", NullValueHandling = NullValueHandling.Ignore)] - public string Original { get; set; } - } - - public class MetaPage - { - [JsonProperty("image_urls")] - public ImageUrls ImageUrls { get; set; } - } - - public class MetaSinglePage - { - [JsonProperty("original_image_url", NullValueHandling = NullValueHandling.Ignore)] - public string OriginalImageUrl { get; set; } - } - - public class Tag - { - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("translated_name")] - public string TranslatedName { get; set; } - } - - public class User - { - [JsonProperty("id")] - public long Id { get; set; } - - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("account")] - public string Account { get; set; } - - [JsonProperty("profile_image_urls")] - public ProfileImageUrls ProfileImageUrls { get; set; } - - [JsonProperty("is_followed")] - public bool IsFollowed { get; set; } - } - - public class ProfileImageUrls - { - [JsonProperty("medium")] - public string Medium { get; set; } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Response/QueryWorksResponse.cs b/src/Pixeval/Data/Web/Response/QueryWorksResponse.cs deleted file mode 100644 index 470e5e06..00000000 --- a/src/Pixeval/Data/Web/Response/QueryWorksResponse.cs +++ /dev/null @@ -1,203 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using Newtonsoft.Json; -using Pixeval.Data.ViewModel; -using Pixeval.Objects.Generic; - -namespace Pixeval.Data.Web.Response -{ - public class QueryWorksResponse - { - [JsonProperty("illusts")] - public List Illusts { get; set; } - - [JsonProperty("next_url")] - public string NextUrl { get; set; } - - public class Illust : IParser - { - [JsonProperty("id")] - public long Id { get; set; } - - [JsonProperty("title")] - public string Title { get; set; } - - [JsonProperty("type")] - public string Type { get; set; } - - [JsonProperty("image_urls")] - public ImageUrls ImageUrls { get; set; } - - [JsonProperty("caption")] - public string Caption { get; set; } - - [JsonProperty("restrict")] - public long Restrict { get; set; } - - [JsonProperty("user")] - public User User { get; set; } - - [JsonProperty("tags")] - public List Tags { get; set; } - - [JsonProperty("tools")] - public List Tools { get; set; } - - [JsonProperty("create_date")] - public DateTimeOffset CreateDate { get; set; } - - [JsonProperty("page_count")] - public long PageCount { get; set; } - - [JsonProperty("width")] - public long Width { get; set; } - - [JsonProperty("height")] - public long Height { get; set; } - - [JsonProperty("sanity_level")] - public long SanityLevel { get; set; } - - [JsonProperty("x_restrict")] - public long XRestrict { get; set; } - - [JsonProperty("meta_single_page")] - public MetaSinglePage MetaSinglePage { get; set; } - - [JsonProperty("meta_pages")] - public List MetaPages { get; set; } - - [JsonProperty("total_view")] - public long TotalView { get; set; } - - [JsonProperty("total_bookmarks")] - public long TotalBookmarks { get; set; } - - [JsonProperty("is_bookmarked")] - public bool IsBookmarked { get; set; } - - [JsonProperty("visible")] - public bool Visible { get; set; } - - [JsonProperty("is_muted")] - public bool IsMuted { get; set; } - - public Illustration Parse() - { - return new Illustration - { - Bookmark = (int) TotalBookmarks, - Id = Id.ToString(), - IsLiked = IsBookmarked, - IsUgoira = Type == "ugoira", - IsManga = !MetaPages.IsNullOrEmpty(), - Origin = MetaSinglePage.OriginalImageUrl ?? ImageUrls.Large, - Large = ImageUrls.Large, - Tags = Tags.Select(t => new ViewModel.Tag {Name = t.Name, TranslatedName = t.TranslatedName}), - Thumbnail = ImageUrls.Medium ?? ImageUrls.SquareMedium, - Title = Title, - UserId = User.Id.ToString(), - UserName = User.Name, - Resolution = $"{Width}x{Height}", - ViewCount = (int) TotalView, - PublishDate = CreateDate - }.Apply(i => - { - if (i.IsManga) - { - i.MangaMetadata = MetaPages.Select(p => - { - var page = (Illustration) i.Clone(); - page.Thumbnail = p.ImageUrls.Medium ?? p.ImageUrls.SquareMedium; - page.Origin = p.ImageUrls.Original; - page.Large = p.ImageUrls.Large; - return page; - }).ToArray(); - foreach (var illustration in i.MangaMetadata) illustration.MangaMetadata = i.MangaMetadata; - } - }); - } - } - - public class ImageUrls - { - [JsonProperty("square_medium")] - public string SquareMedium { get; set; } - - [JsonProperty("medium")] - public string Medium { get; set; } - - [JsonProperty("large")] - public string Large { get; set; } - - [JsonProperty("original", NullValueHandling = NullValueHandling.Ignore)] - public string Original { get; set; } - } - - public class MetaPage - { - [JsonProperty("image_urls")] - public ImageUrls ImageUrls { get; set; } - } - - public class MetaSinglePage - { - [JsonProperty("original_image_url", NullValueHandling = NullValueHandling.Ignore)] - public string OriginalImageUrl { get; set; } - } - - public class Tag - { - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("translated_name")] - public string TranslatedName { get; set; } - } - - public class User - { - [JsonProperty("id")] - public long Id { get; set; } - - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("account")] - public string Account { get; set; } - - [JsonProperty("profile_image_urls")] - public ProfileImageUrls ProfileImageUrls { get; set; } - - [JsonProperty("is_followed")] - public bool IsFollowed { get; set; } - } - - public class ProfileImageUrls - { - [JsonProperty("medium")] - public string Medium { get; set; } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Response/RankingResponse.cs b/src/Pixeval/Data/Web/Response/RankingResponse.cs deleted file mode 100644 index 525beed2..00000000 --- a/src/Pixeval/Data/Web/Response/RankingResponse.cs +++ /dev/null @@ -1,204 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using Newtonsoft.Json; -using Pixeval.Data.ViewModel; -using Pixeval.Objects.Generic; -using Pixeval.Objects.Primitive; - -namespace Pixeval.Data.Web.Response -{ - public class RankingResponse - { - [JsonProperty("illusts")] - public List Illusts { get; set; } - - [JsonProperty("next_url")] - public string NextUrl { get; set; } - - public class Illust : IParser - { - [JsonProperty("id")] - public long Id { get; set; } - - [JsonProperty("title")] - public string Title { get; set; } - - [JsonProperty("type")] - public string Type { get; set; } - - [JsonProperty("image_urls")] - public ImageUrls ImageUrls { get; set; } - - [JsonProperty("caption")] - public string Caption { get; set; } - - [JsonProperty("restrict")] - public long Restrict { get; set; } - - [JsonProperty("user")] - public User User { get; set; } - - [JsonProperty("tags")] - public List Tags { get; set; } - - [JsonProperty("tools")] - public List Tools { get; set; } - - [JsonProperty("create_date")] - public DateTimeOffset CreateDate { get; set; } - - [JsonProperty("page_count")] - public long PageCount { get; set; } - - [JsonProperty("width")] - public long Width { get; set; } - - [JsonProperty("height")] - public long Height { get; set; } - - [JsonProperty("sanity_level")] - public long SanityLevel { get; set; } - - [JsonProperty("x_restrict")] - public long XRestrict { get; set; } - - [JsonProperty("meta_single_page")] - public MetaSinglePage MetaSinglePage { get; set; } - - [JsonProperty("meta_pages")] - public List MetaPages { get; set; } - - [JsonProperty("total_view")] - public long TotalView { get; set; } - - [JsonProperty("total_bookmarks")] - public long TotalBookmarks { get; set; } - - [JsonProperty("is_bookmarked")] - public bool IsBookmarked { get; set; } - - [JsonProperty("visible")] - public bool Visible { get; set; } - - [JsonProperty("is_muted")] - public bool IsMuted { get; set; } - - public Illustration Parse() - { - return new Illustration - { - Bookmark = (int) TotalBookmarks, - Id = Id.ToString(), - IsLiked = IsBookmarked, - IsManga = PageCount != 1, - IsUgoira = Type == "ugoira", - Origin = MetaSinglePage.OriginalImageUrl, - Large = ImageUrls.Large, - Tags = Tags.Select(t => new ViewModel.Tag {Name = t.Name, TranslatedName = t.TranslatedName}), - Thumbnail = ImageUrls.Medium.IsNullOrEmpty() ? ImageUrls.SquareMedium : ImageUrls.Medium, - Title = Title, - UserId = User.Id.ToString(), - UserName = User.Name, - Resolution = $"{Width}x{Height}", - ViewCount = (int) TotalView, - PublishDate = CreateDate - }.Apply(i => - { - if (i.IsManga) - { - i.MangaMetadata = MetaPages.Select(p => - { - var page = (Illustration) i.Clone(); - page.Thumbnail = p.ImageUrls.Medium; - page.Origin = p.ImageUrls.Original; - page.Large = p.ImageUrls.Large; - return page; - }).ToArray(); - foreach (var illustration in i.MangaMetadata) illustration.MangaMetadata = i.MangaMetadata; - } - }); - } - } - - public class ImageUrls - { - [JsonProperty("square_medium")] - public string SquareMedium { get; set; } - - [JsonProperty("medium")] - public string Medium { get; set; } - - [JsonProperty("large")] - public string Large { get; set; } - - [JsonProperty("original", NullValueHandling = NullValueHandling.Ignore)] - public string Original { get; set; } - } - - public class MetaPage - { - [JsonProperty("image_urls")] - public ImageUrls ImageUrls { get; set; } - } - - public class MetaSinglePage - { - [JsonProperty("original_image_url", NullValueHandling = NullValueHandling.Ignore)] - public string OriginalImageUrl { get; set; } - } - - public class Tag - { - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("translated_name")] - public string TranslatedName { get; set; } - } - - public class User - { - [JsonProperty("id")] - public long Id { get; set; } - - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("account")] - public string Account { get; set; } - - [JsonProperty("profile_image_urls")] - public ProfileImageUrls ProfileImageUrls { get; set; } - - [JsonProperty("is_followed")] - public bool IsFollowed { get; set; } - } - - public class ProfileImageUrls - { - [JsonProperty("medium")] - public string Medium { get; set; } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Response/RecommendIllustratorResponse.cs b/src/Pixeval/Data/Web/Response/RecommendIllustratorResponse.cs deleted file mode 100644 index ebe2a611..00000000 --- a/src/Pixeval/Data/Web/Response/RecommendIllustratorResponse.cs +++ /dev/null @@ -1,179 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Linq; -using System.Text.RegularExpressions; -using Newtonsoft.Json; - -namespace Pixeval.Data.Web.Response -{ - public class RecommendIllustratorResponse - { - [JsonProperty("user_previews")] - public UserPreview[] UserPreviews { get; set; } - - [JsonProperty("next_url")] - public string NextUrl { get; set; } - - public class UserPreview : IParser - { - [JsonProperty("user")] - public User User { get; set; } - - [JsonProperty("illusts")] - public Illust[] Illusts { get; set; } - - [JsonProperty("is_muted")] - public bool IsMuted { get; set; } - - public ViewModel.User Parse() - { - return new ViewModel.User {Avatar = Regex.Replace(User.ProfileImageUrls.Medium, "_170\\.", "_50."), Id = User.Id.ToString(), Name = User.Name, Thumbnails = Illusts.Select(i => i.ImageUrls.SquareMedium).ToArray()}; - } - } - - public class Illust - { - [JsonProperty("id")] - public long Id { get; set; } - - [JsonProperty("title")] - public string Title { get; set; } - - [JsonProperty("type")] - public string Type { get; set; } - - [JsonProperty("image_urls")] - public ImageUrls ImageUrls { get; set; } - - [JsonProperty("caption")] - public string Caption { get; set; } - - [JsonProperty("restrict")] - public long Restrict { get; set; } - - [JsonProperty("user")] - public User User { get; set; } - - [JsonProperty("tags")] - public Tag[] Tags { get; set; } - - [JsonProperty("tools")] - public string[] Tools { get; set; } - - [JsonProperty("create_date")] - public DateTimeOffset CreateDate { get; set; } - - [JsonProperty("page_count")] - public long PageCount { get; set; } - - [JsonProperty("width")] - public long Width { get; set; } - - [JsonProperty("height")] - public long Height { get; set; } - - [JsonProperty("sanity_level")] - public long SanityLevel { get; set; } - - [JsonProperty("x_restrict")] - public long XRestrict { get; set; } - - [JsonProperty("meta_single_page")] - public MetaSinglePage MetaSinglePage { get; set; } - - [JsonProperty("meta_pages")] - public MetaPage[] MetaPages { get; set; } - - [JsonProperty("total_view")] - public long TotalView { get; set; } - - [JsonProperty("total_bookmarks")] - public long TotalBookmarks { get; set; } - - [JsonProperty("is_bookmarked")] - public bool IsBookmarked { get; set; } - - [JsonProperty("visible")] - public bool Visible { get; set; } - - [JsonProperty("is_muted")] - public bool IsMuted { get; set; } - } - - public class ImageUrls - { - [JsonProperty("square_medium")] - public string SquareMedium { get; set; } - - [JsonProperty("medium")] - public string Medium { get; set; } - - [JsonProperty("large")] - public string Large { get; set; } - - [JsonProperty("original", NullValueHandling = NullValueHandling.Ignore)] - public string Original { get; set; } - } - - public class MetaPage - { - [JsonProperty("image_urls")] - public ImageUrls ImageUrls { get; set; } - } - - public class MetaSinglePage - { - [JsonProperty("original_image_url", NullValueHandling = NullValueHandling.Ignore)] - public string OriginalImageUrl { get; set; } - } - - public class Tag - { - [JsonProperty("name")] - public string Name { get; set; } - } - - public class User - { - [JsonProperty("id")] - public long Id { get; set; } - - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("account")] - public string Account { get; set; } - - [JsonProperty("profile_image_urls")] - public ProfileImageUrls ProfileImageUrls { get; set; } - - [JsonProperty("is_followed")] - public bool IsFollowed { get; set; } - } - - public class ProfileImageUrls - { - [JsonProperty("medium")] - public string Medium { get; set; } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Response/RecommendResponse.cs b/src/Pixeval/Data/Web/Response/RecommendResponse.cs deleted file mode 100644 index d20cf825..00000000 --- a/src/Pixeval/Data/Web/Response/RecommendResponse.cs +++ /dev/null @@ -1,207 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using Newtonsoft.Json; -using Pixeval.Data.ViewModel; -using Pixeval.Objects.Generic; -using Pixeval.Objects.Primitive; - -namespace Pixeval.Data.Web.Response -{ - public class RecommendResponse - { - [JsonProperty("illusts")] - public List Illusts { get; set; } - - [JsonProperty("contest_exists")] - public bool ContestExists { get; set; } - - [JsonProperty("next_url")] - public string NextUrl { get; set; } - - public class Illust : IParser - { - [JsonProperty("id")] - public long Id { get; set; } - - [JsonProperty("title")] - public string Title { get; set; } - - [JsonProperty("type")] - public string Type { get; set; } - - [JsonProperty("image_urls")] - public ImageUrls ImageUrls { get; set; } - - [JsonProperty("caption")] - public string Caption { get; set; } - - [JsonProperty("restrict")] - public long Restrict { get; set; } - - [JsonProperty("user")] - public User User { get; set; } - - [JsonProperty("tags")] - public List Tags { get; set; } - - [JsonProperty("tools")] - public List Tools { get; set; } - - [JsonProperty("create_date")] - public DateTimeOffset CreateDate { get; set; } - - [JsonProperty("page_count")] - public long PageCount { get; set; } - - [JsonProperty("width")] - public long Width { get; set; } - - [JsonProperty("height")] - public long Height { get; set; } - - [JsonProperty("sanity_level")] - public long SanityLevel { get; set; } - - [JsonProperty("x_restrict")] - public long XRestrict { get; set; } - - [JsonProperty("meta_single_page")] - public MetaSinglePage MetaSinglePage { get; set; } - - [JsonProperty("meta_pages")] - public List MetaPages { get; set; } - - [JsonProperty("total_view")] - public long TotalView { get; set; } - - [JsonProperty("total_bookmarks")] - public long TotalBookmarks { get; set; } - - [JsonProperty("is_bookmarked")] - public bool IsBookmarked { get; set; } - - [JsonProperty("visible")] - public bool Visible { get; set; } - - [JsonProperty("is_muted")] - public bool IsMuted { get; set; } - - public Illustration Parse() - { - return new Illustration - { - Bookmark = (int) TotalBookmarks, - Id = Id.ToString(), - IsLiked = IsBookmarked, - IsManga = PageCount != 1, - IsUgoira = Type == "ugoira", - Origin = MetaSinglePage.OriginalImageUrl.IsNullOrEmpty() ? MetaPages[0].ImageUrls.Original : MetaSinglePage.OriginalImageUrl, - Large = ImageUrls.Large, - Tags = Tags.Select(t => new ViewModel.Tag {Name = t.Name, TranslatedName = t.TranslatedName}), - Thumbnail = ImageUrls.Medium, - Title = Title, - UserId = User.Id.ToString(), - UserName = User.Name, - Resolution = $"{Width}x{Height}", - ViewCount = (int) TotalView, - PublishDate = CreateDate - }.Apply(i => - { - if (i.IsManga) - { - i.MangaMetadata = MetaPages.Select(p => - { - var page = (Illustration) i.Clone(); - page.Thumbnail = p.ImageUrls.Medium; - page.Origin = p.ImageUrls.Original; - page.Large = p.ImageUrls.Large; - return page; - }).ToArray(); - foreach (var illustration in i.MangaMetadata) illustration.MangaMetadata = i.MangaMetadata; - } - }); - } - } - - public class ImageUrls - { - [JsonProperty("square_medium")] - public string SquareMedium { get; set; } - - [JsonProperty("medium")] - public string Medium { get; set; } - - [JsonProperty("large")] - public string Large { get; set; } - - [JsonProperty("original", NullValueHandling = NullValueHandling.Ignore)] - public string Original { get; set; } - } - - public class MetaPage - { - [JsonProperty("image_urls")] - public ImageUrls ImageUrls { get; set; } - } - - public class MetaSinglePage - { - [JsonProperty("original_image_url", NullValueHandling = NullValueHandling.Ignore)] - public string OriginalImageUrl { get; set; } - } - - public class Tag - { - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("translated_name")] - public string TranslatedName { get; set; } - } - - public class User - { - [JsonProperty("id")] - public long Id { get; set; } - - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("account")] - public string Account { get; set; } - - [JsonProperty("profile_image_urls")] - public ProfileImageUrls ProfileImageUrls { get; set; } - - [JsonProperty("is_followed")] - public bool IsFollowed { get; set; } - } - - public class ProfileImageUrls - { - [JsonProperty("medium")] - public string Medium { get; set; } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Response/SingleWorkResponse.cs b/src/Pixeval/Data/Web/Response/SingleWorkResponse.cs deleted file mode 100644 index 430197cb..00000000 --- a/src/Pixeval/Data/Web/Response/SingleWorkResponse.cs +++ /dev/null @@ -1,164 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace Pixeval.Data.Web.Response -{ - public class SingleWorkResponse - { - [JsonProperty("illust")] - public Illust IllustInfo { get; set; } - - public class Illust - { - [JsonProperty("id")] - public long Id { get; set; } - - [JsonProperty("title")] - public string Title { get; set; } - - [JsonProperty("type")] - public string Type { get; set; } - - [JsonProperty("image_urls")] - public ImageUrls ImageUrls { get; set; } - - [JsonProperty("caption")] - public string Caption { get; set; } - - [JsonProperty("restrict")] - public long Restrict { get; set; } - - [JsonProperty("user")] - public User User { get; set; } - - [JsonProperty("tags")] - public List Tags { get; set; } - - [JsonProperty("tools")] - public List Tools { get; set; } - - [JsonProperty("create_date")] - public DateTimeOffset CreateDate { get; set; } - - [JsonProperty("page_count")] - public long PageCount { get; set; } - - [JsonProperty("width")] - public long Width { get; set; } - - [JsonProperty("height")] - public long Height { get; set; } - - [JsonProperty("sanity_level")] - public long SanityLevel { get; set; } - - [JsonProperty("x_restrict")] - public long XRestrict { get; set; } - - [JsonProperty("meta_single_page")] - public MetaSinglePage MetaSinglePage { get; set; } - - [JsonProperty("meta_pages")] - public List MetaPages { get; set; } - - [JsonProperty("total_view")] - public long TotalView { get; set; } - - [JsonProperty("total_bookmarks")] - public long TotalBookmarks { get; set; } - - [JsonProperty("is_bookmarked")] - public bool IsBookmarked { get; set; } - - [JsonProperty("visible")] - public bool Visible { get; set; } - - [JsonProperty("is_muted")] - public bool IsMuted { get; set; } - - [JsonProperty("total_comments")] - public long TotalComments { get; set; } - } - - public class ImageUrls - { - [JsonProperty("square_medium")] - public string SquareMedium { get; set; } - - [JsonProperty("medium")] - public string Medium { get; set; } - - [JsonProperty("large")] - public string Large { get; set; } - - [JsonProperty("original", NullValueHandling = NullValueHandling.Ignore)] - public string Original { get; set; } - } - - public class MetaPage - { - [JsonProperty("image_urls")] - public ImageUrls ImageUrls { get; set; } - } - - public class MetaSinglePage - { - [JsonProperty("original_image_url")] - public string OriginalImageUrl { get; set; } - } - - public class Tag - { - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("translated_name")] - public string TranslatedName { get; set; } - } - - public class User - { - [JsonProperty("id")] - public long Id { get; set; } - - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("account")] - public string Account { get; set; } - - [JsonProperty("profile_image_urls")] - public ProfileImageUrls ProfileImageUrls { get; set; } - - [JsonProperty("is_followed")] - public bool IsFollowed { get; set; } - } - - public class ProfileImageUrls - { - [JsonProperty("medium")] - public string Medium { get; set; } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Response/SpotlightArticleResponse.cs b/src/Pixeval/Data/Web/Response/SpotlightArticleResponse.cs deleted file mode 100644 index 7b406d29..00000000 --- a/src/Pixeval/Data/Web/Response/SpotlightArticleResponse.cs +++ /dev/null @@ -1,49 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace Pixeval.Data.Web.Response -{ - public class SpotlightArticleResponse - { - [JsonProperty("body")] - public List BodyList { get; set; } - - public class Body - { - [JsonProperty("id")] - public string Id { get; set; } - - [JsonProperty("title")] - public string Title { get; set; } - - [JsonProperty("illusts")] - public List Illusts { get; set; } - } - - public class Illust - { - [JsonProperty("illust_id")] - public long IllustId { get; set; } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Response/SpotlightResponse.cs b/src/Pixeval/Data/Web/Response/SpotlightResponse.cs deleted file mode 100644 index 060106b6..00000000 --- a/src/Pixeval/Data/Web/Response/SpotlightResponse.cs +++ /dev/null @@ -1,35 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Collections.Generic; -using Newtonsoft.Json; -using Pixeval.Data.ViewModel; - -namespace Pixeval.Data.Web.Response -{ - public class SpotlightResponse - { - [JsonProperty("spotlight_articles")] - public List SpotlightArticles { get; set; } - - [JsonProperty("next_url")] - public string NextUrl { get; set; } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Response/TokenResponse.cs b/src/Pixeval/Data/Web/Response/TokenResponse.cs deleted file mode 100644 index 29857b25..00000000 --- a/src/Pixeval/Data/Web/Response/TokenResponse.cs +++ /dev/null @@ -1,130 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using Newtonsoft.Json; -using Pixeval.Objects.Exceptions; -using Pixeval.Objects.Primitive; - -namespace Pixeval.Data.Web.Response -{ - public class TokenResponse - { - [JsonProperty("response")] - public Response ToResponse { get; set; } - - public override string ToString() - { - return this.ToJson(); - } - - public class Response - { - [JsonProperty("access_token")] - public string AccessToken { get; set; } - - [JsonProperty("expires_in")] - public long ExpiresIn { get; set; } - - [JsonProperty("token_type")] - public string TokenType { get; set; } - - [JsonProperty("scope")] - public string Scope { get; set; } - - [JsonProperty("refresh_token")] - public string RefreshToken { get; set; } - - [JsonProperty("user")] - public User User { get; set; } - - [JsonProperty("device_token")] - public string DeviceToken { get; set; } - } - - public class User - { - [JsonProperty("profile_image_urls")] - public ProfileImageUrls ProfileImageUrls { get; set; } - - [JsonProperty("id")] - [JsonConverter(typeof(ParseStringConverter))] - public long Id { get; set; } - - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("account")] - public string Account { get; set; } - - [JsonProperty("mail_address")] - public string MailAddress { get; set; } - - [JsonProperty("is_premium")] - public bool IsPremium { get; set; } - - [JsonProperty("x_restrict")] - public long XRestrict { get; set; } - - [JsonProperty("is_mail_authorized")] - public bool IsMailAuthorized { get; set; } - } - - public class ProfileImageUrls - { - [JsonProperty("px_16x16")] - public string Px16X16 { get; set; } - - [JsonProperty("px_50x50")] - public string Px50X50 { get; set; } - - [JsonProperty("px_170x170")] - public string Px170X170 { get; set; } - } - - private class ParseStringConverter : JsonConverter - { - public override bool CanConvert(Type t) - { - return t == typeof(long) || t == typeof(long?); - } - - public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer) - { - if (reader.TokenType == JsonToken.Null) return null; - var value = serializer.Deserialize(reader); - if (long.TryParse(value, out var l)) return l; - throw new TypeMismatchException("Cannot unmarshal type long"); - } - - public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer) - { - if (untypedValue == null) - { - serializer.Serialize(writer, null); - return; - } - - var value = (long) untypedValue; - serializer.Serialize(writer, value.ToString()); - } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Response/TrendingTagResponse.cs b/src/Pixeval/Data/Web/Response/TrendingTagResponse.cs deleted file mode 100644 index 54bc1c65..00000000 --- a/src/Pixeval/Data/Web/Response/TrendingTagResponse.cs +++ /dev/null @@ -1,173 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace Pixeval.Data.Web.Response -{ - public class TrendingTagResponse - { - [JsonProperty("trend_tags")] - public List TrendTags { get; set; } - - public class TrendTag - { - [JsonProperty("tag")] - public string TagStr { get; set; } - - [JsonProperty("translated_name")] - public string TranslatedName { get; set; } - - [JsonProperty("illust")] - public Illust Illust { get; set; } - } - - public class Illust - { - [JsonProperty("id")] - public long Id { get; set; } - - [JsonProperty("title")] - public string Title { get; set; } - - [JsonProperty("type")] - public string Type { get; set; } - - [JsonProperty("image_urls")] - public ImageUrls ImageUrls { get; set; } - - [JsonProperty("caption")] - public string Caption { get; set; } - - [JsonProperty("restrict")] - public long Restrict { get; set; } - - [JsonProperty("user")] - public User User { get; set; } - - [JsonProperty("tags")] - public List Tags { get; set; } - - [JsonProperty("tools")] - public List Tools { get; set; } - - [JsonProperty("create_date")] - public DateTimeOffset CreateDate { get; set; } - - [JsonProperty("page_count")] - public long PageCount { get; set; } - - [JsonProperty("width")] - public long Width { get; set; } - - [JsonProperty("height")] - public long Height { get; set; } - - [JsonProperty("sanity_level")] - public long SanityLevel { get; set; } - - [JsonProperty("x_restrict")] - public long XRestrict { get; set; } - - [JsonProperty("meta_single_page")] - public MetaSinglePage MetaSinglePage { get; set; } - - [JsonProperty("meta_pages")] - public List MetaPages { get; set; } - - [JsonProperty("total_view")] - public long TotalView { get; set; } - - [JsonProperty("total_bookmarks")] - public long TotalBookmarks { get; set; } - - [JsonProperty("is_bookmarked")] - public bool IsBookmarked { get; set; } - - [JsonProperty("visible")] - public bool Visible { get; set; } - - [JsonProperty("is_muted")] - public bool IsMuted { get; set; } - } - - public class ImageUrls - { - [JsonProperty("square_medium")] - public string SquareMedium { get; set; } - - [JsonProperty("medium")] - public string Medium { get; set; } - - [JsonProperty("large")] - public string Large { get; set; } - - [JsonProperty("original", NullValueHandling = NullValueHandling.Ignore)] - public string Original { get; set; } - } - - public class MetaPage - { - [JsonProperty("image_urls")] - public ImageUrls ImageUrls { get; set; } - } - - public class MetaSinglePage - { - [JsonProperty("original_image_url", NullValueHandling = NullValueHandling.Ignore)] - public string OriginalImageUrl { get; set; } - } - - public class Tag - { - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("translated_name")] - public string TranslatedName { get; set; } - } - - public class User - { - [JsonProperty("id")] - public long Id { get; set; } - - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("account")] - public string Account { get; set; } - - [JsonProperty("profile_image_urls")] - public ProfileImageUrls ProfileImageUrls { get; set; } - - [JsonProperty("is_followed")] - public bool IsFollowed { get; set; } - } - - public class ProfileImageUrls - { - [JsonProperty("medium")] - public string Medium { get; set; } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Response/UgoiraMetadataResponse.cs b/src/Pixeval/Data/Web/Response/UgoiraMetadataResponse.cs deleted file mode 100644 index 3730603e..00000000 --- a/src/Pixeval/Data/Web/Response/UgoiraMetadataResponse.cs +++ /dev/null @@ -1,55 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace Pixeval.Data.Web.Response -{ - public class UgoiraMetadataResponse - { - [JsonProperty("ugoira_metadata")] - public UgoiraMetadata UgoiraMetadataInfo { get; set; } - - public class UgoiraMetadata - { - [JsonProperty("zip_urls")] - public ZipUrls ZipUrls { get; set; } - - [JsonProperty("frames")] - public List Frames { get; set; } - } - - public class Frame - { - [JsonProperty("file")] - public string File { get; set; } - - [JsonProperty("delay")] - public long Delay { get; set; } - } - - public class ZipUrls - { - [JsonProperty("medium")] - public string Medium { get; set; } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Response/UploadResponse.cs b/src/Pixeval/Data/Web/Response/UploadResponse.cs deleted file mode 100644 index 5a7042af..00000000 --- a/src/Pixeval/Data/Web/Response/UploadResponse.cs +++ /dev/null @@ -1,206 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using Newtonsoft.Json; -using Pixeval.Data.ViewModel; -using Pixeval.Objects.Generic; - -namespace Pixeval.Data.Web.Response -{ - public class UploadResponse - { - [JsonProperty("illusts")] - public List Illusts { get; set; } - - [JsonProperty("next_url")] - public string NextUrl { get; set; } - - public class Illust : IParser - { - [JsonProperty("id")] - public long Id { get; set; } - - [JsonProperty("title")] - public string Title { get; set; } - - [JsonProperty("type")] - public string Type { get; set; } - - [JsonProperty("image_urls")] - public ImageUrls ImageUrls { get; set; } - - [JsonProperty("caption")] - public string Caption { get; set; } - - [JsonProperty("restrict")] - public long Restrict { get; set; } - - [JsonProperty("user")] - public User User { get; set; } - - [JsonProperty("tags")] - public List Tags { get; set; } - - [JsonProperty("tools")] - public List Tools { get; set; } - - [JsonProperty("create_date")] - public DateTimeOffset CreateDate { get; set; } - - [JsonProperty("page_count")] - public long PageCount { get; set; } - - [JsonProperty("width")] - public long Width { get; set; } - - [JsonProperty("height")] - public long Height { get; set; } - - [JsonProperty("sanity_level")] - public long SanityLevel { get; set; } - - [JsonProperty("x_restrict")] - public long XRestrict { get; set; } - - [JsonProperty("meta_single_page")] - public MetaSinglePage MetaSinglePage { get; set; } - - [JsonProperty("meta_pages")] - public List MetaPages { get; set; } - - [JsonProperty("total_view")] - public long TotalView { get; set; } - - [JsonProperty("total_bookmarks")] - public long TotalBookmarks { get; set; } - - [JsonProperty("is_bookmarked")] - public bool IsBookmarked { get; set; } - - [JsonProperty("visible")] - public bool Visible { get; set; } - - [JsonProperty("is_muted")] - public bool IsMuted { get; set; } - - [JsonProperty("total_comments")] - public long TotalComments { get; set; } - - public Illustration Parse() - { - return new Illustration - { - Bookmark = (int) TotalBookmarks, - Id = Id.ToString(), - IsLiked = IsBookmarked, - IsUgoira = Type == "ugoira", - IsManga = !MetaPages.IsNullOrEmpty(), - Origin = MetaSinglePage.OriginalImageUrl ?? ImageUrls.Large, - Large = ImageUrls.Large, - Tags = Tags.Select(t => new ViewModel.Tag {Name = t.Name, TranslatedName = t.TranslatedName}), - Thumbnail = ImageUrls.Medium ?? ImageUrls.SquareMedium, - Title = Title, - UserId = User.Id.ToString(), - UserName = User.Name, - Resolution = $"{Width}x{Height}", - ViewCount = (int) TotalView, - PublishDate = CreateDate - }.Apply(i => - { - if (i.IsManga) - { - i.MangaMetadata = MetaPages.Select(p => - { - var page = (Illustration) i.Clone(); - page.Thumbnail = p.ImageUrls.Medium ?? p.ImageUrls.SquareMedium; - page.Origin = p.ImageUrls.Original; - page.Large = p.ImageUrls.Large; - return page; - }).ToArray(); - foreach (var illustration in i.MangaMetadata) illustration.MangaMetadata = i.MangaMetadata; - } - }); - } - } - - public class ImageUrls - { - [JsonProperty("square_medium")] - public string SquareMedium { get; set; } - - [JsonProperty("medium")] - public string Medium { get; set; } - - [JsonProperty("large")] - public string Large { get; set; } - - [JsonProperty("original", NullValueHandling = NullValueHandling.Ignore)] - public string Original { get; set; } - } - - public class MetaPage - { - [JsonProperty("image_urls")] - public ImageUrls ImageUrls { get; set; } - } - - public class MetaSinglePage - { - [JsonProperty("original_image_url", NullValueHandling = NullValueHandling.Ignore)] - public string OriginalImageUrl { get; set; } - } - - public class Tag - { - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("translated_name")] - public string TranslatedName { get; set; } - } - - public class User - { - [JsonProperty("id")] - public long Id { get; set; } - - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("account")] - public string Account { get; set; } - - [JsonProperty("profile_image_urls")] - public ProfileImageUrls ProfileImageUrls { get; set; } - - [JsonProperty("is_followed")] - public bool IsFollowed { get; set; } - } - - public class ProfileImageUrls - { - [JsonProperty("medium")] - public string Medium { get; set; } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Response/UserInformationResponse.cs b/src/Pixeval/Data/Web/Response/UserInformationResponse.cs deleted file mode 100644 index cd7e1b95..00000000 --- a/src/Pixeval/Data/Web/Response/UserInformationResponse.cs +++ /dev/null @@ -1,198 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using Newtonsoft.Json; - -namespace Pixeval.Data.Web.Response -{ - public class UserInformationResponse - { - [JsonProperty("user")] - public User UserEntity { get; set; } - - [JsonProperty("profile")] - public Profile UserProfile { get; set; } - - [JsonProperty("profile_publicity")] - public ProfilePublicity UserProfilePublicity { get; set; } - - [JsonProperty("workspace")] - public Workspace UserWorkspace { get; set; } - - public class Profile - { - [JsonProperty("webpage")] - public string Webpage { get; set; } - - [JsonProperty("gender")] - public string Gender { get; set; } - - [JsonProperty("birth")] - public string Birth { get; set; } - - [JsonProperty("birth_day")] - public string BirthDay { get; set; } - - [JsonProperty("birth_year")] - public long BirthYear { get; set; } - - [JsonProperty("region")] - public string Region { get; set; } - - [JsonProperty("address_id")] - public long AddressId { get; set; } - - [JsonProperty("country_code")] - public string CountryCode { get; set; } - - [JsonProperty("job")] - public string Job { get; set; } - - [JsonProperty("job_id")] - public long JobId { get; set; } - - [JsonProperty("total_follow_users")] - public long TotalFollowUsers { get; set; } - - [JsonProperty("total_mypixiv_users")] - public long TotalMypixivUsers { get; set; } - - [JsonProperty("total_illusts")] - public long TotalIllusts { get; set; } - - [JsonProperty("total_manga")] - public long TotalManga { get; set; } - - [JsonProperty("total_novels")] - public long TotalNovels { get; set; } - - [JsonProperty("total_illust_bookmarks_public")] - public long TotalIllustBookmarksPublic { get; set; } - - [JsonProperty("total_illust_series")] - public long TotalIllustSeries { get; set; } - - [JsonProperty("total_novel_series")] - public long TotalNovelSeries { get; set; } - - [JsonProperty("background_image_url")] - public string BackgroundImageUrl { get; set; } - - [JsonProperty("twitter_account")] - public string TwitterAccount { get; set; } - - [JsonProperty("twitter_url")] - public string TwitterUrl { get; set; } - - [JsonProperty("is_premium")] - public bool IsPremium { get; set; } - - [JsonProperty("is_using_custom_profile_image")] - public bool IsUsingCustomProfileImage { get; set; } - } - - public class ProfilePublicity - { - [JsonProperty("gender")] - public string Gender { get; set; } - - [JsonProperty("region")] - public string Region { get; set; } - - [JsonProperty("birth_day")] - public string BirthDay { get; set; } - - [JsonProperty("birth_year")] - public string BirthYear { get; set; } - - [JsonProperty("job")] - public string Job { get; set; } - - [JsonProperty("pawoo")] - public bool Pawoo { get; set; } - } - - public class User - { - [JsonProperty("id")] - public long Id { get; set; } - - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("account")] - public string Account { get; set; } - - [JsonProperty("profile_image_urls")] - public ProfileImageUrls ProfileImageUrls { get; set; } - - [JsonProperty("comment")] - public string Comment { get; set; } - - [JsonProperty("is_followed")] - public bool IsFollowed { get; set; } - } - - public class ProfileImageUrls - { - [JsonProperty("medium")] - public string Medium { get; set; } - } - - public class Workspace - { - [JsonProperty("pc")] - public string Pc { get; set; } - - [JsonProperty("monitor")] - public string Monitor { get; set; } - - [JsonProperty("tool")] - public string Tool { get; set; } - - [JsonProperty("scanner")] - public string Scanner { get; set; } - - [JsonProperty("tablet")] - public string Tablet { get; set; } - - [JsonProperty("mouse")] - public string Mouse { get; set; } - - [JsonProperty("printer")] - public string Printer { get; set; } - - [JsonProperty("desktop")] - public string Desktop { get; set; } - - [JsonProperty("music")] - public string Music { get; set; } - - [JsonProperty("desk")] - public string Desk { get; set; } - - [JsonProperty("chair")] - public string Chair { get; set; } - - [JsonProperty("comment")] - public string Comment { get; set; } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Response/UserNavResponse.cs b/src/Pixeval/Data/Web/Response/UserNavResponse.cs deleted file mode 100644 index 7ccb440d..00000000 --- a/src/Pixeval/Data/Web/Response/UserNavResponse.cs +++ /dev/null @@ -1,106 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Collections.Generic; -using Newtonsoft.Json; -using Pixeval.Objects.Primitive; - -namespace Pixeval.Data.Web.Response -{ - public class UserNavResponse - { - [JsonProperty("user_previews")] - public List UserPreviews { get; set; } - - [JsonProperty("next_url")] - public string NextUrl { get; set; } - - public override string ToString() - { - return this.ToJson(); - } - - public class UserPreview - { - [JsonProperty("user")] - public User User { get; set; } - - [JsonProperty("illusts")] - public List Illusts { get; set; } - - [JsonProperty("is_muted")] - public bool IsMuted { get; set; } - } - - public class Illust - { - [JsonProperty("type")] - public string Type { get; set; } - - [JsonProperty("image_urls")] - public ImageUrls ImageUrl { get; set; } - - [JsonProperty("tools")] - public string[] Tools { get; set; } - - [JsonProperty("page_count")] - public long PageCount { get; set; } - } - - public class ImageUrls - { - [JsonProperty("square_medium")] - public string SquareMedium { get; set; } - - [JsonProperty("medium")] - public string Medium { get; set; } - - [JsonProperty("large")] - public string Large { get; set; } - - [JsonProperty("original", NullValueHandling = NullValueHandling.Ignore)] - public string Original { get; set; } - } - - public class User - { - [JsonProperty("id")] - public long Id { get; set; } - - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("account")] - public string Account { get; set; } - - [JsonProperty("profile_image_urls")] - public ProfileImageUrls ProfileImageUrls { get; set; } - - [JsonProperty("is_followed")] - public bool IsFollowed { get; set; } - } - - public class ProfileImageUrls - { - [JsonProperty("medium")] - public string Medium { get; set; } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Response/UserUpdateResponse.cs b/src/Pixeval/Data/Web/Response/UserUpdateResponse.cs deleted file mode 100644 index 506f316a..00000000 --- a/src/Pixeval/Data/Web/Response/UserUpdateResponse.cs +++ /dev/null @@ -1,204 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using Newtonsoft.Json; -using Pixeval.Data.ViewModel; -using Pixeval.Objects.Generic; -using Pixeval.Objects.Primitive; - -namespace Pixeval.Data.Web.Response -{ - public class UserUpdateResponse - { - [JsonProperty("illusts")] - public List Illusts { get; set; } - - [JsonProperty("next_url")] - public string NextUrl { get; set; } - - public class Illust : IParser - { - [JsonProperty("id")] - public long Id { get; set; } - - [JsonProperty("title")] - public string Title { get; set; } - - [JsonProperty("type")] - public string Type { get; set; } - - [JsonProperty("image_urls")] - public ImageUrls ImageUrls { get; set; } - - [JsonProperty("caption")] - public string Caption { get; set; } - - [JsonProperty("restrict")] - public long Restrict { get; set; } - - [JsonProperty("user")] - public User User { get; set; } - - [JsonProperty("tags")] - public List Tags { get; set; } - - [JsonProperty("tools")] - public List Tools { get; set; } - - [JsonProperty("create_date")] - public DateTimeOffset CreateDate { get; set; } - - [JsonProperty("page_count")] - public long PageCount { get; set; } - - [JsonProperty("width")] - public long Width { get; set; } - - [JsonProperty("height")] - public long Height { get; set; } - - [JsonProperty("sanity_level")] - public long SanityLevel { get; set; } - - [JsonProperty("x_restrict")] - public long XRestrict { get; set; } - - [JsonProperty("meta_single_page")] - public MetaSinglePage MetaSinglePage { get; set; } - - [JsonProperty("meta_pages")] - public List MetaPages { get; set; } - - [JsonProperty("total_view")] - public long TotalView { get; set; } - - [JsonProperty("total_bookmarks")] - public long TotalBookmarks { get; set; } - - [JsonProperty("is_bookmarked")] - public bool IsBookmarked { get; set; } - - [JsonProperty("visible")] - public bool Visible { get; set; } - - [JsonProperty("is_muted")] - public bool IsMuted { get; set; } - - public Illustration Parse() - { - return new Illustration - { - Bookmark = (int) TotalBookmarks, - Id = Id.ToString(), - IsLiked = IsBookmarked, - IsManga = PageCount != 1, - IsUgoira = Type == "ugoira", - Origin = MetaSinglePage.OriginalImageUrl.IsNullOrEmpty() ? ImageUrls.Large : MetaSinglePage.OriginalImageUrl, - Large = ImageUrls.Large, - Tags = Tags.Select(t => new ViewModel.Tag {Name = t.Name, TranslatedName = t.TranslatedName}), - Thumbnail = ImageUrls.Medium, - UserId = User.Id.ToString(), - UserName = User.Name, - Title = Title, - Resolution = $"{Width}x{Height}", - ViewCount = (int) TotalView, - PublishDate = CreateDate - }.Apply(i => - { - if (i.IsManga) - { - i.MangaMetadata = MetaPages.Select(p => - { - var page = (Illustration) i.Clone(); - page.Thumbnail = p.ImageUrls.Medium; - page.Origin = p.ImageUrls.Original; - page.Large = p.ImageUrls.Large; - return page; - }).ToArray(); - foreach (var illustration in i.MangaMetadata) illustration.MangaMetadata = i.MangaMetadata; - } - }); - } - } - - public class ImageUrls - { - [JsonProperty("square_medium")] - public string SquareMedium { get; set; } - - [JsonProperty("medium")] - public string Medium { get; set; } - - [JsonProperty("large")] - public string Large { get; set; } - - [JsonProperty("original", NullValueHandling = NullValueHandling.Ignore)] - public string Original { get; set; } - } - - public class MetaPage - { - [JsonProperty("image_urls")] - public ImageUrls ImageUrls { get; set; } - } - - public class MetaSinglePage - { - [JsonProperty("original_image_url", NullValueHandling = NullValueHandling.Ignore)] - public string OriginalImageUrl { get; set; } - } - - public class Tag - { - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("translated_name")] - public string TranslatedName { get; set; } - } - - public class User - { - [JsonProperty("id")] - public long Id { get; set; } - - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("account")] - public string Account { get; set; } - - [JsonProperty("profile_image_urls")] - public ProfileImageUrls ProfileImageUrls { get; set; } - - [JsonProperty("is_followed")] - public bool IsFollowed { get; set; } - } - - public class ProfileImageUrls - { - [JsonProperty("medium")] - public string Medium { get; set; } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Data/Web/Response/WebApiUserDetailResponse.cs b/src/Pixeval/Data/Web/Response/WebApiUserDetailResponse.cs deleted file mode 100644 index b7c771d4..00000000 --- a/src/Pixeval/Data/Web/Response/WebApiUserDetailResponse.cs +++ /dev/null @@ -1,54 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using Newtonsoft.Json; - -namespace Pixeval.Data.Web.Response -{ - public class WebApiUserDetailResponse - { - [JsonProperty("body")] - public Body ResponseBody { get; set; } - - public class Body - { - [JsonProperty("user_details")] - public UserDetails UserDetails { get; set; } - } - - public class UserDetails - { - [JsonProperty("cover_image")] - public CoverImage CoverImage { get; set; } - } - - public class CoverImage - { - [JsonProperty("profile_cover_image")] - public ProfileCoverImage ProfileCoverImage { get; set; } - } - - public class ProfileCoverImage - { - [JsonProperty("720x360")] - public string The720X360 { get; set; } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/FodyWeavers.xml b/src/Pixeval/FodyWeavers.xml deleted file mode 100644 index d5abfed8..00000000 --- a/src/Pixeval/FodyWeavers.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/src/Pixeval/FodyWeavers.xsd b/src/Pixeval/FodyWeavers.xsd deleted file mode 100644 index 221aeb8a..00000000 --- a/src/Pixeval/FodyWeavers.xsd +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - Used to control if the On_PropertyName_Changed feature is enabled. - - - - - Used to change the name of the method that fires the notify event. This is a string that accepts multiple values in a comma separated form. - - - - - Used to control if equality checks should be inserted. If false, equality checking will be disabled for the project. - - - - - Used to control if equality checks should use the Equals method resolved from the base class. - - - - - Used to control if equality checks should use the static Equals method resolved from the base class. - - - - - Used to turn off build warnings from this weaver. - - - - - Used to turn off build warnings about mismatched On_PropertyName_Changed methods. - - - - - - - - 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. - - - - - A comma-separated list of error codes that can be safely ignored in assembly verification. - - - - - 'false' to turn off automatic generation of the XML Schema file. - - - - - \ No newline at end of file diff --git a/src/Pixeval/Objects/Caching/CachingPolicy.cs b/src/Pixeval/Objects/Caching/CachingPolicy.cs deleted file mode 100644 index 61a724ad..00000000 --- a/src/Pixeval/Objects/Caching/CachingPolicy.cs +++ /dev/null @@ -1,27 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -namespace Pixeval.Objects.Caching -{ - public enum CachingPolicy - { - Memory, File - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/Caching/FileCache.cs b/src/Pixeval/Objects/Caching/FileCache.cs deleted file mode 100644 index 5764502f..00000000 --- a/src/Pixeval/Objects/Caching/FileCache.cs +++ /dev/null @@ -1,112 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace Pixeval.Objects.Caching -{ - public class FileCache : IWeakCacheProvider, IEnumerable> where T : class - { - private readonly Func _cachingPolicy; - private readonly ConcurrentDictionary _fileMapping = new ConcurrentDictionary(); - private readonly string _initDirectory; - private readonly Func _restorePolicy; - - public FileCache(string initDirectory, Func cachingPolicy, Func restorePolicy) - { - _cachingPolicy = cachingPolicy; - _restorePolicy = restorePolicy; - _initDirectory = initDirectory; - - Directory.CreateDirectory(initDirectory); - } - - public IEnumerator> GetEnumerator() - { - return _fileMapping.GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - public void Attach(ref T key, THash associateWith) - { - if (associateWith == null || key == null) return; - var path = Path.Combine(_initDirectory, IWeakCacheProvider.HashKey(associateWith) + ".tmp"); - if (!File.Exists(path)) - { - var s = _cachingPolicy(key); - key = null; - Task.Run(() => - { - _fileMapping.TryAdd(associateWith, path); - WriteFile(path, s); - }); - } - } - - public void Detach(THash associateWith) - { - using var sem = new SemaphoreSlim(1); - var path = Path.Combine(_initDirectory, IWeakCacheProvider.HashKey(associateWith) + "."); - if (File.Exists(path)) - { - _fileMapping.TryRemove(associateWith, out _); - File.Delete(path); - } - } - - public async Task<(bool, T)> TryGet([NotNull] - THash key) - { - if (_fileMapping.TryGetValue(key, out var file) && File.Exists(file)) - { - await using var fileStream = File.OpenRead(file); - fileStream.Position = 0L; - await using Stream memoStream = new MemoryStream(); - await fileStream.CopyToAsync(memoStream); - return (true, _restorePolicy(memoStream)); - } - - return (false, null); - } - - public void Clear() - { - using var sem = new SemaphoreSlim(1); - foreach (var file in Directory.GetFiles(_initDirectory)) File.Delete(file); - } - - private static async void WriteFile(string path, Stream src) - { - await using var fileStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None); - src.Position = 0L; - await src.CopyToAsync(fileStream); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/Caching/IWeakCacheProvider.cs b/src/Pixeval/Objects/Caching/IWeakCacheProvider.cs deleted file mode 100644 index 7b6ac036..00000000 --- a/src/Pixeval/Objects/Caching/IWeakCacheProvider.cs +++ /dev/null @@ -1,40 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Threading.Tasks; - -namespace Pixeval.Objects.Caching -{ - public interface IWeakCacheProvider where T : class - { - void Attach(ref T key, THash associateWith); - - void Detach(THash associateWith); - - Task<(bool, T)> TryGet(THash key); - - void Clear(); - - protected static int HashKey(THash key) - { - return key == null ? 0 : key.GetHashCode(); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/Caching/MemoryCache.cs b/src/Pixeval/Objects/Caching/MemoryCache.cs deleted file mode 100644 index 768f8078..00000000 --- a/src/Pixeval/Objects/Caching/MemoryCache.cs +++ /dev/null @@ -1,71 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Collections; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace Pixeval.Objects.Caching -{ - public class MemoryCache : IWeakCacheProvider, IEnumerable>> where T : class - { - public static readonly MemoryCache Shared = new MemoryCache(); - - private readonly ConcurrentDictionary> _cache = new ConcurrentDictionary>(); - - public IEnumerator>> GetEnumerator() - { - return _cache.GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - public void Attach(ref T key, THash associateWith) - { - if (associateWith == null || key == null) return; - var weakRef = new WeakEntry(key); - key = null; - _cache.TryAdd(IWeakCacheProvider.HashKey(associateWith), weakRef); - } - - public void Detach(THash associateWith) - { - _cache.TryRemove(IWeakCacheProvider.HashKey(associateWith), out _); - } - - public Task<(bool, T)> TryGet([NotNull] - THash key) - { - return _cache.TryGetValue(IWeakCacheProvider.HashKey(key), out var weakRef) && weakRef.Target is { } target ? Task.FromResult((true, target)) : Task.FromResult((false, (T) null)); - } - - public void Clear() - { - lock (_cache) - { - _cache.Clear(); - } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/Caching/WeakEntry.cs b/src/Pixeval/Objects/Caching/WeakEntry.cs deleted file mode 100644 index 8d9b662a..00000000 --- a/src/Pixeval/Objects/Caching/WeakEntry.cs +++ /dev/null @@ -1,71 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Runtime.InteropServices; - -#nullable enable - -namespace Pixeval.Objects.Caching -{ - public class WeakEntry : IEquatable>, IDisposable where T : class - { - private readonly int _hashCode; - - private GCHandle _gcHandle; - - public WeakEntry(T target) - { - _hashCode = target.GetHashCode(); - _gcHandle = GCHandle.Alloc(target, GCHandleType.Weak); - } - - public bool IsAlive => _gcHandle.Target != null; - - public T? Target => _gcHandle.Target as T; - - public void Dispose() - { - _gcHandle.Free(); - GC.SuppressFinalize(this); - } - - public bool Equals(WeakEntry? other) - { - return other != null && ReferenceEquals(other.Target, Target); - } - - ~WeakEntry() - { - Dispose(); - } - - public override bool Equals(object? obj) - { - if (obj is WeakEntry weakEntry) return Equals(weakEntry); - return false; - } - - public override int GetHashCode() - { - return _hashCode; - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/Exceptions/AttributeNotFoundException.cs b/src/Pixeval/Objects/Exceptions/AttributeNotFoundException.cs deleted file mode 100644 index 49c434cb..00000000 --- a/src/Pixeval/Objects/Exceptions/AttributeNotFoundException.cs +++ /dev/null @@ -1,44 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Runtime.Serialization; - -namespace Pixeval.Objects.Exceptions -{ - public class AttributeNotFoundException : Exception - { - public AttributeNotFoundException() - { - } - - protected AttributeNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) - { - } - - public AttributeNotFoundException(string message) : base(message) - { - } - - public AttributeNotFoundException(string message, Exception innerException) : base(message, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/Exceptions/AuthenticateFailedException.cs b/src/Pixeval/Objects/Exceptions/AuthenticateFailedException.cs deleted file mode 100644 index 3f25448b..00000000 --- a/src/Pixeval/Objects/Exceptions/AuthenticateFailedException.cs +++ /dev/null @@ -1,44 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Runtime.Serialization; - -namespace Pixeval.Objects.Exceptions -{ - public class AuthenticateFailedException : Exception - { - public AuthenticateFailedException() - { - } - - protected AuthenticateFailedException(SerializationInfo info, StreamingContext context) : base(info, context) - { - } - - public AuthenticateFailedException(string message) : base(message) - { - } - - public AuthenticateFailedException(string message, Exception innerException) : base(message, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/Exceptions/Logger/ExceptionDumper.cs b/src/Pixeval/Objects/Exceptions/Logger/ExceptionDumper.cs deleted file mode 100644 index 488f949b..00000000 --- a/src/Pixeval/Objects/Exceptions/Logger/ExceptionDumper.cs +++ /dev/null @@ -1,137 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading; -using Microsoft.Win32; -using Pixeval.Objects.Primitive; -using Refit; - -namespace Pixeval.Objects.Exceptions.Logger -{ - [StructLayout(LayoutKind.Sequential)] - public struct MemoryStatusEx - { - public uint dwLength; - public uint dwMemoryLoad; - public ulong ullTotalPhys; - public ulong ullAvailPhys; - public ulong ullTotalPageFile; - public ulong ullAvailPageFile; - public ulong ullTotalVirtual; - public ulong ullAvailVirtual; - public ulong ullAvailExtendedVirtual; - } - - - public class ExceptionDumper - { - public static async void WriteException(Exception e) - { - using var semaphore = new SemaphoreSlim(1); - await semaphore.WaitAsync(TimeSpan.FromSeconds(5)); - - var exceptionMessage = e is ApiException exception ? exception.Content + Environment.NewLine + exception : e.ToString(); - var sb = new StringBuilder(); - sb.AppendLine(@"Pixeval - A Strong, Fast and Flexible Pixiv Client"); - sb.AppendLine(@"Copyright (C) 2019-2020 Dylech30th"); - sb.AppendLine(); - sb.AppendLine(@"We have encountered an unrecoverable problem. A dump file with error snapshot has been created."); - sb.AppendLine(@"In order to help with diagnosis and debug, Pixeval will collect some information contains: "); - sb.AppendLine(@" ¡¤ Computer Architecture"); - sb.AppendLine(@" ¡¤ Operating System"); - sb.AppendLine(@" ¡¤ Event Log"); - sb.AppendLine(@" ¡¤ Exception Message"); - sb.AppendLine(); - sb.AppendLine(@"Begin Dump Information"); - sb.AppendLine($" Pixeval Version: {AppContext.CurrentVersion}"); - sb.AppendLine($" Creation: {DateTime.Now}"); - sb.AppendLine(@"End Dump Information"); - sb.AppendLine(); - sb.AppendLine(@"Begin Debugging Information Collection"); - sb.AppendLine(@" Begin Computer Architecture"); - sb.AppendLine($" CPU Architecture: {Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE")}"); - sb.AppendLine($" Is 64-bit Platform: {Environment.Is64BitOperatingSystem}"); - sb.AppendLine($" Is 64-bit Process: {Environment.Is64BitProcess}"); - sb.AppendLine($" Total Installed RAM: {GetTotalInstalledMemory()} GB"); - sb.AppendLine($" Total Available RAM: {GetAvailableMemory()} MB"); - sb.AppendLine(@" End Computer Architecture"); - sb.AppendLine(); - sb.AppendLine(@" Begin Operating System"); - sb.AppendLine($" OS Version String: {Environment.OSVersion.VersionString}"); - sb.AppendLine($" OS Version {Environment.OSVersion.Version}"); - sb.AppendLine($" Service Pack Version: {(Environment.OSVersion.ServicePack.IsNullOrEmpty() ? "Not Installed" : "Environment.OSVersion.ServicePack")}"); - sb.AppendLine($" Visual C++ Redistributable Version: {GetCppRedistributableVersion()}"); - sb.AppendLine(@" End Operating System"); - sb.AppendLine(); - sb.AppendLine(@" Begin Exception Log"); - sb.AppendLine(@" Exception: "); - sb.AppendLine(FormatMultilineData(exceptionMessage, 3)); - sb.AppendLine(" End Exception Log"); - sb.AppendLine(@"End Debugging Information Collection"); - try - { - await File.WriteAllTextAsync(Path.Combine(AppContext.ExceptionReportFolder, $"{DateTime.Now.ToString(CultureInfo.InvariantCulture)}.txt".Replace("/", "-").Replace(":", "-")), sb.ToString()); - } - catch - { - // ignore - } - } - - private static string FormatMultilineData(string data, int indent) - { - var indentation = new string(' ', indent * 4); - return data.Split('\n').Select(s => indentation + s).Join('\n'); - } - - private static string GetCppRedistributableVersion() - { - using var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Wow6432Node\Microsoft\VisualStudio\14.0\VC\Runtimes\x64"); - return key == null ? "Not Installed" : key.GetValue("Bld").ToString(); - } - - private static ulong GetTotalInstalledMemory() - { - return GetMemoryStatusExInternal().ullTotalPhys / 1024 / 1024 / 1024; - } - - private static ulong GetAvailableMemory() - { - return GetMemoryStatusExInternal().ullAvailPhys / 1024 / 1024; - } - - private static MemoryStatusEx GetMemoryStatusExInternal() - { - var memInfo = new MemoryStatusEx {dwLength = 64}; - //此方法为手动Hack,按照填充规则计算大小,祝我好运 - _ = GlobalMemoryStatusEx(ref memInfo); //实践证明,必须有人接收返回值,否则会报错 - return memInfo; - } - - [DllImport("kernel32.dll", EntryPoint = "GlobalMemoryStatusEx", CallingConvention = CallingConvention.StdCall)] //此处一定要用Ex,否则内存计算不全 - private static extern int GlobalMemoryStatusEx(ref MemoryStatusEx lpBuffer); - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/Exceptions/QueryNotRespondingException.cs b/src/Pixeval/Objects/Exceptions/QueryNotRespondingException.cs deleted file mode 100644 index f97e0840..00000000 --- a/src/Pixeval/Objects/Exceptions/QueryNotRespondingException.cs +++ /dev/null @@ -1,44 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Runtime.Serialization; - -namespace Pixeval.Objects.Exceptions -{ - public class QueryNotRespondingException : Exception - { - public QueryNotRespondingException() - { - } - - protected QueryNotRespondingException(SerializationInfo info, StreamingContext context) : base(info, context) - { - } - - public QueryNotRespondingException(string message) : base(message) - { - } - - public QueryNotRespondingException(string message, Exception innerException) : base(message, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/Exceptions/TokenNotFoundException.cs b/src/Pixeval/Objects/Exceptions/TokenNotFoundException.cs deleted file mode 100644 index 2db98d8d..00000000 --- a/src/Pixeval/Objects/Exceptions/TokenNotFoundException.cs +++ /dev/null @@ -1,44 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Runtime.Serialization; - -namespace Pixeval.Objects.Exceptions -{ - public class TokenNotFoundException : Exception - { - public TokenNotFoundException() - { - } - - protected TokenNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) - { - } - - public TokenNotFoundException(string message) : base(message) - { - } - - public TokenNotFoundException(string message, Exception innerException) : base(message, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/Exceptions/TypeMismatchException.cs b/src/Pixeval/Objects/Exceptions/TypeMismatchException.cs deleted file mode 100644 index cb2e7741..00000000 --- a/src/Pixeval/Objects/Exceptions/TypeMismatchException.cs +++ /dev/null @@ -1,44 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Runtime.Serialization; - -namespace Pixeval.Objects.Exceptions -{ - public class TypeMismatchException : Exception - { - public TypeMismatchException() - { - } - - protected TypeMismatchException(SerializationInfo info, StreamingContext context) : base(info, context) - { - } - - public TypeMismatchException(string message) : base(message) - { - } - - public TypeMismatchException(string message, Exception innerException) : base(message, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/Generic/Enumerates.cs b/src/Pixeval/Objects/Generic/Enumerates.cs deleted file mode 100644 index 575d4400..00000000 --- a/src/Pixeval/Objects/Generic/Enumerates.cs +++ /dev/null @@ -1,78 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using Pixeval.Objects.Primitive; - -namespace Pixeval.Objects.Generic -{ - public static class Enumerates - { - public static bool IsNullOrEmpty(this IEnumerable enumerable) - { - return enumerable == null || !enumerable.Any(); - } - - public static void AddRange(this ICollection dst, IEnumerable src) - { - foreach (var t in src) dst.Add(t); - } - - public static void AddSorted(this IList list, T item, IComparer comparer) - { - if (comparer == null) - { - list.Add(item); - return; - } - - var i = 0; - while (i < list.Count && comparer.Compare(list[i], item) < 0) i++; - - list.Insert(i, item); - } - - public static IImmutableSet ToImmutableSet(this IEnumerable enumerable, Func function) - { - return enumerable == null ? new HashSet().ToImmutableHashSet() : enumerable.Select(function).ToImmutableHashSet(); - } - - public static bool EqualsIgnoreCase(this IEnumerable src, IEnumerable compare) - { - return src.All(x => Strings.IsNullOrEmpty(x) && compare.Any(i => i.EqualsIgnoreCase(x))); - } - - public static IEnumerable Peek(this IEnumerable enumerable, Action action) - { - var peek = enumerable as T[] ?? enumerable.ToArray(); - foreach (var t in peek) action(t); - - return peek; - } - - public static IEnumerable NonNull(this IEnumerable source) - { - return source.Where(s => s != null); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/Generic/Functions.cs b/src/Pixeval/Objects/Generic/Functions.cs deleted file mode 100644 index b975be0e..00000000 --- a/src/Pixeval/Objects/Generic/Functions.cs +++ /dev/null @@ -1,47 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Threading.Tasks; - -namespace Pixeval.Objects.Generic -{ - public static class Functions - { - public static T Apply(this T receiver, Action action) - { - action(receiver); - return receiver; - } - - public static Task AwaitAsync(this T obj, Func> on, int interval = 0, TimeSpan timeout = default) - { - var timer = DateTime.Now; - return Task.Run(async () => - { - while (!await on(obj)) - { - if (timeout != default && DateTime.Now - timer >= timeout) break; - if (interval != 0) await Task.Delay(interval); - } - }); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/Generic/Observable.cs b/src/Pixeval/Objects/Generic/Observable.cs deleted file mode 100644 index 7d833e9e..00000000 --- a/src/Pixeval/Objects/Generic/Observable.cs +++ /dev/null @@ -1,64 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using PropertyChanged; - -namespace Pixeval.Objects.Generic -{ - [AddINotifyPropertyChangedInterface] - public class Observable - { - private T _value; - - public Observable(T value) - { - _value = value; - } - - public T Value - { - get => _value; - set - { - if (!_value.Equals(value)) - { - ValueChanged?.Invoke(Value, new ObservableValueChangedEventArgs(_value, value)); - _value = value; - } - } - } - - public event EventHandler> ValueChanged; - } - - public class ObservableValueChangedEventArgs : EventArgs - { - public ObservableValueChangedEventArgs(T oldValue, T newValue) - { - OldValue = oldValue; - NewValue = newValue; - } - - public T OldValue { get; set; } - - public T NewValue { get; set; } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/Generic/Tasks.cs b/src/Pixeval/Objects/Generic/Tasks.cs deleted file mode 100644 index 50f7775d..00000000 --- a/src/Pixeval/Objects/Generic/Tasks.cs +++ /dev/null @@ -1,66 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Pixeval.Objects.Generic -{ - public class Tasks - { - private Func> _mappingFunc; - private IEnumerable _taskQueue; - - private Tasks() - { - } - - public static Tasks Of(IEnumerable tasks) - { - return new Tasks {_taskQueue = tasks.NonNull()}; - } - - public Tasks Mapping(Func> map) - { - _mappingFunc = map; - return this; - } - - public IEnumerable> Construct() - { - return _taskQueue.Select(taskObj => _mappingFunc(taskObj)); - } - } - - public static class TaskHelper - { - public static Task WhenAll(this IEnumerable> tasks) - { - return Task.WhenAll(tasks); - } - - public static Task> WhenAny(this IEnumerable> tasks) - { - return Task.WhenAny(tasks); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/I18n/ResourceLocator.cs b/src/Pixeval/Objects/I18n/ResourceLocator.cs deleted file mode 100644 index 6c0c4847..00000000 --- a/src/Pixeval/Objects/I18n/ResourceLocator.cs +++ /dev/null @@ -1,93 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Windows; -using System.Windows.Resources; -using System.Xml; -using Pixeval.Data.ViewModel; -using Pixeval.Objects.Primitive; -using Pixeval.Persisting; - -namespace Pixeval.Objects.I18n -{ - public static partial class AkaI18N - { - private static IEnumerable _i18NXmlNodes; - - public static string GetResource(string key) - { - if (_i18NXmlNodes == null) - { - // we load settings here because we need to get the culture field - if (File.Exists(Path.Combine(AppContext.SettingsFolder, "settings.json"))) - { - var s = File.ReadAllText(Path.Combine(AppContext.SettingsFolder, "settings.json")).FromJson(); - InitializeXmlNodes(s.Culture); - } - else - { - InitializeXmlNodes(CultureInfo.CurrentCulture.Name); - } - } - - return GetValueByKey(key); - } - - public static void Reload(I18NOption option) - { - InitializeXmlNodes(option.Name); - foreach (var prop in typeof(AkaI18N).GetProperties(BindingFlags.Public | BindingFlags.Static)) prop.SetValue(null, GetValueByKey(prop.Name)); - } - - private static void InitializeXmlNodes(string culture) - { - var fileName = new Uri($"pack://application:,,,/Pixeval;component/Objects/I18n/Xml/resx_{culture.ToLower()}.xml"); - StreamResourceInfo streamResourceInfo; - try - { - streamResourceInfo = Application.GetResourceStream(fileName); - } - catch (IOException) - { - streamResourceInfo = Application.GetResourceStream(new Uri("pack://application:,,,/Pixeval;component/Objects/I18n/Xml/resx_zh-cn.xml")); - } - - var xml = new XmlDocument(); - xml.Load(streamResourceInfo?.Stream); - _i18NXmlNodes = xml.SelectSingleNode("/localization").ChildNodes.Cast(); - } - - public static string GetCultureAcceptLanguage() - { - return CultureInfo.CurrentCulture.Name.ToLower(); - } - - private static string GetValueByKey(string key) - { - return _i18NXmlNodes.First(p => p.Attributes["key"].Value == key).Attributes["value"].Value; - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/I18n/StringResources.cs b/src/Pixeval/Objects/I18n/StringResources.cs deleted file mode 100644 index 8c37ccc4..00000000 --- a/src/Pixeval/Objects/I18n/StringResources.cs +++ /dev/null @@ -1,1788 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.ComponentModel; -using System.Runtime.CompilerServices; - -namespace Pixeval.Objects.I18n -{ - public static partial class AkaI18N - { - public static string emptyEmailOrPasswordIsNotAllowed = GetResource(nameof(EmptyEmailOrPasswordIsNotAllowed)); - - public static string idDoNotExists = GetResource(nameof(IdDoNotExists)); - - public static string cannotFindUser = GetResource(nameof(CannotFindUser)); - - public static string inputIsEmpty = GetResource(nameof(InputIsEmpty)); - - public static string queryNotResponding = GetResource(nameof(QueryNotResponding)); - - public static string idIllegal = GetResource(nameof(IdIllegal)); - - public static string userIdIllegal = GetResource(nameof(UserIdIllegal)); - - public static string appApiAuthenticateTimeout = GetResource(nameof(AppApiAuthenticateTimeout)); - - public static string webApiAuthenticateTimeout = GetResource(nameof(WebApiAuthenticateTimeout)); - - public static string multiplePixevalInstanceDetected = GetResource(nameof(MultiplePixevalInstanceDetected)); - - public static string multiplePixevalInstanceDetectedTitle = GetResource(nameof(MultiplePixevalInstanceDetectedTitle)); - - public static string cppRedistributableRequired = GetResource(nameof(CppRedistributableRequired)); - - public static string cppRedistributableRequiredTitle = GetResource(nameof(CppRedistributableRequiredTitle)); - - public static string certificateInstallationIsRequired = GetResource(nameof(CertificateInstallationIsRequired)); - - public static string certificateInstallationIsRequiredTitle = GetResource(nameof(CertificateInstallationIsRequiredTitle)); - - public static string trendsAddIllust = GetResource(nameof(TrendsAddIllust)); - - public static string trendsAddBookmark = GetResource(nameof(TrendsAddBookmark)); - - public static string trendsAddFavorite = GetResource(nameof(TrendsAddFavorite)); - - public static string searchingTrends = GetResource(nameof(SearchingTrends)); - - public static string searchingUserUpdates = GetResource(nameof(SearchingUserUpdates)); - - public static string searchingGallery = GetResource(nameof(SearchingGallery)); - - public static string searchingRecommend = GetResource(nameof(SearchingRecommend)); - - public static string searchingFollower = GetResource(nameof(SearchingFollower)); - - public static string searchingSpotlight = GetResource(nameof(SearchingSpotlight)); - - public static string queuedDownload = GetResource(nameof(QueuedDownload)); - - public static string queuedAllToDownload = GetResource(nameof(QueuedAllToDownload)); - - public static string shareLinkCopiedToClipboard = GetResource(nameof(ShareLinkCopiedToClipboard)); - - public static string pathNotExist = GetResource(nameof(PathNotExist)); - - public static string sauceNaoFileCountLimit = GetResource(nameof(SauceNaoFileCountLimit)); - - public static string cannotFindResult = GetResource(nameof(CannotFindResult)); - - public static string pleaseSelectFile = GetResource(nameof(PleaseSelectFile)); - - public static string pleaseSelectLocation = GetResource(nameof(PleaseSelectLocation)); - - public static string cannotRetrieveContentLengthHeader = GetResource(nameof(CannotRetrieveContentLengthHeader)); - - public static string toggleR18OnSuccess = GetResource(nameof(ToggleR18OnSuccess)); - - public static string toggleR18OnFailed = GetResource(nameof(ToggleR18OnFailed)); - - public static string tryingToToggleR18Switch = GetResource(nameof(TryingToToggleR18Switch)); - - public static string rankOptionDay = GetResource(nameof(RankOptionDay)); - - public static string rankOptionWeek = GetResource(nameof(RankOptionWeek)); - - public static string rankOptionMonth = GetResource(nameof(RankOptionMonth)); - - public static string rankOptionDayMale = GetResource(nameof(RankOptionDayMale)); - - public static string rankOptionDayFemale = GetResource(nameof(RankOptionDayFemale)); - - public static string rankOptionDayManga = GetResource(nameof(RankOptionDayManga)); - - public static string rankOptionWeekManga = GetResource(nameof(RankOptionWeekManga)); - - public static string rankOptionWeekOriginal = GetResource(nameof(RankOptionWeekOriginal)); - - public static string rankOptionWeekRookie = GetResource(nameof(RankOptionWeekRookie)); - - public static string rankOptionDayR18 = GetResource(nameof(RankOptionDayR18)); - - public static string rankOptionDayMaleR18 = GetResource(nameof(RankOptionDayMaleR18)); - - public static string rankOptionDayFemaleR18 = GetResource(nameof(RankOptionDayFemaleR18)); - - public static string rankOptionWeekR18 = GetResource(nameof(RankOptionWeekR18)); - - public static string rankOptionWeekR18G = GetResource(nameof(RankOptionWeekR18G)); - - public static string rankDateCannotBeNull = GetResource(nameof(RankDateCannotBeNull)); - - public static string rankNeedR18On = GetResource(nameof(RankNeedR18On)); - - public static string cannotFindSpecifiedCertificate = GetResource(nameof(CannotFindSpecifiedCertificate)); - - public static string gifIllustrationHint = GetResource(nameof(GifIllustrationHint)); - - public static string mangaIllustrationHintFormat = GetResource(nameof(MangaIllustrationHintFormat)); - - public static string userIdHintFormat = GetResource(nameof(UserIdHintFormat)); - - public static string downloadSingleIllustration = GetResource(nameof(DownloadSingleIllustration)); - - public static string downloadAllInCurrentList = GetResource(nameof(DownloadAllInCurrentList)); - - public static string downloadSpotlight = GetResource(nameof(DownloadSpotlight)); - - public static string retractSidebar = GetResource(nameof(RetractSidebar)); - - public static string restrictPolicy = GetResource(nameof(RestrictPolicy)); - - public static string _private = GetResource(nameof(Private)); - - public static string _public = GetResource(nameof(Public)); - - public static string homePage = GetResource(nameof(HomePage)); - - public static string myGallery = GetResource(nameof(MyGallery)); - - public static string myFollowing = GetResource(nameof(MyFollowing)); - - public static string spotlight = GetResource(nameof(Spotlight)); - - public static string recommend = GetResource(nameof(Recommend)); - - public static string illustRanking = GetResource(nameof(IllustRanking)); - - public static string userTrend = GetResource(nameof(UserTrend)); - - public static string userUpdate = GetResource(nameof(UserUpdate)); - - public static string searchImageBySource = GetResource(nameof(SearchImageBySource)); - - public static string downloadQueueAndHistory = GetResource(nameof(DownloadQueueAndHistory)); - - public static string setting = GetResource(nameof(Setting)); - - public static string logout = GetResource(nameof(Logout)); - - public static string searchHint = GetResource(nameof(SearchHint)); - - public static string queryUser = GetResource(nameof(QueryUser)); - - public static string querySingleUser = GetResource(nameof(QuerySingleUser)); - - public static string querySingleIllust = GetResource(nameof(QuerySingleIllust)); - - public static string recommendIllustratorTurnPage = GetResource(nameof(RecommendIllustratorTurnPage)); - - public static string pixevalVersionFormat = GetResource(nameof(PixevalVersionFormat)); - - public static string aboutPixeval = GetResource(nameof(AboutPixeval)); - - public static string userBrowserFollowCountHint = GetResource(nameof(UserBrowserFollowCountHint)); - - public static string userBrowserFollow = GetResource(nameof(UserBrowserFollow)); - - public static string userBrowserUnFollow = GetResource(nameof(UserBrowserUnFollow)); - - public static string userBrowserPrivateFollow = GetResource(nameof(UserBrowserPrivateFollow)); - - public static string userBrowserIllustSelector = GetResource(nameof(UserBrowserIllustSelector)); - - public static string userBrowserGallerySelector = GetResource(nameof(UserBrowserGallerySelector)); - - public static string illustBrowserIllustId = GetResource(nameof(IllustBrowserIllustId)); - - public static string illustBrowserTotalViews = GetResource(nameof(IllustBrowserTotalViews)); - - public static string illustBrowserTotalBookmarks = GetResource(nameof(IllustBrowserTotalBookmarks)); - - public static string illustBrowserResolution = GetResource(nameof(IllustBrowserResolution)); - - public static string illustBrowserUploadDate = GetResource(nameof(IllustBrowserUploadDate)); - - public static string illustBrowserIllustTag = GetResource(nameof(IllustBrowserIllustTag)); - - public static string illustBrowserSetWallpaper = GetResource(nameof(IllustBrowserSetWallpaper)); - - public static string illustBrowserShareLink = GetResource(nameof(IllustBrowserShareLink)); - - public static string illustBrowserViewInBrowser = GetResource(nameof(IllustBrowserViewInBrowser)); - - public static string illustBrowserDownload = GetResource(nameof(IllustBrowserDownload)); - - public static string illustBrowserPrivateBookmark = GetResource(nameof(IllustBrowserPrivateBookmark)); - - public static string illustBrowserBookmark = GetResource(nameof(IllustBrowserBookmark)); - - public static string illustBrowserRemoveBookmark = GetResource(nameof(IllustBrowserRemoveBookmark)); - - public static string downloadQueueShowDownloadIllust = GetResource(nameof(DownloadQueueShowDownloadIllust)); - - public static string downloadQueueRemoveFromDownloading = GetResource(nameof(DownloadQueueRemoveFromDownloading)); - - public static string downloadQueueDownloading = GetResource(nameof(DownloadQueueDownloading)); - - public static string downloadQueueEmptyNotifier = GetResource(nameof(DownloadQueueEmptyNotifier)); - - public static string downloadQueueDownloaded = GetResource(nameof(DownloadQueueDownloaded)); - - public static string emailOrPasswordIsWrong = GetResource(nameof(EmailOrPasswordIsWrong)); - - public static string copy = GetResource(nameof(Copy)); - - public static string conditionBoxHint = GetResource(nameof(ConditionBoxHint)); - - public static string pixevalSettings = GetResource(nameof(PixevalSettings)); - - public static string sortByPopulation = GetResource(nameof(SortByPopulation)); - - public static string turnOffR18 = GetResource(nameof(TurnOffR18)); - - public static string turnOnIllustratorRecommend = GetResource(nameof(TurnOnIllustratorRecommend)); - - public static string turnOnDirectConnect = GetResource(nameof(TurnOnDirectConnect)); - - public static string tagMatchOption = GetResource(nameof(TagMatchOption)); - - public static string turnOnCache = GetResource(nameof(TurnOnCache)); - - public static string memoryCachePolicy = GetResource(nameof(MemoryCachePolicy)); - - public static string fileCachePolicy = GetResource(nameof(FileCachePolicy)); - - public static string minBookmarkRequired = GetResource(nameof(MinBookmarkRequired)); - - public static string searchPageCountHint = GetResource(nameof(SearchPageCountHint)); - - public static string searchPageStart = GetResource(nameof(SearchPageStart)); - - public static string spotlightSearchPageStart = GetResource(nameof(SpotlightSearchPageStart)); - - public static string downloadLocation = GetResource(nameof(DownloadLocation)); - - public static string tagsToBeExclude = GetResource(nameof(TagsToBeExclude)); - - public static string tagsToBeInclude = GetResource(nameof(TagsToBeInclude)); - - public static string searchPerPageCountHint = GetResource(nameof(SearchPerPageCountHint)); - - public static string turnOnWebR18 = GetResource(nameof(TurnOnWebR18)); - - public static string sauceNaoFileLocationHint = GetResource(nameof(SauceNaoFileLocationHint)); - - public static string sauceNaoUploadAndSearch = GetResource(nameof(SauceNaoUploadAndSearch)); - - public static string signIn = GetResource(nameof(SignIn)); - - public static string signInAccount = GetResource(nameof(SignInAccount)); - - public static string signInPassword = GetResource(nameof(SignInPassword)); - - public static string signInButtonText = GetResource(nameof(SignInButtonText)); - - public static string signInUpdatingSession = GetResource(nameof(SignInUpdatingSession)); - - public static string browsingHistoryCount = GetResource(nameof(BrowsingHistoryCount)); - - public static string downloadQueueBrowsingHistory = GetResource(nameof(DownloadQueueBrowsingHistory)); - - public static string downloadQueueHistoryListIsEmpty = GetResource(nameof(DownloadQueueHistoryListIsEmpty)); - - public static string pixevalUpdateAvailable = GetResource(nameof(PixevalUpdateAvailable)); - - public static string pixevalUpdateAvailableTitle = GetResource(nameof(PixevalUpdateAvailableTitle)); - - public static string thisLoginSessionRequiresRecaptcha = GetResource(nameof(ThisLoginSessionRequiresRecaptcha)); - - public static string supportMe = GetResource(nameof(SupportMe)); - - public static string downloadTo = GetResource(nameof(DownloadTo)); - - public static string userPreviewPopupFollow = GetResource(nameof(UserPreviewPopupFollow)); - - public static string userPreviewPopupUnFollow = GetResource(nameof(UserPreviewPopupUnFollow)); - - public static string selectCultureInfo = GetResource(nameof(SelectCultureInfo)); - - public static string createNewFolderWhenDownloadFromUser = GetResource(nameof(CreateNewFolderWhenDownloadFromUser)); - - public static string EmptyEmailOrPasswordIsNotAllowed - { - get => emptyEmailOrPasswordIsNotAllowed; - set - { - emptyEmailOrPasswordIsNotAllowed = value; - OnStaticPropertyChanged(); - } - } - - public static string IdDoNotExists - { - get => idDoNotExists; - set - { - idDoNotExists = value; - OnStaticPropertyChanged(); - } - } - - public static string CannotFindUser - { - get => cannotFindUser; - set - { - cannotFindUser = value; - OnStaticPropertyChanged(); - } - } - - public static string InputIsEmpty - { - get => inputIsEmpty; - set - { - inputIsEmpty = value; - OnStaticPropertyChanged(); - } - } - - public static string QueryNotResponding - { - get => queryNotResponding; - set - { - queryNotResponding = value; - OnStaticPropertyChanged(); - } - } - - public static string IdIllegal - { - get => idIllegal; - set - { - idIllegal = value; - OnStaticPropertyChanged(); - } - } - - public static string UserIdIllegal - { - get => userIdIllegal; - set - { - userIdIllegal = value; - OnStaticPropertyChanged(); - } - } - - public static string AppApiAuthenticateTimeout - { - get => appApiAuthenticateTimeout; - set - { - appApiAuthenticateTimeout = value; - OnStaticPropertyChanged(); - } - } - - public static string WebApiAuthenticateTimeout - { - get => webApiAuthenticateTimeout; - set - { - webApiAuthenticateTimeout = value; - OnStaticPropertyChanged(); - } - } - - public static string MultiplePixevalInstanceDetected - { - get => multiplePixevalInstanceDetected; - set - { - multiplePixevalInstanceDetected = value; - OnStaticPropertyChanged(); - } - } - - public static string MultiplePixevalInstanceDetectedTitle - { - get => multiplePixevalInstanceDetectedTitle; - set - { - multiplePixevalInstanceDetectedTitle = value; - OnStaticPropertyChanged(); - } - } - - public static string CppRedistributableRequired - { - get => cppRedistributableRequired; - set - { - cppRedistributableRequired = value; - OnStaticPropertyChanged(); - } - } - - public static string CppRedistributableRequiredTitle - { - get => cppRedistributableRequiredTitle; - set - { - cppRedistributableRequiredTitle = value; - OnStaticPropertyChanged(); - } - } - - public static string CertificateInstallationIsRequired - { - get => certificateInstallationIsRequired; - set - { - certificateInstallationIsRequired = value; - OnStaticPropertyChanged(); - } - } - - public static string CertificateInstallationIsRequiredTitle - { - get => certificateInstallationIsRequiredTitle; - set - { - certificateInstallationIsRequiredTitle = value; - OnStaticPropertyChanged(); - } - } - - public static string TrendsAddIllust - { - get => trendsAddIllust; - set - { - trendsAddIllust = value; - OnStaticPropertyChanged(); - } - } - - public static string TrendsAddBookmark - { - get => trendsAddBookmark; - set - { - trendsAddBookmark = value; - OnStaticPropertyChanged(); - } - } - - public static string TrendsAddFavorite - { - get => trendsAddFavorite; - set - { - trendsAddFavorite = value; - OnStaticPropertyChanged(); - } - } - - public static string SearchingTrends - { - get => searchingTrends; - set - { - searchingTrends = value; - OnStaticPropertyChanged(); - } - } - - public static string SearchingUserUpdates - { - get => searchingUserUpdates; - set - { - searchingUserUpdates = value; - OnStaticPropertyChanged(); - } - } - - public static string SearchingGallery - { - get => searchingGallery; - set - { - searchingGallery = value; - OnStaticPropertyChanged(); - } - } - - public static string SearchingRecommend - { - get => searchingRecommend; - set - { - searchingRecommend = value; - OnStaticPropertyChanged(); - } - } - - public static string SearchingFollower - { - get => searchingFollower; - set - { - searchingFollower = value; - OnStaticPropertyChanged(); - } - } - - public static string SearchingSpotlight - { - get => searchingSpotlight; - set - { - searchingSpotlight = value; - OnStaticPropertyChanged(); - } - } - - public static string QueuedDownload - { - get => queuedDownload; - set - { - queuedDownload = value; - OnStaticPropertyChanged(); - } - } - - public static string QueuedAllToDownload - { - get => queuedAllToDownload; - set - { - queuedAllToDownload = value; - OnStaticPropertyChanged(); - } - } - - public static string ShareLinkCopiedToClipboard - { - get => shareLinkCopiedToClipboard; - set - { - shareLinkCopiedToClipboard = value; - OnStaticPropertyChanged(); - } - } - - public static string PathNotExist - { - get => pathNotExist; - set - { - pathNotExist = value; - OnStaticPropertyChanged(); - } - } - - public static string SauceNaoFileCountLimit - { - get => sauceNaoFileCountLimit; - set - { - sauceNaoFileCountLimit = value; - OnStaticPropertyChanged(); - } - } - - public static string CannotFindResult - { - get => cannotFindResult; - set - { - cannotFindResult = value; - OnStaticPropertyChanged(); - } - } - - public static string PleaseSelectFile - { - get => pleaseSelectFile; - set - { - pleaseSelectFile = value; - OnStaticPropertyChanged(); - } - } - - public static string PleaseSelectLocation - { - get => pleaseSelectLocation; - set - { - pleaseSelectLocation = value; - OnStaticPropertyChanged(); - } - } - - public static string CannotRetrieveContentLengthHeader - { - get => cannotRetrieveContentLengthHeader; - set - { - cannotRetrieveContentLengthHeader = value; - OnStaticPropertyChanged(); - } - } - - public static string ToggleR18OnSuccess - { - get => toggleR18OnSuccess; - set - { - toggleR18OnSuccess = value; - OnStaticPropertyChanged(); - } - } - - public static string ToggleR18OnFailed - { - get => toggleR18OnFailed; - set - { - toggleR18OnFailed = value; - OnStaticPropertyChanged(); - } - } - - public static string TryingToToggleR18Switch - { - get => tryingToToggleR18Switch; - set - { - tryingToToggleR18Switch = value; - OnStaticPropertyChanged(); - } - } - - public static string RankOptionDay - { - get => rankOptionDay; - set - { - rankOptionDay = value; - OnStaticPropertyChanged(); - } - } - - public static string RankOptionWeek - { - get => rankOptionWeek; - set - { - rankOptionWeek = value; - OnStaticPropertyChanged(); - } - } - - public static string RankOptionMonth - { - get => rankOptionMonth; - set - { - rankOptionMonth = value; - OnStaticPropertyChanged(); - } - } - - public static string RankOptionDayMale - { - get => rankOptionDayMale; - set - { - rankOptionDayMale = value; - OnStaticPropertyChanged(); - } - } - - public static string RankOptionDayFemale - { - get => rankOptionDayFemale; - set - { - rankOptionDayFemale = value; - OnStaticPropertyChanged(); - } - } - - public static string RankOptionDayManga - { - get => rankOptionDayManga; - set - { - rankOptionDayManga = value; - OnStaticPropertyChanged(); - } - } - - public static string RankOptionWeekManga - { - get => rankOptionWeekManga; - set - { - rankOptionWeekManga = value; - OnStaticPropertyChanged(); - } - } - - public static string RankOptionWeekOriginal - { - get => rankOptionWeekOriginal; - set - { - rankOptionWeekOriginal = value; - OnStaticPropertyChanged(); - } - } - - public static string RankOptionWeekRookie - { - get => rankOptionWeekRookie; - set - { - rankOptionWeekRookie = value; - OnStaticPropertyChanged(); - } - } - - public static string RankOptionDayR18 - { - get => rankOptionDayR18; - set - { - rankOptionDayR18 = value; - OnStaticPropertyChanged(); - } - } - - public static string RankOptionDayMaleR18 - { - get => rankOptionDayMaleR18; - set - { - rankOptionDayMaleR18 = value; - OnStaticPropertyChanged(); - } - } - - public static string RankOptionDayFemaleR18 - { - get => rankOptionDayFemaleR18; - set - { - rankOptionDayFemaleR18 = value; - OnStaticPropertyChanged(); - } - } - - public static string RankOptionWeekR18 - { - get => rankOptionWeekR18; - set - { - rankOptionWeekR18 = value; - OnStaticPropertyChanged(); - } - } - - public static string RankOptionWeekR18G - { - get => rankOptionWeekR18G; - set - { - rankOptionWeekR18G = value; - OnStaticPropertyChanged(); - } - } - - public static string RankDateCannotBeNull - { - get => rankDateCannotBeNull; - set - { - rankDateCannotBeNull = value; - OnStaticPropertyChanged(); - } - } - - public static string RankNeedR18On - { - get => rankNeedR18On; - set - { - rankNeedR18On = value; - OnStaticPropertyChanged(); - } - } - - public static string CannotFindSpecifiedCertificate - { - get => cannotFindSpecifiedCertificate; - set - { - cannotFindSpecifiedCertificate = value; - OnStaticPropertyChanged(); - } - } - - public static string GifIllustrationHint - { - get => gifIllustrationHint; - set - { - gifIllustrationHint = value; - OnStaticPropertyChanged(); - } - } - - public static string MangaIllustrationHintFormat - { - get => mangaIllustrationHintFormat; - set - { - mangaIllustrationHintFormat = value; - OnStaticPropertyChanged(); - } - } - - public static string UserIdHintFormat - { - get => userIdHintFormat; - set - { - userIdHintFormat = value; - OnStaticPropertyChanged(); - } - } - - public static string DownloadSingleIllustration - { - get => downloadSingleIllustration; - set - { - downloadSingleIllustration = value; - OnStaticPropertyChanged(); - } - } - - public static string DownloadAllInCurrentList - { - get => downloadAllInCurrentList; - set - { - downloadAllInCurrentList = value; - OnStaticPropertyChanged(); - } - } - - public static string DownloadSpotlight - { - get => downloadSpotlight; - set - { - downloadSpotlight = value; - OnStaticPropertyChanged(); - } - } - - public static string RetractSidebar - { - get => retractSidebar; - set - { - retractSidebar = value; - OnStaticPropertyChanged(); - } - } - - public static string RestrictPolicy - { - get => restrictPolicy; - set - { - restrictPolicy = value; - OnStaticPropertyChanged(); - } - } - - public static string Private - { - get => _private; - set - { - _private = value; - OnStaticPropertyChanged(); - } - } - - public static string Public - { - get => _public; - set - { - _public = value; - OnStaticPropertyChanged(); - } - } - - public static string HomePage - { - get => homePage; - set - { - homePage = value; - OnStaticPropertyChanged(); - } - } - - public static string MyGallery - { - get => myGallery; - set - { - myGallery = value; - OnStaticPropertyChanged(); - } - } - - public static string MyFollowing - { - get => myFollowing; - set - { - myFollowing = value; - OnStaticPropertyChanged(); - } - } - - public static string Spotlight - { - get => spotlight; - set - { - spotlight = value; - OnStaticPropertyChanged(); - } - } - - public static string Recommend - { - get => recommend; - set - { - recommend = value; - OnStaticPropertyChanged(); - } - } - - public static string IllustRanking - { - get => illustRanking; - set - { - illustRanking = value; - OnStaticPropertyChanged(); - } - } - - public static string UserTrend - { - get => userTrend; - set - { - userTrend = value; - OnStaticPropertyChanged(); - } - } - - public static string UserUpdate - { - get => userUpdate; - set - { - userUpdate = value; - OnStaticPropertyChanged(); - } - } - - public static string SearchImageBySource - { - get => searchImageBySource; - set - { - searchImageBySource = value; - OnStaticPropertyChanged(); - } - } - - public static string DownloadQueueAndHistory - { - get => downloadQueueAndHistory; - set - { - downloadQueueAndHistory = value; - OnStaticPropertyChanged(); - } - } - - public static string Setting - { - get => setting; - set - { - setting = value; - OnStaticPropertyChanged(); - } - } - - public static string Logout - { - get => logout; - set - { - logout = value; - OnStaticPropertyChanged(); - } - } - - public static string SearchHint - { - get => searchHint; - set - { - searchHint = value; - OnStaticPropertyChanged(); - } - } - - public static string QueryUser - { - get => queryUser; - set - { - queryUser = value; - OnStaticPropertyChanged(); - } - } - - public static string QuerySingleUser - { - get => querySingleUser; - set - { - querySingleUser = value; - OnStaticPropertyChanged(); - } - } - - public static string QuerySingleIllust - { - get => querySingleIllust; - set - { - querySingleIllust = value; - OnStaticPropertyChanged(); - } - } - - public static string RecommendIllustratorTurnPage - { - get => recommendIllustratorTurnPage; - set - { - recommendIllustratorTurnPage = value; - OnStaticPropertyChanged(); - } - } - - public static string PixevalVersionFormat - { - get => pixevalVersionFormat; - set - { - pixevalVersionFormat = value; - OnStaticPropertyChanged(); - } - } - - public static string AboutPixeval - { - get => aboutPixeval; - set - { - aboutPixeval = value; - OnStaticPropertyChanged(); - } - } - - public static string UserBrowserFollowCountHint - { - get => userBrowserFollowCountHint; - set - { - userBrowserFollowCountHint = value; - OnStaticPropertyChanged(); - } - } - - public static string UserBrowserFollow - { - get => userBrowserFollow; - set - { - userBrowserFollow = value; - OnStaticPropertyChanged(); - } - } - - public static string UserBrowserUnFollow - { - get => userBrowserUnFollow; - set - { - userBrowserUnFollow = value; - OnStaticPropertyChanged(); - } - } - - public static string UserBrowserPrivateFollow - { - get => userBrowserPrivateFollow; - set - { - userBrowserPrivateFollow = value; - OnStaticPropertyChanged(); - } - } - - public static string UserBrowserIllustSelector - { - get => userBrowserIllustSelector; - set - { - userBrowserIllustSelector = value; - OnStaticPropertyChanged(); - } - } - - public static string UserBrowserGallerySelector - { - get => userBrowserGallerySelector; - set - { - userBrowserGallerySelector = value; - OnStaticPropertyChanged(); - } - } - - public static string IllustBrowserIllustId - { - get => illustBrowserIllustId; - set - { - illustBrowserIllustId = value; - OnStaticPropertyChanged(); - } - } - - public static string IllustBrowserTotalViews - { - get => illustBrowserTotalViews; - set - { - illustBrowserTotalViews = value; - OnStaticPropertyChanged(); - } - } - - public static string IllustBrowserTotalBookmarks - { - get => illustBrowserTotalBookmarks; - set - { - illustBrowserTotalBookmarks = value; - OnStaticPropertyChanged(); - } - } - - public static string IllustBrowserResolution - { - get => illustBrowserResolution; - set - { - illustBrowserResolution = value; - OnStaticPropertyChanged(); - } - } - - public static string IllustBrowserUploadDate - { - get => illustBrowserUploadDate; - set - { - illustBrowserUploadDate = value; - OnStaticPropertyChanged(); - } - } - - public static string IllustBrowserIllustTag - { - get => illustBrowserIllustTag; - set - { - illustBrowserIllustTag = value; - OnStaticPropertyChanged(); - } - } - - public static string IllustBrowserSetWallpaper - { - get => illustBrowserSetWallpaper; - set - { - illustBrowserSetWallpaper = value; - OnStaticPropertyChanged(); - } - } - - public static string IllustBrowserShareLink - { - get => illustBrowserShareLink; - set - { - illustBrowserShareLink = value; - OnStaticPropertyChanged(); - } - } - - public static string IllustBrowserViewInBrowser - { - get => illustBrowserViewInBrowser; - set - { - illustBrowserViewInBrowser = value; - OnStaticPropertyChanged(); - } - } - - public static string IllustBrowserDownload - { - get => illustBrowserDownload; - set - { - illustBrowserDownload = value; - OnStaticPropertyChanged(); - } - } - - public static string IllustBrowserPrivateBookmark - { - get => illustBrowserPrivateBookmark; - set - { - illustBrowserPrivateBookmark = value; - OnStaticPropertyChanged(); - } - } - - public static string IllustBrowserBookmark - { - get => illustBrowserBookmark; - set - { - illustBrowserBookmark = value; - OnStaticPropertyChanged(); - } - } - - public static string IllustBrowserRemoveBookmark - { - get => illustBrowserRemoveBookmark; - set - { - illustBrowserRemoveBookmark = value; - OnStaticPropertyChanged(); - } - } - - public static string DownloadQueueShowDownloadIllust - { - get => downloadQueueShowDownloadIllust; - set - { - downloadQueueShowDownloadIllust = value; - OnStaticPropertyChanged(); - } - } - - public static string DownloadQueueRemoveFromDownloading - { - get => downloadQueueRemoveFromDownloading; - set - { - downloadQueueRemoveFromDownloading = value; - OnStaticPropertyChanged(); - } - } - - public static string DownloadQueueDownloading - { - get => downloadQueueDownloading; - set - { - downloadQueueDownloading = value; - OnStaticPropertyChanged(); - } - } - - public static string DownloadQueueEmptyNotifier - { - get => downloadQueueEmptyNotifier; - set - { - downloadQueueEmptyNotifier = value; - OnStaticPropertyChanged(); - } - } - - public static string DownloadQueueDownloaded - { - get => downloadQueueDownloaded; - set - { - downloadQueueDownloaded = value; - OnStaticPropertyChanged(); - } - } - - public static string EmailOrPasswordIsWrong - { - get => emailOrPasswordIsWrong; - set - { - emailOrPasswordIsWrong = value; - OnStaticPropertyChanged(); - } - } - - public static string Copy - { - get => copy; - set - { - copy = value; - OnStaticPropertyChanged(); - } - } - - public static string ConditionBoxHint - { - get => conditionBoxHint; - set - { - conditionBoxHint = value; - OnStaticPropertyChanged(); - } - } - - public static string PixevalSettings - { - get => pixevalSettings; - set - { - pixevalSettings = value; - OnStaticPropertyChanged(); - } - } - - public static string SortByPopulation - { - get => sortByPopulation; - set - { - sortByPopulation = value; - OnStaticPropertyChanged(); - } - } - - public static string TurnOffR18 - { - get => turnOffR18; - set - { - turnOffR18 = value; - OnStaticPropertyChanged(); - } - } - - public static string TurnOnIllustratorRecommend - { - get => turnOnIllustratorRecommend; - set - { - turnOnIllustratorRecommend = value; - OnStaticPropertyChanged(); - } - } - - public static string TurnOnDirectConnect - { - get => turnOnDirectConnect; - set - { - turnOnDirectConnect = value; - OnStaticPropertyChanged(); - } - } - - public static string TagMatchOption - { - get => tagMatchOption; - set - { - tagMatchOption = value; - OnStaticPropertyChanged(); - } - } - - public static string TurnOnCache - { - get => turnOnCache; - set - { - turnOnCache = value; - OnStaticPropertyChanged(); - } - } - - public static string MemoryCachePolicy - { - get => memoryCachePolicy; - set - { - memoryCachePolicy = value; - OnStaticPropertyChanged(); - } - } - - public static string FileCachePolicy - { - get => fileCachePolicy; - set - { - fileCachePolicy = value; - OnStaticPropertyChanged(); - } - } - - public static string MinBookmarkRequired - { - get => minBookmarkRequired; - set - { - minBookmarkRequired = value; - OnStaticPropertyChanged(); - } - } - - public static string SearchPageCountHint - { - get => searchPageCountHint; - set - { - searchPageCountHint = value; - OnStaticPropertyChanged(); - } - } - - public static string SearchPageStart - { - get => searchPageStart; - set - { - searchPageStart = value; - OnStaticPropertyChanged(); - } - } - - public static string SpotlightSearchPageStart - { - get => spotlightSearchPageStart; - set - { - spotlightSearchPageStart = value; - OnStaticPropertyChanged(); - } - } - - public static string DownloadLocation - { - get => downloadLocation; - set - { - downloadLocation = value; - OnStaticPropertyChanged(); - } - } - - public static string TagsToBeExclude - { - get => tagsToBeExclude; - set - { - tagsToBeExclude = value; - OnStaticPropertyChanged(); - } - } - - public static string TagsToBeInclude - { - get => tagsToBeInclude; - set - { - tagsToBeInclude = value; - OnStaticPropertyChanged(); - } - } - - public static string SearchPerPageCountHint - { - get => searchPerPageCountHint; - set - { - searchPerPageCountHint = value; - OnStaticPropertyChanged(); - } - } - - public static string TurnOnWebR18 - { - get => turnOnWebR18; - set - { - turnOnWebR18 = value; - OnStaticPropertyChanged(); - } - } - - public static string SauceNaoFileLocationHint - { - get => sauceNaoFileLocationHint; - set - { - sauceNaoFileLocationHint = value; - OnStaticPropertyChanged(); - } - } - - public static string SauceNaoUploadAndSearch - { - get => sauceNaoUploadAndSearch; - set - { - sauceNaoUploadAndSearch = value; - OnStaticPropertyChanged(); - } - } - - public static string SignIn - { - get => signIn; - set - { - signIn = value; - OnStaticPropertyChanged(); - } - } - - public static string SignInAccount - { - get => signInAccount; - set - { - signInAccount = value; - OnStaticPropertyChanged(); - } - } - - public static string SignInPassword - { - get => signInPassword; - set - { - signInPassword = value; - OnStaticPropertyChanged(); - } - } - - public static string SignInButtonText - { - get => signInButtonText; - set - { - signInButtonText = value; - OnStaticPropertyChanged(); - } - } - - public static string SignInUpdatingSession - { - get => signInUpdatingSession; - set - { - signInUpdatingSession = value; - OnStaticPropertyChanged(); - } - } - - public static string BrowsingHistoryCount - { - get => browsingHistoryCount; - set - { - browsingHistoryCount = value; - OnStaticPropertyChanged(); - } - } - - public static string DownloadQueueBrowsingHistory - { - get => downloadQueueBrowsingHistory; - set - { - downloadQueueBrowsingHistory = value; - OnStaticPropertyChanged(); - } - } - - public static string DownloadQueueHistoryListIsEmpty - { - get => downloadQueueHistoryListIsEmpty; - set - { - downloadQueueHistoryListIsEmpty = value; - OnStaticPropertyChanged(); - } - } - - public static string PixevalUpdateAvailable - { - get => pixevalUpdateAvailable; - set - { - pixevalUpdateAvailable = value; - OnStaticPropertyChanged(); - } - } - - public static string PixevalUpdateAvailableTitle - { - get => pixevalUpdateAvailableTitle; - set - { - pixevalUpdateAvailableTitle = value; - OnStaticPropertyChanged(); - } - } - - public static string ThisLoginSessionRequiresRecaptcha - { - get => thisLoginSessionRequiresRecaptcha; - set - { - thisLoginSessionRequiresRecaptcha = value; - OnStaticPropertyChanged(); - } - } - - public static string SupportMe - { - get => supportMe; - set - { - supportMe = value; - OnStaticPropertyChanged(); - } - } - - public static string DownloadTo - { - get => downloadTo; - set - { - downloadTo = value; - OnStaticPropertyChanged(); - } - } - - public static string UserPreviewPopupFollow - { - get => userPreviewPopupFollow; - set - { - userPreviewPopupFollow = value; - OnStaticPropertyChanged(); - } - } - - public static string UserPreviewPopupUnFollow - { - get => userPreviewPopupUnFollow; - set - { - userPreviewPopupUnFollow = value; - OnStaticPropertyChanged(); - } - } - - public static string SelectCultureInfo - { - get => selectCultureInfo; - set - { - selectCultureInfo = value; - OnStaticPropertyChanged(); - } - } - - public static string CreateNewFolderWhenDownloadFromUser - { - get => createNewFolderWhenDownloadFromUser; - set - { - createNewFolderWhenDownloadFromUser = value; - OnStaticPropertyChanged(); - } - } - - public static event PropertyChangedEventHandler StaticPropertyChanged; - - private static void OnStaticPropertyChanged([CallerMemberName] - string propertyName = null) - { - StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs(propertyName)); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/I18n/Xml/resx_en-us.xml b/src/Pixeval/Objects/I18n/Xml/resx_en-us.xml deleted file mode 100644 index c2434431..00000000 --- a/src/Pixeval/Objects/I18n/Xml/resx_en-us.xml +++ /dev/null @@ -1,175 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Pixeval/Objects/I18n/Xml/resx_zh-cn.xml b/src/Pixeval/Objects/I18n/Xml/resx_zh-cn.xml deleted file mode 100644 index b76e2aa2..00000000 --- a/src/Pixeval/Objects/I18n/Xml/resx_zh-cn.xml +++ /dev/null @@ -1,173 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Pixeval/Objects/Native/WallpaperManager.cs b/src/Pixeval/Objects/Native/WallpaperManager.cs deleted file mode 100644 index c3803245..00000000 --- a/src/Pixeval/Objects/Native/WallpaperManager.cs +++ /dev/null @@ -1,76 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Runtime.InteropServices; -using System.Threading.Tasks; -using System.Windows.Media.Imaging; -using Microsoft.Win32; -using Pixeval.Objects.Primitive; - -namespace Pixeval.Objects.Native -{ - public class WallpaperManager - { - private const int SetDeskWallpaper = 20; - private const int UpdateIniFile = 0x01; - private const int SendWinIniChange = 0x02; - - public WallpaperManager(string storeLocation, BitmapSource background) - { - StoreLocation = storeLocation; - Background = background; - } - - public string StoreLocation { get; set; } - - public BitmapSource Background { get; set; } - - [DllImport("user32.dll", CharSet = CharSet.Auto)] - private static extern int SystemParametersInfo(int uAction, int uParameter, string lpvParameter, int fuWinIni); - - private async Task CreateBmpFile() - { - await Background.Save(StoreLocation); - } - - private static bool CheckOperatingSystemVersion() - { - var win8Version = new Version(6, 2, 9200, 0); - return Environment.OSVersion.Platform == PlatformID.Win32NT && Environment.OSVersion.Version >= win8Version; - } - - private bool IsImageSupportSpan() - { - return Background.PixelWidth / (double) Background.PixelHeight >= 1.7; - } - - public async ValueTask Execute() - { - await CreateBmpFile(); - using var regKey = Registry.CurrentUser.OpenSubKey(@"Control Panel\Desktop", true); - if (regKey == null) return false; - regKey.SetValue("WallpaperStyle", (CheckOperatingSystemVersion() && IsImageSupportSpan() ? /* span */ 22 : /* normal */ 10).ToString()); - regKey.SetValue("TitleWallpaper", 0.ToString()); - SystemParametersInfo(SetDeskWallpaper, 0, StoreLocation, UpdateIniFile | SendWinIniChange); - return true; - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/Primitive/Attributes.cs b/src/Pixeval/Objects/Primitive/Attributes.cs deleted file mode 100644 index b6006fb9..00000000 --- a/src/Pixeval/Objects/Primitive/Attributes.cs +++ /dev/null @@ -1,46 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; - -namespace Pixeval.Objects.Primitive -{ - [AttributeUsage(AttributeTargets.Field)] - public class EnumAlias : Attribute - { - public EnumAlias(string aliasAs) - { - AliasAs = aliasAs; - } - - public string AliasAs { get; set; } - } - - [AttributeUsage(AttributeTargets.Field)] - public class EnumLocalizedName : Attribute - { - public EnumLocalizedName(string name) - { - Name = name; - } - - public string Name { get; set; } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/Primitive/InternalIO.cs b/src/Pixeval/Objects/Primitive/InternalIO.cs deleted file mode 100644 index 868e6b6a..00000000 --- a/src/Pixeval/Objects/Primitive/InternalIO.cs +++ /dev/null @@ -1,134 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections.Generic; -using System.IO; -using System.IO.Compression; -using System.Threading.Tasks; -using System.Windows.Media.Imaging; -using ImageMagick; - -namespace Pixeval.Objects.Primitive -{ - // ReSharper disable once InconsistentNaming - public static class InternalIO - { - public static async Task ToBytes(this Stream stream) - { - if (stream is MemoryStream ms) return ms.ToArray(); - - var mStream = new MemoryStream(); - await stream.CopyToAsync(mStream); - return mStream.ToArray(); - } - - public static BitmapImage CreateBitmapImageFromStream(Stream stream) - { - stream.Seek(0, SeekOrigin.Begin); - if (stream.Length == 0) return null; - var bmp = new BitmapImage {CreateOptions = BitmapCreateOptions.DelayCreation}; - bmp.BeginInit(); - bmp.CacheOption = BitmapCacheOption.OnLoad; - bmp.StreamSource = stream; - bmp.EndInit(); - bmp.Freeze(); - return bmp; - } - - public static async Task ToByteArrayAsync(this BitmapImage bitmapImage) - { - if (bitmapImage.StreamSource is { } stream) - { - var ms = new MemoryStream(); - await stream.CopyToAsync(ms); - ms.Position = 0L; - return ms.ToArray(); - } - - throw new ArgumentException(nameof(bitmapImage.StreamSource)); - } - - public static IReadOnlyList ReadGifZipEntries(Stream stream) - { - var dis = new List(); - using var zipArchive = new ZipArchive(stream, ZipArchiveMode.Read); - - foreach (var zipArchiveEntry in zipArchive.Entries) - { - using var aStream = zipArchiveEntry.Open(); - - var ms = new MemoryStream(); - aStream.CopyTo(ms); - ms.Position = 0L; - dis.Add(ms); - } - - return dis; - } - - public static IEnumerable ReadGifZipEntries(byte[] bArr) - { - return ReadGifZipEntries(new MemoryStream(bArr)); - } - - public static Stream MergeGifStream(IReadOnlyList streams, IReadOnlyList delay) - { - var ms = new MemoryStream(); - using var mCollection = new MagickImageCollection(); - - for (var i = 0; i < streams.Count; i++) - { - var iStream = streams[i]; - - var img = new MagickImage(iStream) {AnimationDelay = (int) delay[i]}; - mCollection.Add(img); - } - - var settings = new QuantizeSettings {Colors = 256}; - mCollection.Quantize(settings); - mCollection.Optimize(); - mCollection.Write(ms, MagickFormat.Gif); - return ms; - } - - public static Stream ToStream(this BitmapImage bitmapImage) - { - var ms = new MemoryStream(); - var encoder = new PngBitmapEncoder(); - encoder.Frames.Add(BitmapFrame.Create(bitmapImage)); - encoder.Save(ms); - return ms; - } - - public static async Task Save(this BitmapSource bitmapImage, string location) where TEncoder : BitmapEncoder, new() - { - var encoder = new TEncoder(); - encoder.Frames.Add(BitmapFrame.Create(bitmapImage)); - await using var fs = CreateNewChannel(location); - encoder.Save(fs); - } - - public static FileStream CreateNewChannel(string location) - { - return new FileStream(location, FileMode.Create, FileAccess.ReadWrite, FileShare.None); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/Primitive/Reflection.cs b/src/Pixeval/Objects/Primitive/Reflection.cs deleted file mode 100644 index 51a2cd9e..00000000 --- a/src/Pixeval/Objects/Primitive/Reflection.cs +++ /dev/null @@ -1,44 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Reflection; -using Pixeval.Objects.Exceptions; - -namespace Pixeval.Objects.Primitive -{ - public static class Reflection - { - public static T GetCustomAttribute(this object obj) where T : Attribute - { - return CustomAttributeExtensions.GetCustomAttribute(obj.GetType()) ?? throw new AttributeNotFoundException(typeof(T).ToString()); - } - - public static T GetEnumAttribute(this Enum value) where T : Attribute - { - return value.GetType().GetField(value.ToString())!.GetCustomAttribute(false) ?? throw new AttributeNotFoundException(typeof(T).ToString()); - } - - public static bool AttributeAttached(this Enum value) where T : Attribute - { - return value.GetType().GetField(value.ToString())!.GetCustomAttribute(false) != null; - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/Primitive/Strings.cs b/src/Pixeval/Objects/Primitive/Strings.cs deleted file mode 100644 index f1f59e24..00000000 --- a/src/Pixeval/Objects/Primitive/Strings.cs +++ /dev/null @@ -1,103 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Security.Cryptography; -using System.Text; -using Newtonsoft.Json; - -namespace Pixeval.Objects.Primitive -{ - public static class Strings - { - public static byte[] GetBytes(this string str, Encoding encoding = null) - { - return encoding == null ? Encoding.UTF8.GetBytes(str) : encoding.GetBytes(str); - } - - public static string GetString(this byte[] data, Encoding encoding = null) - { - return encoding == null ? Encoding.UTF8.GetString(data) : encoding.GetString(data); - } - - public static string ToJson(this T obj) - { - return JsonConvert.SerializeObject(obj, new JsonSerializerSettings {Formatting = Formatting.Indented}); - } - - public static T FromJson(this string src) - { - return JsonConvert.DeserializeObject(src); - } - - public static string Join(this IEnumerable enumerable, Func transformer, char delimiter) - { - return string.Join(delimiter, enumerable.Select(transformer)); - } - - public static string Join(this IEnumerable enumerable, char delimiter) - { - return string.Join(delimiter, enumerable); - } - - public static bool IsNullOrEmpty(this string src) - { - return string.IsNullOrEmpty(src); - } - - public static bool EqualsIgnoreCase(this string str1, string str2) - { - return string.Equals(str1, str2, StringComparison.OrdinalIgnoreCase); - } - - public static bool IsNumber(this string str) - { - return int.TryParse(str, out _); - } - - // see https://stackoverflow.com/questions/146134/how-to-remove-illegal-characters-from-path-and-filenames - public static string FormatPath(string original) - { - return string.Concat(original.Split(Path.GetInvalidFileNameChars())); - } - - public static string AssumeImageContentType(string fileName) - { - return fileName[^3..] switch - { - "png" => "image/png", - "jpg" => "image/jpeg", - "jpeg" => "image/jpeg", - "gif" => "image/gif", - _ => "image/jpeg" - }; - } - - public static string Hash(this string str) where T : HashAlgorithm, new() - { - using var crypt = new T(); - var hashBytes = crypt.ComputeHash(str.GetBytes()); - return hashBytes.Select(b => b.ToString("x2")).Aggregate((s1, s2) => s1 + s2); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/Primitive/UIHelper.cs b/src/Pixeval/Objects/Primitive/UIHelper.cs deleted file mode 100644 index a0a278ae..00000000 --- a/src/Pixeval/Objects/Primitive/UIHelper.cs +++ /dev/null @@ -1,243 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Controls.Primitives; -using System.Windows.Input; -using System.Windows.Interop; -using System.Windows.Media; -using System.Windows.Media.Animation; -using Microsoft.CSharp.RuntimeBinder; - -namespace Pixeval.Objects.Primitive -{ - public static class UiHelper - { - [DllImport("user32.dll")] - private static extern IntPtr GetForegroundWindow(); - - [DllImport("user32.dll")] - private static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr processId); - - [DllImport("user32.dll")] - private static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach); - - [DllImport("user32.dll")] - public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags); - - /// - /// Little trick, from https://stackoverflow.com/questions/257587/bring-a-window-to-the-front-in-wpf - /// - /// window to active - public static void GlobalActivate(this Window w) - { - const uint noSize = 0x0001; - const uint noMove = 0x0002; - const uint showWindow = 0x0040; - var interopHelper = new WindowInteropHelper(w); - var thisWindowThreadId = GetWindowThreadProcessId(interopHelper.Handle, IntPtr.Zero); - var currentForegroundWindow = GetForegroundWindow(); - var currentForegroundWindowThreadId = GetWindowThreadProcessId(currentForegroundWindow, IntPtr.Zero); - AttachThreadInput(currentForegroundWindowThreadId, thisWindowThreadId, true); - SetWindowPos(interopHelper.Handle, new IntPtr(0), 0, 0, 0, 0, noSize | noMove | showWindow); - AttachThreadInput(currentForegroundWindowThreadId, thisWindowThreadId, false); - if (w.WindowState == WindowState.Minimized) w.WindowState = WindowState.Normal; - w.Show(); - w.Activate(); - } - - public static void Disable(this FrameworkElement element) - { - element.IsEnabled = false; - } - - public static void Enable(this FrameworkElement element) - { - element.IsEnabled = true; - } - - public static IEnumerable FindVisualChildren(DependencyObject depObj) where T : DependencyObject - { - if (depObj != null) - for (var i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++) - { - var child = VisualTreeHelper.GetChild(depObj, i); - if (child is T dependencyObject) yield return dependencyObject; - - foreach (var childOfChild in FindVisualChildren(child)) yield return childOfChild; - } - } - - public static T DataContext(this FrameworkElement element) - { - return (T) element.DataContext; - } - - public static void SetImageSource(object img, ImageSource imgSource) - { - Application.Current.Dispatcher?.Invoke(() => ((Image) img).Source = imgSource); - } - - public static void ReleaseImage(object img) - { - Application.Current.Dispatcher?.Invoke(() => ((Image) img).Source = null); - } - - public static ObservableCollection NewItemsSource(ItemsControl itemsControl) - { - var collection = new ObservableCollection(); - SetItemsSource(itemsControl, collection); - return collection; - } - - public static void SetItemsSource(ItemsControl itemsControl, IEnumerable itemSource) - { - itemsControl.ItemsSource = itemSource; - } - - public static void ReleaseItemsSource(ItemsControl listView) - { - listView.ItemsSource = null; - } - - public static void StartDoubleAnimationUseCubicEase(object sender, string path, double from, double to, int milliseconds) - { - var sb = new Storyboard(); - var doubleAnimation = new DoubleAnimation(from, to, TimeSpan.FromMilliseconds(milliseconds)) {EasingFunction = new CubicEase {EasingMode = EasingMode.EaseOut}}; - Storyboard.SetTarget(doubleAnimation, (DependencyObject) sender); - Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath(path)); - sb.Children.Add(doubleAnimation); - sb.Begin(); - } - - public static T GetDataContext(this object sender) - { - if (sender is FrameworkElement element) return element.DataContext(); - - throw new NotSupportedException($"parameter must be derive class of {nameof(FrameworkElement)}"); - } - - public static T GetResources(this FrameworkElement element, string name) - { - return (T) element.Resources[name]; - } - - public static void CloseControls(params UIElement[] controls) - { - foreach (var control in controls) CloseControl(control); - } - - public static void CloseControl(this UIElement control) - { - try - { - ((dynamic) control).IsOpen = false; - } - catch (RuntimeBinderException) - { - // ignore - } - } - - public static void OpenControl(this UIElement control) - { - try - { - ((dynamic) control).IsOpen = true; - } - catch (RuntimeBinderException) - { - // ignore - } - } - - public static void Scroll(ScrollViewer sender, MouseWheelEventArgs e) - { - if (e.Delta > 0) - { - sender.LineUp(); - sender.LineUp(); - } - else - { - sender.LineDown(); - sender.LineDown(); - } - } - } - - public class PopupHelper - { - public static readonly DependencyProperty PopupPlacementTargetProperty = DependencyProperty.RegisterAttached("PopupPlacementTarget", typeof(DependencyObject), typeof(PopupHelper), new PropertyMetadata(null, OnPopupPlacementTargetChanged)); - - public static DependencyObject GetPopupPlacementTarget(DependencyObject obj) - { - return (DependencyObject) obj.GetValue(PopupPlacementTargetProperty); - } - - public static void SetPopupPlacementTarget(DependencyObject obj, DependencyObject value) - { - obj.SetValue(PopupPlacementTargetProperty, value); - } - - private static void OnPopupPlacementTargetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - if (e.NewValue != null) - { - var popupPopupPlacementTarget = e.NewValue as DependencyObject; - var pop = d as Popup; - - var w = Window.GetWindow(popupPopupPlacementTarget ?? throw new InvalidOperationException()); - if (null != w) - { - w.LocationChanged += (sender, args) => - { - if (pop != null) - { - var offset = pop.HorizontalOffset; - pop.HorizontalOffset = offset + 1; - pop.HorizontalOffset = offset; - } - }; - - w.SizeChanged += (sender, args) => - { - var mi = typeof(Popup).GetMethod("UpdatePosition", BindingFlags.NonPublic | BindingFlags.Instance); - try - { - mi?.Invoke(pop, null); - } - catch - { - // ignored - } - }; - } - } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/ValueConverters/BoolToCachingPolicyConverter.cs b/src/Pixeval/Objects/ValueConverters/BoolToCachingPolicyConverter.cs deleted file mode 100644 index e0603285..00000000 --- a/src/Pixeval/Objects/ValueConverters/BoolToCachingPolicyConverter.cs +++ /dev/null @@ -1,40 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Globalization; -using System.Windows.Data; -using Pixeval.Objects.Caching; - -namespace Pixeval.Objects.ValueConverters -{ - public class BoolToCachingPolicyConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - return value is CachingPolicy.File; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - return value is true ? CachingPolicy.File : CachingPolicy.Memory; - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/ValueConverters/DateTimeConverter.cs b/src/Pixeval/Objects/ValueConverters/DateTimeConverter.cs deleted file mode 100644 index dd737e4e..00000000 --- a/src/Pixeval/Objects/ValueConverters/DateTimeConverter.cs +++ /dev/null @@ -1,41 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Globalization; -using System.Windows.Data; - -namespace Pixeval.Objects.ValueConverters -{ - public class DateTimeConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - if (value is DateTime d) return d.ToString("yyyy/MM/dd HH:mm:ss"); - - return string.Empty; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/ValueConverters/DateTimeOffsetConverter.cs b/src/Pixeval/Objects/ValueConverters/DateTimeOffsetConverter.cs deleted file mode 100644 index 4b3ab635..00000000 --- a/src/Pixeval/Objects/ValueConverters/DateTimeOffsetConverter.cs +++ /dev/null @@ -1,41 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Globalization; -using System.Windows.Data; - -namespace Pixeval.Objects.ValueConverters -{ - public class DateTimeOffsetConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - if (value is DateTimeOffset d) return d.ToString("yyyy/MM/dd HH:mm:ss"); - - return string.Empty; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/ValueConverters/DoubleToPercentConverter.cs b/src/Pixeval/Objects/ValueConverters/DoubleToPercentConverter.cs deleted file mode 100644 index 2aec3e01..00000000 --- a/src/Pixeval/Objects/ValueConverters/DoubleToPercentConverter.cs +++ /dev/null @@ -1,41 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Globalization; -using System.Windows.Data; - -namespace Pixeval.Objects.ValueConverters -{ - public class DoubleToPercentConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - if (value is double d) return $"{d * 100:F}%"; - - return string.Empty; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/ValueConverters/EnumToStringConverter.cs b/src/Pixeval/Objects/ValueConverters/EnumToStringConverter.cs deleted file mode 100644 index fe811eda..00000000 --- a/src/Pixeval/Objects/ValueConverters/EnumToStringConverter.cs +++ /dev/null @@ -1,49 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Globalization; -using System.Windows.Data; - -namespace Pixeval.Objects.ValueConverters -{ - public class EnumToStringConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - if (value is Enum v) - try - { - return Enum.GetName(v.GetType(), value); - } - catch - { - return string.Empty; - } - - return string.Empty; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/ValueConverters/IllustSubscriptConverter.cs b/src/Pixeval/Objects/ValueConverters/IllustSubscriptConverter.cs deleted file mode 100644 index ffde7a40..00000000 --- a/src/Pixeval/Objects/ValueConverters/IllustSubscriptConverter.cs +++ /dev/null @@ -1,46 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Globalization; -using System.Windows; -using System.Windows.Data; -using Pixeval.Data.ViewModel; - -namespace Pixeval.Objects.ValueConverters -{ - public class IllustSubscriptConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - var val = (Illustration) value; - if (val == null) return Visibility.Hidden; - - if (val.IsManga || val.IsUgoira) return Visibility.Visible; - - return Visibility.Hidden; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/ValueConverters/IllustrationMatchConditionMaskConverter.cs b/src/Pixeval/Objects/ValueConverters/IllustrationMatchConditionMaskConverter.cs deleted file mode 100644 index 46d09789..00000000 --- a/src/Pixeval/Objects/ValueConverters/IllustrationMatchConditionMaskConverter.cs +++ /dev/null @@ -1,44 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Globalization; -using System.Windows; -using System.Windows.Data; -using Pixeval.Core; -using Pixeval.Data.ViewModel; - -namespace Pixeval.Objects.ValueConverters -{ - public class IllustrationMatchConditionMaskConverter : IMultiValueConverter - { - public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) - { - if (values[0] is string v && values[1] is Illustration illustration) return AppContext.DefaultQualifier.Qualified(illustration, IllustrationQualification.Parse(v)) ? Visibility.Visible : Visibility.Hidden; - - return Visibility.Hidden; - } - - public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/ValueConverters/InverseBooleanConverter.cs b/src/Pixeval/Objects/ValueConverters/InverseBooleanConverter.cs deleted file mode 100644 index f273b6a6..00000000 --- a/src/Pixeval/Objects/ValueConverters/InverseBooleanConverter.cs +++ /dev/null @@ -1,39 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Globalization; -using System.Windows.Data; - -namespace Pixeval.Objects.ValueConverters -{ - public class InverseBooleanConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - return value is bool b && !b; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/ValueConverters/MultiCultureConverter.cs b/src/Pixeval/Objects/ValueConverters/MultiCultureConverter.cs deleted file mode 100644 index f1208e3f..00000000 --- a/src/Pixeval/Objects/ValueConverters/MultiCultureConverter.cs +++ /dev/null @@ -1,45 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Globalization; -using System.Linq; -using System.Windows.Data; -using Pixeval.Data.ViewModel; - -namespace Pixeval.Objects.ValueConverters -{ - public class MultiCultureConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - if (value is string s) return AppContext.AvailableCultures.FirstOrDefault(cul => cul.Name == s) ?? I18NOption.ChineseSimplified; - - return I18NOption.ChineseSimplified; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - if (value is I18NOption option) return option.Name; - - return I18NOption.ChineseSimplified.Name; - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/ValueConverters/NumericConverter.cs b/src/Pixeval/Objects/ValueConverters/NumericConverter.cs deleted file mode 100644 index 6689fc9d..00000000 --- a/src/Pixeval/Objects/ValueConverters/NumericConverter.cs +++ /dev/null @@ -1,55 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Globalization; -using System.Windows.Data; - -namespace Pixeval.Objects.ValueConverters -{ - public class DoublePlusConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - if (value == null || parameter == null) return 0; - return (double) value + (double) parameter; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } - } - - public class DoubleDivisionConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - if (value != null && parameter != null) return (double) value / (double) parameter; - - return 0; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/ValueConverters/QueryR18ToggleButtonIsCheckedConverter.cs b/src/Pixeval/Objects/ValueConverters/QueryR18ToggleButtonIsCheckedConverter.cs deleted file mode 100644 index 7f656239..00000000 --- a/src/Pixeval/Objects/ValueConverters/QueryR18ToggleButtonIsCheckedConverter.cs +++ /dev/null @@ -1,47 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Windows.Data; - -namespace Pixeval.Objects.ValueConverters -{ - public class QueryR18ToggleButtonIsCheckedConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - if (value is IEnumerable val) - { - var enumerable = val as string[] ?? val.ToArray(); - if (enumerable.Contains("R-18") && enumerable.Contains("R-18G")) return true; - } - - return false; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/ValueConverters/StringSplitConverter.cs b/src/Pixeval/Objects/ValueConverters/StringSplitConverter.cs deleted file mode 100644 index ba1bc66a..00000000 --- a/src/Pixeval/Objects/ValueConverters/StringSplitConverter.cs +++ /dev/null @@ -1,42 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Windows.Data; -using Pixeval.Objects.Primitive; - -namespace Pixeval.Objects.ValueConverters -{ - public class StringSplitConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - return value == null ? string.Empty : string.Join(' ', value as IEnumerable ?? Array.Empty()); - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - if (value == null || value.ToString().IsNullOrEmpty()) return new List(); - return value.ToString()?.Split(" ") ?? Array.Empty(); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/ValueConverters/TagMatchEnumToModelConverter.cs b/src/Pixeval/Objects/ValueConverters/TagMatchEnumToModelConverter.cs deleted file mode 100644 index 699c517d..00000000 --- a/src/Pixeval/Objects/ValueConverters/TagMatchEnumToModelConverter.cs +++ /dev/null @@ -1,51 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Globalization; -using System.Windows.Data; -using Pixeval.Core; -using Pixeval.Data.ViewModel; - -namespace Pixeval.Objects.ValueConverters -{ - public class TagMatchEnumToModelConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - if (value is SearchTagMatchOption option) - return option switch - { - SearchTagMatchOption.PartialMatchForTags => SearchTagMatchOptionModel.PartialMatchModel, - SearchTagMatchOption.ExactMatchForTags => SearchTagMatchOptionModel.ExactMatchModel, - SearchTagMatchOption.TitleAndCaption => SearchTagMatchOptionModel.TitleAndCaptionModel, - _ => throw new ArgumentOutOfRangeException() - }; - return null; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - if (value is SearchTagMatchOptionModel model) return model.Corresponding; - - return null; - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/ValueConverters/TrendsStatConverter.cs b/src/Pixeval/Objects/ValueConverters/TrendsStatConverter.cs deleted file mode 100644 index 5c4ad440..00000000 --- a/src/Pixeval/Objects/ValueConverters/TrendsStatConverter.cs +++ /dev/null @@ -1,51 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Globalization; -using System.Windows.Data; -using Pixeval.Data.ViewModel; -using Pixeval.Objects.I18n; - -namespace Pixeval.Objects.ValueConverters -{ - [ValueConversion(typeof(TrendType), typeof(string))] - public class TrendsStatConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - if (value is TrendType obj) - return obj switch - { - TrendType.AddIllust => AkaI18N.TrendsAddIllust, - TrendType.AddBookmark => AkaI18N.TrendsAddBookmark, - TrendType.AddFavorite => AkaI18N.TrendsAddFavorite, - _ => string.Empty - }; - - return string.Empty; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/ValueConverters/VisibilityConverter.cs b/src/Pixeval/Objects/ValueConverters/VisibilityConverter.cs deleted file mode 100644 index 00f7786c..00000000 --- a/src/Pixeval/Objects/ValueConverters/VisibilityConverter.cs +++ /dev/null @@ -1,93 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Globalization; -using System.Linq; -using System.Windows; -using System.Windows.Data; - -namespace Pixeval.Objects.ValueConverters -{ - public class VisibleIfTrueConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - value ??= false; - var val = (bool) value; - return val ? Visibility.Visible : Visibility.Hidden; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } - } - - public class VisibleIfFalseConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - value ??= false; - - var val = (bool) value; - return val ? Visibility.Hidden : Visibility.Visible; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } - } - - public class ImageListViewVisibilityConverter : IMultiValueConverter - { - public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) - { - var val = values.Cast().ToArray(); - - if (!(val[0] || val[1] || val[2] || val[3])) return Visibility.Visible; - - return Visibility.Hidden; - } - - public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } - } - - public class UserPreviewListViewVisibilityConverter : IMultiValueConverter - { - public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) - { - var val = values.Cast().ToArray(); - - if (!val[0] && !val[1] || val[2]) return Visibility.Visible; - - return Visibility.Hidden; - } - - public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/Web/HttpsProxyServer.cs b/src/Pixeval/Objects/Web/HttpsProxyServer.cs deleted file mode 100644 index 84cadf22..00000000 --- a/src/Pixeval/Objects/Web/HttpsProxyServer.cs +++ /dev/null @@ -1,148 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.IO; -using System.Net; -using System.Net.Security; -using System.Net.Sockets; -using System.Security.Authentication; -using System.Security.Cryptography.X509Certificates; -using System.Threading.Tasks; - -namespace Pixeval.Objects.Web -{ - /// - /// Thanks fish, for login usage only, - /// USE AT YOUR OWN RISK - /// - public class HttpsProxyServer : IDisposable - { - private readonly X509Certificate2 _certificate; - private readonly string _ip; - private readonly TcpListener _tcpListener; - - /// - /// Create an with specified host, port, target and certificate - /// - /// proxy server host - /// proxy server port to listen - /// the ip need to be forwarding to - /// server certificate - private HttpsProxyServer(string host, int port, string targetIp, X509Certificate2 x509Certificate2) - { - _ip = targetIp; - _certificate = x509Certificate2; - _tcpListener = new TcpListener(IPAddress.Parse(host), port); - _tcpListener.Start(); - _tcpListener.BeginAcceptTcpClient(AcceptTcpClientCallback, _tcpListener); - } - - public void Dispose() - { - _certificate?.Dispose(); - _tcpListener.Stop(); - } - - public static HttpsProxyServer Create(string host, int port, string targetIp, X509Certificate2 x509Certificate2) - { - return new HttpsProxyServer(host, port, targetIp, x509Certificate2); - } - - private async void AcceptTcpClientCallback(IAsyncResult result) - { - try - { - var listener = (TcpListener) result.AsyncState; - if (listener != null) - { - var client = listener.EndAcceptTcpClient(result); - listener.BeginAcceptTcpClient(AcceptTcpClientCallback, listener); - using (client) - { - var clientStream = client.GetStream(); - var content = await new StreamReader(clientStream).ReadLineAsync(); - // content starts with "CONNECT" means it's trying to establish an HTTPS connection - if (content == null || !content.StartsWith("CONNECT")) return; - var writer = new StreamWriter(clientStream); - await writer.WriteLineAsync("HTTP/1.1 200 Connection established"); - await writer.WriteLineAsync($"Timestamp: {DateTime.Now}"); - await writer.WriteLineAsync("Proxy-agent: Pixeval"); - await writer.WriteLineAsync(); - await writer.FlushAsync(); - var clientSsl = new SslStream(clientStream, false); - // use specified certificate to establish the HTTPS connection - await clientSsl.AuthenticateAsServerAsync(_certificate, false, SslProtocols.Tls | SslProtocols.Tls13 | SslProtocols.Tls12 | SslProtocols.Tls11, false); - // create an HTTP connection to the target IP - var serverSsl = await CreateConnection(_ip); - - // forwarding the HTTPS connection without SNI - var request = Task.Run(() => - { - try - { - clientSsl.CopyTo(serverSsl); - } - catch - { - // ignore - } - }); - var response = Task.Run(() => - { - try - { - serverSsl.CopyTo(clientSsl); - } - catch - { - // ignore - } - }); - Task.WaitAny(request, response); - serverSsl.Close(); - } - } - } - catch - { - // ignore - } - } - - private static async Task CreateConnection(string ip) - { - var client = new TcpClient(); - await client.ConnectAsync(ip, 443); - var netStream = client.GetStream(); - var sslStream = new SslStream(netStream, false, (sender, certificate, chain, errors) => true); - try - { - await sslStream.AuthenticateAsClientAsync(""); - return sslStream; - } - catch - { - await sslStream.DisposeAsync(); - throw; - } - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Objects/Web/PacFileServer.cs b/src/Pixeval/Objects/Web/PacFileServer.cs deleted file mode 100644 index 65191e3e..00000000 --- a/src/Pixeval/Objects/Web/PacFileServer.cs +++ /dev/null @@ -1,36 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using EmbedIO; - -namespace Pixeval.Objects.Web -{ - /// - /// A small server in order to represent the proxy-auto-configuration file - /// - public static class PacFileServer - { - public static WebServer Create(string hostname, int port) - { - var server = new WebServer(o => o.WithUrlPrefix($"http://{hostname}:{port}").WithMode(HttpListenerMode.EmbedIO)).WithStaticFolder("/", AppContext.ResourceFolder, false); - return server; - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Persisting/Authentication.cs b/src/Pixeval/Persisting/Authentication.cs deleted file mode 100644 index 41bbe0d5..00000000 --- a/src/Pixeval/Persisting/Authentication.cs +++ /dev/null @@ -1,193 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Linq; -using System.Security.Cryptography; -using System.Text.RegularExpressions; -using System.Threading; -using System.Threading.Tasks; -using System.Windows; -using CefSharp; -using EmbedIO; -using Pixeval.Data.Web; -using Pixeval.Data.Web.Delegation; -using Pixeval.Data.Web.Protocol; -using Pixeval.Data.Web.Request; -using Pixeval.Objects.Exceptions; -using Pixeval.Objects.Generic; -using Pixeval.Objects.I18n; -using Pixeval.Objects.Primitive; -using Pixeval.Objects.Web; -using Pixeval.Persisting.WebApi; -using Pixeval.UI; -using Refit; - -namespace Pixeval.Persisting -{ - /// - /// A helper class to process the Pixiv authentication - /// - public class Authentication - { - private const string ClientHash = "28c1fdd170a5204386cb1313c7077b34f83e4aaf4aa829ce78c231e05b0bae2c"; - - private static string UtcTimeNow => DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss+00:00"); - - /// - /// App-API authentication process using account and password - /// - /// account - /// password - /// - public static async Task AppApiAuthenticate(string name, string pwd) - { - var time = UtcTimeNow; - var hash = (time + ClientHash).Hash(); - - try - { - var token = await RestService.For(HttpClientFactory.PixivApi(ProtocolBase.OAuthBaseUrl, true).Apply(h => h.Timeout = TimeSpan.FromSeconds(10))).GetTokenByPassword(new PasswordTokenRequest {Name = name, Password = pwd}, time, hash); - Session.Current = Session.Parse(pwd, token); - } - catch (TaskCanceledException) - { - throw new AuthenticateFailedException(AkaI18N.AppApiAuthenticateTimeout); - } - } - - /// - /// App-API authentication process using specified refresh token - /// - /// refresh token - /// - public static async Task AppApiAuthenticate(string refreshToken) - { - try - { - var token = await RestService.For(HttpClientFactory.PixivApi(ProtocolBase.OAuthBaseUrl, true).Apply(h => h.Timeout = TimeSpan.FromSeconds(10))).RefreshToken(new RefreshTokenRequest {RefreshToken = refreshToken}); - Session.Current = Session.Parse(Session.Current.Password, token); - } - catch (TaskCanceledException) - { - throw new AuthenticateFailedException(AkaI18N.AppApiAuthenticateTimeout); - } - } - - /// - /// Authentication process to pixiv web api, which is driven by - /// CefSharp - /// This method is for login usage only, USE AT YOUR OWN RISK - /// - /// user name - /// user password - /// - public static async Task WebApiAuthenticate(string name, string pwd) - { - // create x.509 certificate object for intercepting https traffic, USE AT YOUR OWN RISK - var certificate = await CertificateManager.GetFakeServerCertificate(); - // create https proxy server for intercepting and forwarding https traffic - using var proxyServer = HttpsProxyServer.Create("127.0.0.1", AppContext.ProxyPort, new PixivApiDnsResolver().Lookup()[0].ToString(), certificate); - // create pac file server for providing the proxy-auto-configuration file, - // which is driven by EmbedIO, this is because CefSharp do not accept file uri - using var pacServer = PacFileServer.Create("127.0.0.1", AppContext.PacPort); - pacServer.Start(); - var chrome = SignIn.Instance.ChromiumWebBrowser; - const string loginUrl = "https://accounts.pixiv.net/login"; - chrome.Address = loginUrl; - chrome.FrameLoadEnd += (sender, args) => - { - // when the login page is loaded, we will execute the following js snippet - // which is going to fill and submit the form - if (args.Url == loginUrl) - // ReSharper disable once AccessToDisposedClosure - chrome.ExecuteScriptAsync($@" - var container_login = document.getElementById('container-login'); - var fields = container_login.getElementsByClassName('input-field'); - var account = fields[0].getElementsByTagName('input')[0]; - var password = fields[1].getElementsByTagName('input')[0]; - account.value = '{name}'; - password.value = '{pwd}'; - document.getElementById('container-login').getElementsByClassName('signup-form__submit')[0].click(); - "); - }; -#pragma warning disable 4014 - var cancellationTokenSource = new CancellationTokenSource(); - Task.Run(async () => - { - // ReSharper disable AccessToDisposedClosure - while (!cancellationTokenSource.Token.IsCancellationRequested) - { - await Task.Delay(1000, cancellationTokenSource.Token); - var src = await chrome.Dispatcher.Invoke(async () => - { - if (chrome.WebBrowser != null) return await chrome.WebBrowser.GetSourceAsync(); - return ""; - }); - if (src.Contains("error-msg-list__item")) - { - cancellationTokenSource.Cancel(); - chrome.Dispatcher.Invoke(() => - { - MessageBox.Show(AkaI18N.ThisLoginSessionRequiresRecaptcha); - SignIn.Instance.BrowserDialog.IsOpen = true; - }); - } - } - }, cancellationTokenSource.Token); -#pragma warning restore 4014 - - // polling to check we have got the correct Cookie, which names PHPSESSID and - // has a form like "numbers_hash" - static bool PixivCookieRecorded(Cookie cookie) - { - return Regex.IsMatch(cookie.Domain, @".*\.pixiv\.net") && cookie.Name == "PHPSESSID" && Regex.IsMatch(cookie.Value, @"\d+_.*"); - } - - // create an asynchronous polling task while the authenticate process is running, - // it will check the Cookie - await chrome.AwaitAsync(async c => - { - var visitor = new TaskCookieVisitor(); - Cef.GetGlobalCookieManager().VisitAllCookies(visitor); - return (await visitor.Task).Any(PixivCookieRecorded); - }, 500, TimeSpan.FromMinutes(3)); - - // check if we have got the Cookie when the time limit is exceeded, return successfully - // if it does, otherwise throw an exception - var completionVisitor = new TaskCookieVisitor(); - Cef.GetGlobalCookieManager().VisitAllCookies(completionVisitor); - - chrome.Dispose(); - cancellationTokenSource.Cancel(); - SignIn.Instance.BrowserDialog.CurrentSession?.Close(); - // finalizing objects and save the cookie to user identity - if ((await completionVisitor.Task).FirstOrDefault(PixivCookieRecorded) is { } cookie) - { - Session.Current ??= new Session(); - Session.Current.PhpSessionId = cookie.Value; - Session.Current.CookieCreation = cookie.Creation.ToLocalTime(); - return; - } - - throw new AuthenticateFailedException(AkaI18N.WebApiAuthenticateTimeout); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Persisting/Session.cs b/src/Pixeval/Persisting/Session.cs deleted file mode 100644 index 89804756..00000000 --- a/src/Pixeval/Persisting/Session.cs +++ /dev/null @@ -1,232 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.IO; -using System.Net; -using System.Text; -using System.Threading.Tasks; -using AdysTech.CredentialManager; -using Newtonsoft.Json; -using Pixeval.Data.Web.Response; -using Pixeval.Objects.Primitive; - -namespace Pixeval.Persisting -{ - /// - /// A class which represents current session. etc. - /// - public class Session - { - /// - /// Global session, contains both app-API and web-API - /// - public static Session Current; - - /// - /// User's display name of Pixiv - /// - public string Name { get; set; } - - /// - /// AccessToken expiration - /// - public DateTime ExpireIn { get; set; } - - /// - /// The OAuth AccessToken of the session, which is the most important field - /// - public string AccessToken { get; set; } - - /// - /// The OAuth RefreshToken of the session, which is used to refresh the session - /// - public string RefreshToken { get; set; } - - /// - /// Avatar url of the current user - /// - public string AvatarUrl { get; set; } - - /// - /// Pixiv ID of current user - /// - public string Id { get; set; } - - /// - /// MailAddress of current user, it is also the login account, managed by CredentialManager - /// - [JsonIgnore] - public string MailAddress { get; set; } - - /// - /// Account of current user, be aware not to mix it up with MailAddress - /// - public string Account { get; set; } - - /// - /// Password of current user, managed by CredentialManager - /// - [JsonIgnore] - public string Password { get; set; } - - /// - /// A.k.a PHPSESSID(Cookie), used by web-API - /// - public string PhpSessionId { get; set; } - - /// - /// The creation date of the PhpSessionId - /// - public DateTime CookieCreation { get; set; } - - /// - /// Indicate whether the accounts is pixiv premium - /// - public bool IsPremium { get; set; } - - /// - /// Parse a to an - /// - /// password - /// to be parsed - /// - public static Session Parse(string password, TokenResponse token) - { - var response = token.ToResponse; - return new Session - { - Name = response.User.Name, - ExpireIn = DateTime.Now + TimeSpan.FromSeconds(response.ExpiresIn), - AccessToken = response.AccessToken, - RefreshToken = response.RefreshToken, - AvatarUrl = response.User.ProfileImageUrls.Px170X170, - Id = response.User.Id.ToString(), - MailAddress = response.User.MailAddress, - Account = response.User.Account, - Password = password, - PhpSessionId = Current?.PhpSessionId, - CookieCreation = Current?.CookieCreation ?? default, - IsPremium = token.ToResponse.User.IsPremium - }; - } - - public override string ToString() - { - return this.ToJson(); - } - - /// - /// Save the identity object to local - /// - /// - public async Task Store() - { - await File.WriteAllTextAsync(Path.Combine(AppContext.ConfFolder, AppContext.ConfigurationFileName), ToString()); - CredentialManager.SaveCredentials(AppContext.AppIdentifier, new NetworkCredential(MailAddress, Password)); - } - - /// - /// Load the identity object from local - /// - /// - public static async Task Restore() - { - Current = (await File.ReadAllTextAsync(Path.Combine(AppContext.ConfFolder, AppContext.ConfigurationFileName), Encoding.UTF8)).FromJson(); - var credential = CredentialManager.GetCredentials(AppContext.AppIdentifier); - Current.MailAddress = credential.UserName; - Current.Password = credential.Password; - } - - /// - /// Inspect the configuration file are present - /// - /// - public static bool ConfExists() - { - var path = Path.Combine(AppContext.ConfFolder, AppContext.ConfigurationFileName); - return File.Exists(path) && new FileInfo(path).Length != 0 && CredentialManager.GetCredentials(AppContext.AppIdentifier) != null; - } - - /// - /// Check if the app-API session need to be refresh, we just simply compare two - /// - /// app-API session - /// true if needed - public static bool AppApiRefreshRequired(Session identity) - { - return identity == null || identity.AccessToken.IsNullOrEmpty() || identity.ExpireIn == default || identity.ExpireIn <= DateTime.Now; - } - - /// - /// Check if the web-Api session need to be refresh, the refreshing policy checks if the cookie has - /// been created for 7 days - /// - /// web-API session - /// true if needed - public static bool WebApiRefreshRequired(Session identity) - { - return identity == null || identity.PhpSessionId.IsNullOrEmpty() || identity.CookieCreation == default || (DateTime.Now - identity.CookieCreation).Days >= 7; - } - - /// - /// Refresh the session if required, it is composed of two sections, app-API login - /// and web-API login, each section has its own expiration check, and both two sections - /// are invoked separately, we will only refresh the required section - /// - /// - public static async Task RefreshIfRequired() - { - if (Current == null) await Restore(); - - // refresh through app-API - static async Task RefreshAppApi() - { - if (AppApiRefreshRequired(Current)) - { - // we'd prefer use refresh token - if (Current?.RefreshToken.IsNullOrEmpty() is true) - await Authentication.AppApiAuthenticate(Current?.MailAddress, Current?.Password); - else - await Authentication.AppApiAuthenticate(Current?.RefreshToken); - } - } - - // refresh through web-API - static async Task RefreshWebApi() - { - if (WebApiRefreshRequired(Current)) await Authentication.WebApiAuthenticate(Current?.MailAddress, Current?.Password); - } - - // wait for both two sections to be complete - await Task.WhenAll(RefreshAppApi(), RefreshWebApi()); - } - - /// - /// clear the session and user identity, this action will remove the persisting data - /// - public static void Clear() - { - if (File.Exists(Path.Combine(AppContext.ConfFolder, AppContext.ConfigurationFileName))) File.Delete(Path.Combine(AppContext.ConfFolder, AppContext.ConfigurationFileName)); - if (CredentialManager.GetCredentials(AppContext.AppIdentifier) != null) CredentialManager.RemoveCredentials(AppContext.AppIdentifier); - Current = new Session(); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Persisting/Settings.cs b/src/Pixeval/Persisting/Settings.cs deleted file mode 100644 index 1f60edda..00000000 --- a/src/Pixeval/Persisting/Settings.cs +++ /dev/null @@ -1,159 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading.Tasks; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; -using Pixeval.Core; -using Pixeval.Objects.Primitive; -using PropertyChanged; - -namespace Pixeval.Persisting -{ - /// - /// A class represents user preference - /// - [AddINotifyPropertyChangedInterface] - public class Settings - { - public static Settings Global = new Settings(); - - private string _downloadLocation = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures); - - /// - /// Insert illustration to the sorted list, order by it's Bookmark property - /// - public bool SortOnInserting { get; set; } - - /// - /// The minimum bookmark to be filter - /// - public int MinBookmark { get; set; } = 1; - - /// - /// Determines whether Pixeval should recommend illustrators or not - /// - public bool RecommendIllustrator { get; set; } - - /// - /// The default download location - /// - public string DownloadLocation - { - get => _downloadLocation.IsNullOrEmpty() ? Environment.GetFolderPath(Environment.SpecialFolder.MyPictures) : _downloadLocation; - set => _downloadLocation = value; - } - - /// - /// Indicate the way to match tags - /// - [JsonConverter(typeof(StringEnumConverter))] - public SearchTagMatchOption TagMatchOption { get; set; } = SearchTagMatchOption.PartialMatchForTags; - - /// - /// Specify the localization culture - /// - public string Culture { get; set; } = "zh-cn"; - - /// - /// How many pages need to be queried once, minimum is 1, maximum is 10 - /// - public int QueryPages { get; set; } = 1; - - /// - /// The page number of the query start - /// - public int QueryStart { get; set; } = 1; - - /// - /// Determines whether Pixeval should use direct connect(bypass SNI) - /// - public bool DirectConnect { get; set; } - - /// - /// The spotlight page number of the query start - /// - public int SpotlightQueryStart { get; set; } = 1; - - /// - /// Tags to be exclude - /// - public ISet ExcludeTag { get; set; } = new HashSet(); - - /// - /// Tags to be include - /// - public ISet IncludeTag { get; set; } = new HashSet(); - - public bool CreateNewFolderWhenDownloadFromUser { get; set; } - - public override string ToString() - { - return this.ToJson(); - } - - /// - /// Save current settings to local - /// - /// - public async Task Store() - { - await File.WriteAllTextAsync(Path.Combine(AppContext.SettingsFolder, "settings.json"), Global.ToString()); - } - - /// - /// Load settings from local - /// - /// - public static async Task Restore() - { - if (File.Exists(Path.Combine(AppContext.SettingsFolder, "settings.json"))) - Global = (await File.ReadAllTextAsync(Path.Combine(AppContext.SettingsFolder, "settings.json"))).FromJson(); - else - Initialize(); - } - - /// - /// Initialize the default value of settings - /// - public static void Initialize() - { - if (File.Exists(Path.Combine(AppContext.SettingsFolder, "settings.json"))) File.Delete(Path.Combine(AppContext.SettingsFolder, "settings.json")); - - Global._downloadLocation = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures); - Global.DownloadLocation = string.Empty; - Global.SortOnInserting = false; - Global.IncludeTag = new HashSet(); - Global.ExcludeTag = new HashSet(); - Global.DirectConnect = false; - Global.MinBookmark = 0; - Global.QueryPages = 1; - Global.QueryStart = 1; - Global.SpotlightQueryStart = 1; - Global.RecommendIllustrator = false; - Global.CreateNewFolderWhenDownloadFromUser = false; - Global.TagMatchOption = SearchTagMatchOption.PartialMatchForTags; - Global.Culture = "zh-cn"; - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Persisting/WebApi/BypassProxyRequestHandler.cs b/src/Pixeval/Persisting/WebApi/BypassProxyRequestHandler.cs deleted file mode 100644 index ed48d0d5..00000000 --- a/src/Pixeval/Persisting/WebApi/BypassProxyRequestHandler.cs +++ /dev/null @@ -1,41 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using CefSharp; -using CefSharp.Handler; - -namespace Pixeval.Persisting.WebApi -{ - public class BypassProxyRequestHandler : RequestHandler - { - public static readonly BypassProxyRequestHandler Instance = new BypassProxyRequestHandler(); - - protected override IResourceRequestHandler GetResourceRequestHandler(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool isNavigation, bool isDownload, string requestInitiator, ref bool disableDefaultHandling) - { - return new BypassProxyResourceRequestHandler(); - } - - protected override bool OnCertificateError(IWebBrowser chromiumWebBrowser, IBrowser browser, CefErrorCode errorCode, string requestUrl, ISslInfo sslInfo, IRequestCallback callback) - { - callback.Continue(true); - return true; - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Persisting/WebApi/BypassProxyResourceRequestHandler.cs b/src/Pixeval/Persisting/WebApi/BypassProxyResourceRequestHandler.cs deleted file mode 100644 index 37d01ca2..00000000 --- a/src/Pixeval/Persisting/WebApi/BypassProxyResourceRequestHandler.cs +++ /dev/null @@ -1,40 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using CefSharp; -using CefSharp.Handler; - -namespace Pixeval.Persisting.WebApi -{ - public class BypassProxyResourceRequestHandler : ResourceRequestHandler - { - protected override CefReturnValue OnBeforeResourceLoad(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IRequestCallback callback) - { - if (request.Url.Contains("Twitter", StringComparison.Ordinal) || request.Url.EndsWith("png") || request.Url.EndsWith("jpg")) - { - callback.Continue(false); - return CefReturnValue.Cancel; - } - - return CefReturnValue.Continue; - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Persisting/WebApi/CertificateManager.cs b/src/Pixeval/Persisting/WebApi/CertificateManager.cs deleted file mode 100644 index 68086075..00000000 --- a/src/Pixeval/Persisting/WebApi/CertificateManager.cs +++ /dev/null @@ -1,133 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.IO; -using System.Security.Cryptography.X509Certificates; -using System.Threading.Tasks; -using System.Windows; -using Pixeval.Objects.I18n; -using Pixeval.Objects.Primitive; - -namespace Pixeval.Persisting.WebApi -{ - /// - /// This class is for web-API login usage only, the private key of the CA Root Certificate - /// is personally guaranteed to be absolutely secure. However, if you see any warning or any - /// website is using the certificate which is issued by "Dylech30th Do Not Trust Certificate - /// Authority", PLEASE NEVER TRUST THEM. Suppress this warning may lead into - /// a Man-In-The-Middle attack, and I personally will not be responsible for any consequence - /// that caused by suppressing this warning. USE AT YOUR OWN RISK - /// - public class CertificateManager - { - private static X509Certificate2 _fakeCa; - private static X509Certificate2 _serverCert; - - private readonly X509Certificate2 _cert; - - /// - /// Create a with specified - /// - /// certificate to be managed - public CertificateManager(X509Certificate2 certificate) - { - _cert = certificate; - } - - /// - /// Get the fake CA root certificate of Pixeval - /// - /// - public static async Task GetFakeCaRootCertificate() - { - if (_fakeCa != null) return _fakeCa; - if (Application.GetResourceStream(new Uri("pack://application:,,,/Pixeval;component/Resources/pixeval_ca.cer")) is { } streamResource) - { - await using (streamResource.Stream) - { - _fakeCa = new X509Certificate2(await streamResource.Stream.ToBytes()); - } - - return _fakeCa; - } - - throw new FileNotFoundException(AkaI18N.CannotFindSpecifiedCertificate); - } - - /// - /// Get the server certificate of Pixeval - /// - /// - public static async Task GetFakeServerCertificate() - { - if (_serverCert != null) return _serverCert; - if (Application.GetResourceStream(new Uri("pack://application:,,,/Pixeval;component/Resources/pixeval_server_cert.pfx")) is { } streamResource) - { - await using (streamResource.Stream) - { - _serverCert = new X509Certificate2(await streamResource.Stream.ToBytes(), "pixeval", X509KeyStorageFlags.UserKeySet); - } - - return _serverCert; - } - - throw new FileNotFoundException(AkaI18N.CannotFindSpecifiedCertificate); - } - - /// - /// Install a certificate to specified location - /// - /// - /// - public void Install(StoreName storeName, StoreLocation storeLocation) - { - using var store = new X509Store(storeName, storeLocation); - store.Open(OpenFlags.ReadWrite); - store.Add(_cert); - } - - /// - /// Uninstall a certificate from specified location - /// - /// - /// - public void Uninstall(StoreName storeName, StoreLocation storeLocation) - { - using var store = new X509Store(storeName, storeLocation); - store.Open(OpenFlags.ReadWrite); - store.Remove(_cert); - } - - /// - /// Query a certificate from specified location - /// - /// - /// - /// true if the certificate is present - public bool Query(StoreName storeName, StoreLocation storeLocation) - { - using var store = new X509Store(storeName, storeLocation); - store.Open(OpenFlags.ReadOnly); - if (_cert.Thumbprint == null) return false; - return store.Certificates.Find(X509FindType.FindByThumbprint, _cert.Thumbprint, true).Count > 0; - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Pixeval.csproj b/src/Pixeval/Pixeval.csproj deleted file mode 100644 index f3308e73..00000000 --- a/src/Pixeval/Pixeval.csproj +++ /dev/null @@ -1,78 +0,0 @@ - - - - WinExe - netcoreapp3.1 - true - win-x64 - A Strong, Fast and Flexible Pixiv Client - false - Pixeval.App - Resources\pxlogo.ico - false - - x64 - $(NoWarn);NU1701 - - - - Off - app.manifest - - - - - - - - - - - true - - - true - - - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Pixeval/Properties/Annotations.cs b/src/Pixeval/Properties/Annotations.cs deleted file mode 100644 index c1f66601..00000000 --- a/src/Pixeval/Properties/Annotations.cs +++ /dev/null @@ -1,1461 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; - -// ReSharper disable InheritdocConsiderUsage - -#pragma warning disable 1591 -// ReSharper disable UnusedMember.Global -// ReSharper disable MemberCanBePrivate.Global -// ReSharper disable UnusedAutoPropertyAccessor.Global -// ReSharper disable IntroduceOptionalParameters.Global -// ReSharper disable MemberCanBeProtected.Global -// ReSharper disable InconsistentNaming - -namespace Pixeval.Annotations -{ - /// - /// Indicates that the value of the marked element could be null sometimes, - /// so checking for null is required before its usage. - /// - /// - /// - /// [CanBeNull] object Test() => null; - /// - /// void UseTest() { - /// var p = Test(); - /// var s = p.ToString(); // Warning: Possible 'System.NullReferenceException' - /// } - /// - /// - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.GenericParameter)] - public sealed class CanBeNullAttribute : Attribute - { - } - - /// - /// Indicates that the value of the marked element can never be null. - /// - /// - /// - /// [NotNull] object Foo() { - /// return null; // Warning: Possible 'null' assignment - /// } - /// - /// - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.GenericParameter)] - public sealed class NotNullAttribute : Attribute - { - } - - /// - /// Can be applied to symbols of types derived from IEnumerable as well as to symbols of Task - /// and Lazy classes to indicate that the value of a collection item, of the Task.Result property - /// or of the Lazy.Value property can never be null. - /// - /// - /// - /// public void Foo([ItemNotNull]List<string> books) - /// { - /// foreach (var book in books) { - /// if (book != null) // Warning: Expression is always true - /// Console.WriteLine(book.ToUpper()); - /// } - /// } - /// - /// - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Delegate | AttributeTargets.Field)] - public sealed class ItemNotNullAttribute : Attribute - { - } - - /// - /// Can be applied to symbols of types derived from IEnumerable as well as to symbols of Task - /// and Lazy classes to indicate that the value of a collection item, of the Task.Result property - /// or of the Lazy.Value property can be null. - /// - /// - /// - /// public void Foo([ItemCanBeNull]List<string> books) - /// { - /// foreach (var book in books) - /// { - /// // Warning: Possible 'System.NullReferenceException' - /// Console.WriteLine(book.ToUpper()); - /// } - /// } - /// - /// - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Delegate | AttributeTargets.Field)] - public sealed class ItemCanBeNullAttribute : Attribute - { - } - - /// - /// Indicates that the marked method builds string by the format pattern and (optional) arguments. - /// The parameter, which contains the format string, should be given in constructor. The format string - /// should be in -like form. - /// - /// - /// - /// [StringFormatMethod("message")] - /// void ShowError(string message, params object[] args) { /* do something */ } - /// - /// void Foo() { - /// ShowError("Failed: {0}"); // Warning: Non-existing argument in format string - /// } - /// - /// - [AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Delegate)] - public sealed class StringFormatMethodAttribute : Attribute - { - /// - /// Specifies which parameter of an annotated method should be treated as the format string - /// - public StringFormatMethodAttribute([NotNull] - string formatParameterName) - { - FormatParameterName = formatParameterName; - } - - [NotNull] - public string FormatParameterName { get; } - } - - /// - /// Use this annotation to specify a type that contains static or const fields - /// with values for the annotated property/field/parameter. - /// The specified type will be used to improve completion suggestions. - /// - /// - /// - /// namespace TestNamespace - /// { - /// public class Constants - /// { - /// public static int INT_CONST = 1; - /// public const string STRING_CONST = "1"; - /// } - /// - /// public class Class1 - /// { - /// [ValueProvider("TestNamespace.Constants")] public int myField; - /// public void Foo([ValueProvider("TestNamespace.Constants")] string str) { } - /// - /// public void Test() - /// { - /// Foo(/*try completion here*/);// - /// myField = /*try completion here*/ - /// } - /// } - /// } - /// - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)] - public sealed class ValueProviderAttribute : Attribute - { - public ValueProviderAttribute([NotNull] - string name) - { - Name = name; - } - - [NotNull] - public string Name { get; } - } - - /// - /// Indicates that the integral value falls into the specified interval. - /// It's allowed to specify multiple non-intersecting intervals. - /// Values of interval boundaries are inclusive. - /// - /// - /// - /// void Foo([ValueRange(0, 100)] int value) { - /// if (value == -1) { // Warning: Expression is always 'false' - /// ... - /// } - /// } - /// - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Method | AttributeTargets.Delegate, AllowMultiple = true)] - public sealed class ValueRangeAttribute : Attribute - { - public ValueRangeAttribute(long from, long to) - { - From = from; - To = to; - } - - public ValueRangeAttribute(ulong from, ulong to) - { - From = from; - To = to; - } - - public ValueRangeAttribute(long value) - { - From = To = value; - } - - public ValueRangeAttribute(ulong value) - { - From = To = value; - } - - public object From { get; } - public object To { get; } - } - - /// - /// Indicates that the integral value never falls below zero. - /// - /// - /// - /// void Foo([NonNegativeValue] int value) { - /// if (value == -1) { // Warning: Expression is always 'false' - /// ... - /// } - /// } - /// - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Method | AttributeTargets.Delegate)] - public sealed class NonNegativeValueAttribute : Attribute - { - } - - /// - /// Indicates that the function argument should be a string literal and match one - /// of the parameters of the caller function. For example, ReSharper annotates - /// the parameter of . - /// - /// - /// - /// void Foo(string param) { - /// if (param == null) - /// throw new ArgumentNullException("par"); // Warning: Cannot resolve symbol - /// } - /// - /// - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class InvokerParameterNameAttribute : Attribute - { - } - - /// - /// Indicates that the method is contained in a type that implements - /// System.ComponentModel.INotifyPropertyChanged interface and this method - /// is used to notify that some property value changed. - /// - /// - /// The method should be non-static and conform to one of the supported signatures: - /// - /// - /// NotifyChanged(string) - /// - /// - /// NotifyChanged(params string[]) - /// - /// - /// NotifyChanged{T}(Expression{Func{T}}) - /// - /// - /// NotifyChanged{T,U}(Expression{Func{T,U}}) - /// - /// - /// SetProperty{T}(ref T, T, string) - /// - /// - /// - /// - /// - /// public class Foo : INotifyPropertyChanged { - /// public event PropertyChangedEventHandler PropertyChanged; - /// - /// [NotifyPropertyChangedInvocator] - /// protected virtual void NotifyChanged(string propertyName) { ... } - /// - /// string _name; - /// - /// public string Name { - /// get { return _name; } - /// set { _name = value; NotifyChanged("LastName"); /* Warning */ } - /// } - /// } - /// - /// Examples of generated notifications: - /// - /// - /// NotifyChanged("Property") - /// - /// - /// NotifyChanged(() => Property) - /// - /// - /// NotifyChanged((VM x) => x.Property) - /// - /// - /// SetProperty(ref myField, value, "Property") - /// - /// - /// - [AttributeUsage(AttributeTargets.Method)] - public sealed class NotifyPropertyChangedInvocatorAttribute : Attribute - { - public NotifyPropertyChangedInvocatorAttribute() - { - } - - public NotifyPropertyChangedInvocatorAttribute([NotNull] - string parameterName) - { - ParameterName = parameterName; - } - - [CanBeNull] - public string ParameterName { get; } - } - - /// - /// Describes dependency between method input and output. - /// - /// - ///

Function Definition Table syntax:

- /// - /// FDT ::= FDTRow [;FDTRow]* - /// FDTRow ::= Input => Output | Output <= Input - /// Input ::= ParameterName: Value [, Input]* - /// Output ::= [ParameterName: Value]* {halt|stop|void|nothing|Value} - /// Value ::= true | false | null | notnull | canbenull - /// - /// If the method has a single input parameter, its name could be omitted.
- /// Using halt (or void/nothing, which is the same) for the method output - /// means that the method doesn't return normally (throws or terminates the process).
- /// Value canbenull is only applicable for output parameters.
- /// You can use multiple [ContractAnnotation] for each FDT row, or use single attribute - /// with rows separated by semicolon. There is no notion of order rows, all rows are checked - /// for applicability and applied per each program state tracked by the analysis engine.
- ///
- /// - /// - /// - /// - /// [ContractAnnotation("=> halt")] - /// public void TerminationMethod() - /// - /// - /// - /// - /// [ContractAnnotation("null <= param:null")] // reverse condition syntax - /// public string GetName(string surname) - /// - /// - /// - /// - /// [ContractAnnotation("s:null => true")] - /// public bool IsNullOrEmpty(string s) // string.IsNullOrEmpty() - /// - /// - /// - /// - /// // A method that returns null if the parameter is null, - /// // and not null if the parameter is not null - /// [ContractAnnotation("null => null; notnull => notnull")] - /// public object Transform(object data) - /// - /// - /// - /// - /// [ContractAnnotation("=> true, result: notnull; => false, result: null")] - /// public bool TryParse(string s, out Person result) - /// - /// - /// - /// - [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] - public sealed class ContractAnnotationAttribute : Attribute - { - public ContractAnnotationAttribute([NotNull] - string contract) : this(contract, false) - { - } - - public ContractAnnotationAttribute([NotNull] - string contract, bool forceFullStates) - { - Contract = contract; - ForceFullStates = forceFullStates; - } - - [NotNull] - public string Contract { get; } - - public bool ForceFullStates { get; } - } - - /// - /// Indicates whether the marked element should be localized. - /// - /// - /// - /// [LocalizationRequiredAttribute(true)] - /// class Foo { - /// string str = "my string"; // Warning: Localizable string - /// } - /// - /// - [AttributeUsage(AttributeTargets.All)] - public sealed class LocalizationRequiredAttribute : Attribute - { - public LocalizationRequiredAttribute() : this(true) - { - } - - public LocalizationRequiredAttribute(bool required) - { - Required = required; - } - - public bool Required { get; } - } - - /// - /// Indicates that the value of the marked type (or its derivatives) - /// cannot be compared using '==' or '!=' operators and Equals() - /// should be used instead. However, using '==' or '!=' for comparison - /// with null is always permitted. - /// - /// - /// - /// [CannotApplyEqualityOperator] - /// class NoEquality { } - /// - /// class UsesNoEquality { - /// void Test() { - /// var ca1 = new NoEquality(); - /// var ca2 = new NoEquality(); - /// if (ca1 != null) { // OK - /// bool condition = ca1 == ca2; // Warning - /// } - /// } - /// } - /// - /// - [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct)] - public sealed class CannotApplyEqualityOperatorAttribute : Attribute - { - } - - /// - /// When applied to a target attribute, specifies a requirement for any type marked - /// with the target attribute to implement or inherit specific type or types. - /// - /// - /// - /// [BaseTypeRequired(typeof(IComponent)] // Specify requirement - /// class ComponentAttribute : Attribute { } - /// - /// [Component] // ComponentAttribute requires implementing IComponent interface - /// class MyComponent : IComponent { } - /// - /// - [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] - [BaseTypeRequired(typeof(Attribute))] - public sealed class BaseTypeRequiredAttribute : Attribute - { - public BaseTypeRequiredAttribute([NotNull] - Type baseType) - { - BaseType = baseType; - } - - [NotNull] - public Type BaseType { get; } - } - - /// - /// Indicates that the marked symbol is used implicitly (e.g. via reflection, in external library), - /// so this symbol will not be reported as unused (as well as by other usage inspections). - /// - [AttributeUsage(AttributeTargets.All)] - public sealed class UsedImplicitlyAttribute : Attribute - { - public UsedImplicitlyAttribute() : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) - { - } - - public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags) : this(useKindFlags, ImplicitUseTargetFlags.Default) - { - } - - public UsedImplicitlyAttribute(ImplicitUseTargetFlags targetFlags) : this(ImplicitUseKindFlags.Default, targetFlags) - { - } - - public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) - { - UseKindFlags = useKindFlags; - TargetFlags = targetFlags; - } - - public ImplicitUseKindFlags UseKindFlags { get; } - - public ImplicitUseTargetFlags TargetFlags { get; } - } - - /// - /// Can be applied to attributes, type parameters, and parameters of a type assignable from - /// . - /// When applied to an attribute, the decorated attribute behaves the same as . - /// When applied to a type parameter or to a parameter of type , indicates that the - /// corresponding type - /// is used implicitly. - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.GenericParameter | AttributeTargets.Parameter)] - public sealed class MeansImplicitUseAttribute : Attribute - { - public MeansImplicitUseAttribute() : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) - { - } - - public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags) : this(useKindFlags, ImplicitUseTargetFlags.Default) - { - } - - public MeansImplicitUseAttribute(ImplicitUseTargetFlags targetFlags) : this(ImplicitUseKindFlags.Default, targetFlags) - { - } - - public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) - { - UseKindFlags = useKindFlags; - TargetFlags = targetFlags; - } - - [UsedImplicitly] - public ImplicitUseKindFlags UseKindFlags { get; } - - [UsedImplicitly] - public ImplicitUseTargetFlags TargetFlags { get; } - } - - /// - /// Specify the details of implicitly used symbol when it is marked - /// with or . - /// - [Flags] - public enum ImplicitUseKindFlags - { - Default = Access | Assign | InstantiatedWithFixedConstructorSignature, - - /// Only entity marked with attribute considered used. - Access = 1, - - /// Indicates implicit assignment to a member. - Assign = 2, - - /// - /// Indicates implicit instantiation of a type with fixed constructor signature. - /// That means any unused constructor parameters won't be reported as such. - /// - InstantiatedWithFixedConstructorSignature = 4, - - /// Indicates implicit instantiation of a type. - InstantiatedNoFixedConstructorSignature = 8 - } - - /// - /// Specify what is considered to be used implicitly when marked - /// with or . - /// - [Flags] - public enum ImplicitUseTargetFlags - { - Default = Itself, Itself = 1, - - /// Members of entity marked with attribute are considered used. - Members = 2, - - /// Inherited entities are considered used. - WithInheritors = 4, - - /// Entity marked with attribute and all its members considered used. - WithMembers = Itself | Members - } - - /// - /// This attribute is intended to mark publicly available API - /// which should not be removed and so is treated as used. - /// - [MeansImplicitUse(ImplicitUseTargetFlags.WithMembers)] - [AttributeUsage(AttributeTargets.All, Inherited = false)] - public sealed class PublicAPIAttribute : Attribute - { - public PublicAPIAttribute() - { - } - - public PublicAPIAttribute([NotNull] - string comment) - { - Comment = comment; - } - - [CanBeNull] - public string Comment { get; } - } - - /// - /// Tells code analysis engine if the parameter is completely handled when the invoked method is on stack. - /// If the parameter is a delegate, indicates that delegate is executed while the method is executed. - /// If the parameter is an enumerable, indicates that it is enumerated while the method is executed. - /// - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class InstantHandleAttribute : Attribute - { - } - - /// - /// Indicates that a method does not make any observable state changes. - /// The same as System.Diagnostics.Contracts.PureAttribute. - /// - /// - /// - /// [Pure] int Multiply(int x, int y) => x * y; - /// - /// void M() { - /// Multiply(123, 42); // Warning: Return value of pure method is not used - /// } - /// - /// - [AttributeUsage(AttributeTargets.Method)] - public sealed class PureAttribute : Attribute - { - } - - /// - /// Indicates that the return value of the method invocation must be used. - /// - /// - /// Methods decorated with this attribute (in contrast to pure methods) might change state, - /// but make no sense without using their return value.
- /// Similarly to , this attribute - /// will help detecting usages of the method when the return value in not used. - /// Additionally, you can optionally specify a custom message, which will be used when showing warnings, e.g. - /// [MustUseReturnValue("Use the return value to...")]. - ///
- [AttributeUsage(AttributeTargets.Method)] - public sealed class MustUseReturnValueAttribute : Attribute - { - public MustUseReturnValueAttribute() - { - } - - public MustUseReturnValueAttribute([NotNull] - string justification) - { - Justification = justification; - } - - [CanBeNull] - public string Justification { get; } - } - - /// - /// Indicates the type member or parameter of some type, that should be used instead of all other ways - /// to get the value of that type. This annotation is useful when you have some "context" value evaluated - /// and stored somewhere, meaning that all other ways to get this value must be consolidated with existing one. - /// - /// - /// - /// class Foo { - /// [ProvidesContext] IBarService _barService = ...; - /// - /// void ProcessNode(INode node) { - /// DoSomething(node, node.GetGlobalServices().Bar); - /// // ^ Warning: use value of '_barService' field - /// } - /// } - /// - /// - [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.GenericParameter)] - public sealed class ProvidesContextAttribute : Attribute - { - } - - /// - /// Indicates that a parameter is a path to a file or a folder within a web project. - /// Path can be relative or absolute, starting from web root (~). - /// - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class PathReferenceAttribute : Attribute - { - public PathReferenceAttribute() - { - } - - public PathReferenceAttribute([NotNull] [PathReference] - string basePath) - { - BasePath = basePath; - } - - [CanBeNull] - public string BasePath { get; } - } - - /// - /// An extension method marked with this attribute is processed by code completion - /// as a 'Source Template'. When the extension method is completed over some expression, its source code - /// is automatically expanded like a template at call site. - /// - /// - /// Template method body can contain valid source code and/or special comments starting with '$'. - /// Text inside these comments is added as source code when the template is applied. Template parameters - /// can be used either as additional method parameters or as identifiers wrapped in two '$' signs. - /// Use the attribute to specify macros for parameters. - /// - /// - /// In this example, the 'forEach' method is a source template available over all values - /// of enumerable types, producing ordinary C# 'foreach' statement and placing caret inside block: - /// - /// [SourceTemplate] - /// public static void forEach<T>(this IEnumerable<T> xs) { - /// foreach (var x in xs) { - /// //$ $END$ - /// } - /// } - /// - /// - [AttributeUsage(AttributeTargets.Method)] - public sealed class SourceTemplateAttribute : Attribute - { - } - - /// - /// Allows specifying a macro for a parameter of a source template. - /// - /// - /// You can apply the attribute on the whole method or on any of its additional parameters. The macro expression - /// is defined in the property. When applied on a method, the target - /// template parameter is defined in the property. To apply the macro silently - /// for the parameter, set the property value = -1. - /// - /// - /// Applying the attribute on a source template method: - /// - /// [SourceTemplate, Macro(Target = "item", Expression = "suggestVariableName()")] - /// public static void forEach<T>(this IEnumerable<T> collection) { - /// foreach (var item in collection) { - /// //$ $END$ - /// } - /// } - /// - /// Applying the attribute on a template method parameter: - /// - /// [SourceTemplate] - /// public static void something(this Entity x, [Macro(Expression = "guid()", Editable = -1)] string newguid) { - /// /*$ var $x$Id = "$newguid$" + x.ToString(); - /// x.DoSomething($x$Id); */ - /// } - /// - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method, AllowMultiple = true)] - public sealed class MacroAttribute : Attribute - { - /// - /// Allows specifying a macro that will be executed for a source template - /// parameter when the template is expanded. - /// - [CanBeNull] - public string Expression { get; set; } - - /// - /// Allows specifying which occurrence of the target parameter becomes editable when the template is deployed. - /// - /// - /// If the target parameter is used several times in the template, only one occurrence becomes editable; - /// other occurrences are changed synchronously. To specify the zero-based index of the editable occurrence, - /// use values >= 0. To make the parameter non-editable when the template is expanded, use -1. - /// - public int Editable { get; set; } - - /// - /// Identifies the target parameter of a source template if the - /// is applied on a template method. - /// - [CanBeNull] - public string Target { get; set; } - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] - public sealed class AspMvcAreaMasterLocationFormatAttribute : Attribute - { - public AspMvcAreaMasterLocationFormatAttribute([NotNull] - string format) - { - Format = format; - } - - [NotNull] - public string Format { get; } - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] - public sealed class AspMvcAreaPartialViewLocationFormatAttribute : Attribute - { - public AspMvcAreaPartialViewLocationFormatAttribute([NotNull] - string format) - { - Format = format; - } - - [NotNull] - public string Format { get; } - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] - public sealed class AspMvcAreaViewLocationFormatAttribute : Attribute - { - public AspMvcAreaViewLocationFormatAttribute([NotNull] - string format) - { - Format = format; - } - - [NotNull] - public string Format { get; } - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] - public sealed class AspMvcMasterLocationFormatAttribute : Attribute - { - public AspMvcMasterLocationFormatAttribute([NotNull] - string format) - { - Format = format; - } - - [NotNull] - public string Format { get; } - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] - public sealed class AspMvcPartialViewLocationFormatAttribute : Attribute - { - public AspMvcPartialViewLocationFormatAttribute([NotNull] - string format) - { - Format = format; - } - - [NotNull] - public string Format { get; } - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] - public sealed class AspMvcViewLocationFormatAttribute : Attribute - { - public AspMvcViewLocationFormatAttribute([NotNull] - string format) - { - Format = format; - } - - [NotNull] - public string Format { get; } - } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter - /// is an MVC action. If applied to a method, the MVC action name is calculated - /// implicitly from the context. Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcActionAttribute : Attribute - { - public AspMvcActionAttribute() - { - } - - public AspMvcActionAttribute([NotNull] - string anonymousProperty) - { - AnonymousProperty = anonymousProperty; - } - - [CanBeNull] - public string AnonymousProperty { get; } - } - - /// - /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC area. - /// Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcAreaAttribute : Attribute - { - public AspMvcAreaAttribute() - { - } - - public AspMvcAreaAttribute([NotNull] - string anonymousProperty) - { - AnonymousProperty = anonymousProperty; - } - - [CanBeNull] - public string AnonymousProperty { get; } - } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter is - /// an MVC controller. If applied to a method, the MVC controller name is calculated - /// implicitly from the context. Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcControllerAttribute : Attribute - { - public AspMvcControllerAttribute() - { - } - - public AspMvcControllerAttribute([NotNull] - string anonymousProperty) - { - AnonymousProperty = anonymousProperty; - } - - [CanBeNull] - public string AnonymousProperty { get; } - } - - /// - /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC Master. Use this attribute - /// for custom wrappers similar to System.Web.Mvc.Controller.View(String, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcMasterAttribute : Attribute - { - } - - /// - /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC model type. Use this attribute - /// for custom wrappers similar to System.Web.Mvc.Controller.View(String, Object). - /// - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class AspMvcModelTypeAttribute : Attribute - { - } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter is an MVC - /// partial view. If applied to a method, the MVC partial view name is calculated implicitly - /// from the context. Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.RenderPartialExtensions.RenderPartial(HtmlHelper, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcPartialViewAttribute : Attribute - { - } - - /// - /// ASP.NET MVC attribute. Allows disabling inspections for MVC views within a class or a method. - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] - public sealed class AspMvcSuppressViewErrorAttribute : Attribute - { - } - - /// - /// ASP.NET MVC attribute. Indicates that a parameter is an MVC display template. - /// Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.DisplayExtensions.DisplayForModel(HtmlHelper, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcDisplayTemplateAttribute : Attribute - { - } - - /// - /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC editor template. - /// Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.EditorExtensions.EditorForModel(HtmlHelper, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcEditorTemplateAttribute : Attribute - { - } - - /// - /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC template. - /// Use this attribute for custom wrappers similar to - /// System.ComponentModel.DataAnnotations.UIHintAttribute(System.String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcTemplateAttribute : Attribute - { - } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter - /// is an MVC view component. If applied to a method, the MVC view name is calculated implicitly - /// from the context. Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Controller.View(Object). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcViewAttribute : Attribute - { - } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter - /// is an MVC view component name. - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcViewComponentAttribute : Attribute - { - } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter - /// is an MVC view component view. If applied to a method, the MVC view component view name is default. - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcViewComponentViewAttribute : Attribute - { - } - - /// - /// ASP.NET MVC attribute. When applied to a parameter of an attribute, - /// indicates that this parameter is an MVC action name. - /// - /// - /// - /// [ActionName("Foo")] - /// public ActionResult Login(string returnUrl) { - /// ViewBag.ReturnUrl = Url.Action("Foo"); // OK - /// return RedirectToAction("Bar"); // Error: Cannot resolve action - /// } - /// - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property)] - public sealed class AspMvcActionSelectorAttribute : Attribute - { - } - - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field)] - public sealed class HtmlElementAttributesAttribute : Attribute - { - public HtmlElementAttributesAttribute() - { - } - - public HtmlElementAttributesAttribute([NotNull] - string name) - { - Name = name; - } - - [CanBeNull] - public string Name { get; } - } - - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class HtmlAttributeValueAttribute : Attribute - { - public HtmlAttributeValueAttribute([NotNull] - string name) - { - Name = name; - } - - [NotNull] - public string Name { get; } - } - - /// - /// Razor attribute. Indicates that the marked parameter or method is a Razor section. - /// Use this attribute for custom wrappers similar to - /// System.Web.WebPages.WebPageBase.RenderSection(String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)] - public sealed class RazorSectionAttribute : Attribute - { - } - - /// - /// Indicates how method, constructor invocation, or property access - /// over collection type affects the contents of the collection. - /// Use to specify the access type. - /// - /// - /// Using this attribute only makes sense if all collection methods are marked with this attribute. - /// - /// - /// - /// public class MyStringCollection : List<string> - /// { - /// [CollectionAccess(CollectionAccessType.Read)] - /// public string GetFirstString() - /// { - /// return this.ElementAt(0); - /// } - /// } - /// class Test - /// { - /// public void Foo() - /// { - /// // Warning: Contents of the collection is never updated - /// var col = new MyStringCollection(); - /// string x = col.GetFirstString(); - /// } - /// } - /// - /// - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Property)] - public sealed class CollectionAccessAttribute : Attribute - { - public CollectionAccessAttribute(CollectionAccessType collectionAccessType) - { - CollectionAccessType = collectionAccessType; - } - - public CollectionAccessType CollectionAccessType { get; } - } - - /// - /// Provides a value for the to define - /// how the collection method invocation affects the contents of the collection. - /// - [Flags] - public enum CollectionAccessType - { - /// Method does not use or modify content of the collection. - None = 0, - - /// Method only reads content of the collection but does not modify it. - Read = 1, - - /// Method can change content of the collection but does not add new elements. - ModifyExistingContent = 2, - - /// Method can add new elements to the collection. - UpdatedContent = ModifyExistingContent | 4 - } - - /// - /// Indicates that the marked method is assertion method, i.e. it halts the control flow if - /// one of the conditions is satisfied. To set the condition, mark one of the parameters with - /// attribute. - /// - [AttributeUsage(AttributeTargets.Method)] - public sealed class AssertionMethodAttribute : Attribute - { - } - - /// - /// Indicates the condition parameter of the assertion method. The method itself should be - /// marked by attribute. The mandatory argument of - /// the attribute is the assertion type. - /// - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class AssertionConditionAttribute : Attribute - { - public AssertionConditionAttribute(AssertionConditionType conditionType) - { - ConditionType = conditionType; - } - - public AssertionConditionType ConditionType { get; } - } - - /// - /// Specifies assertion type. If the assertion method argument satisfies the condition, - /// then the execution continues. Otherwise, execution is assumed to be halted. - /// - public enum AssertionConditionType - { - /// Marked parameter should be evaluated to true. - IS_TRUE = 0, - - /// Marked parameter should be evaluated to false. - IS_FALSE = 1, - - /// Marked parameter should be evaluated to null value. - IS_NULL = 2, - - /// Marked parameter should be evaluated to not null value. - IS_NOT_NULL = 3 - } - - /// - /// Indicates that the marked method unconditionally terminates control flow execution. - /// For example, it could unconditionally throw exception. - /// - [Obsolete("Use [ContractAnnotation('=> halt')] instead")] - [AttributeUsage(AttributeTargets.Method)] - public sealed class TerminatesProgramAttribute : Attribute - { - } - - /// - /// Indicates that method is pure LINQ method, with postponed enumeration (like Enumerable.Select, - /// .Where). This annotation allows inference of [InstantHandle] annotation for parameters - /// of delegate type by analyzing LINQ method chains. - /// - [AttributeUsage(AttributeTargets.Method)] - public sealed class LinqTunnelAttribute : Attribute - { - } - - /// - /// Indicates that IEnumerable passed as a parameter is not enumerated. - /// Use this annotation to suppress the 'Possible multiple enumeration of IEnumerable' inspection. - /// - /// - /// - /// static void ThrowIfNull<T>([NoEnumeration] T v, string n) where T : class - /// { - /// // custom check for null but no enumeration - /// } - /// - /// void Foo(IEnumerable<string> values) - /// { - /// ThrowIfNull(values, nameof(values)); - /// var x = values.ToList(); // No warnings about multiple enumeration - /// } - /// - /// - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class NoEnumerationAttribute : Attribute - { - } - - /// - /// Indicates that the marked parameter is a regular expression pattern. - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class RegexPatternAttribute : Attribute - { - } - - /// - /// Prevents the Member Reordering feature from tossing members of the marked class. - /// - /// - /// The attribute must be mentioned in your member reordering patterns. - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.Enum)] - public sealed class NoReorderAttribute : Attribute - { - } - - /// - /// XAML attribute. Indicates the type that has ItemsSource property and should be treated - /// as ItemsControl-derived type, to enable inner items DataContext type resolve. - /// - [AttributeUsage(AttributeTargets.Class)] - public sealed class XamlItemsControlAttribute : Attribute - { - } - - /// - /// XAML attribute. Indicates the property of some BindingBase-derived type, that - /// is used to bind some item of ItemsControl-derived type. This annotation will - /// enable the DataContext type resolve for XAML bindings for such properties. - /// - /// - /// Property should have the tree ancestor of the ItemsControl type or - /// marked with the attribute. - /// - [AttributeUsage(AttributeTargets.Property)] - public sealed class XamlItemBindingOfItemsControlAttribute : Attribute - { - } - - /// - /// XAML attribute. Indicates the property of some Style-derived type, that - /// is used to style items of ItemsControl-derived type. This annotation will - /// enable the DataContext type resolve for XAML bindings for such properties. - /// - /// - /// Property should have the tree ancestor of the ItemsControl type or - /// marked with the attribute. - /// - [AttributeUsage(AttributeTargets.Property)] - public sealed class XamlItemStyleOfItemsControlAttribute : Attribute - { - } - - [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] - public sealed class AspChildControlTypeAttribute : Attribute - { - public AspChildControlTypeAttribute([NotNull] - string tagName, [NotNull] - Type controlType) - { - TagName = tagName; - ControlType = controlType; - } - - [NotNull] - public string TagName { get; } - - [NotNull] - public Type ControlType { get; } - } - - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)] - public sealed class AspDataFieldAttribute : Attribute - { - } - - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)] - public sealed class AspDataFieldsAttribute : Attribute - { - } - - [AttributeUsage(AttributeTargets.Property)] - public sealed class AspMethodPropertyAttribute : Attribute - { - } - - [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] - public sealed class AspRequiredAttributeAttribute : Attribute - { - public AspRequiredAttributeAttribute([NotNull] - string attribute) - { - Attribute = attribute; - } - - [NotNull] - public string Attribute { get; } - } - - [AttributeUsage(AttributeTargets.Property)] - public sealed class AspTypePropertyAttribute : Attribute - { - public AspTypePropertyAttribute(bool createConstructorReferences) - { - CreateConstructorReferences = createConstructorReferences; - } - - public bool CreateConstructorReferences { get; } - } - - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - public sealed class RazorImportNamespaceAttribute : Attribute - { - public RazorImportNamespaceAttribute([NotNull] - string name) - { - Name = name; - } - - [NotNull] - public string Name { get; } - } - - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - public sealed class RazorInjectionAttribute : Attribute - { - public RazorInjectionAttribute([NotNull] - string type, [NotNull] - string fieldName) - { - Type = type; - FieldName = fieldName; - } - - [NotNull] - public string Type { get; } - - [NotNull] - public string FieldName { get; } - } - - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - public sealed class RazorDirectiveAttribute : Attribute - { - public RazorDirectiveAttribute([NotNull] - string directive) - { - Directive = directive; - } - - [NotNull] - public string Directive { get; } - } - - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - public sealed class RazorPageBaseTypeAttribute : Attribute - { - public RazorPageBaseTypeAttribute([NotNull] - string baseType) - { - BaseType = baseType; - } - - public RazorPageBaseTypeAttribute([NotNull] - string baseType, string pageName) - { - BaseType = baseType; - PageName = pageName; - } - - [NotNull] - public string BaseType { get; } - - [CanBeNull] - public string PageName { get; } - } - - [AttributeUsage(AttributeTargets.Method)] - public sealed class RazorHelperCommonAttribute : Attribute - { - } - - [AttributeUsage(AttributeTargets.Property)] - public sealed class RazorLayoutAttribute : Attribute - { - } - - [AttributeUsage(AttributeTargets.Method)] - public sealed class RazorWriteLiteralMethodAttribute : Attribute - { - } - - [AttributeUsage(AttributeTargets.Method)] - public sealed class RazorWriteMethodAttribute : Attribute - { - } - - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class RazorWriteMethodParameterAttribute : Attribute - { - } -} \ No newline at end of file diff --git a/src/Pixeval/Properties/launchSettings.json b/src/Pixeval/Properties/launchSettings.json deleted file mode 100644 index c7aadb52..00000000 --- a/src/Pixeval/Properties/launchSettings.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "profiles": { - "Pixeval": { - "commandName": "Project" - } - } -} \ No newline at end of file diff --git a/src/Pixeval/Resources/dqueue.ttf b/src/Pixeval/Resources/dqueue.ttf deleted file mode 100644 index 5e35b562108b911a3941a348431b2a3afd19ce71..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8028 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 diff --git a/src/Pixeval/Resources/iconfont.ttf b/src/Pixeval/Resources/iconfont.ttf deleted file mode 100644 index 2fc4eaff052c55159522dcf5b90a36dc20b9b3ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16276 zcmd^md3;>Om2OqtzDwWReS6=u_M+~VY^^PIw`|L@EenIOjcs`Yyh+INDoY+&1{^jS z2!U*m$s~j@Byke*k_Xuyd08gouq2s~3`~YF3CU!Jz%WUhgvkVW%zH_&uID@Vwq!vd z%k-TeLd3K zM~{vi`}TqOdB((N8I#io#!v45<|(zAF%9sA|8;O|WM86w8)1A7u5=I??n&io#LvJr z9XvXH?N10Z<3ED;qw&enk&Rbe`F_UKCy*XLI&$qXzKN$$9!EMkF>-XQf2(x^V@v-H zZ5}-~d3?I*k}Vcv%XcANW@t&8IX}a8scFW}Tk@Th^SV#b&OvVOTaB^3zP|rphRX){ zSy{WEB2IX|RlZZY6-kW=yBJ+SSmY5Fu+x;Q;F|SYQPV-}l<@IG z2S$)rO`(iRIdV8ts<}wJ{QOQPGfmtfXa@e96Y>{XfupWqvV`0>`E1&M(LT1a;(Bqt zGk)})X0$qbYU)iL%HK5q&EWl2*#Al$%+7xq@0+#tCV8}?HqI(;fXHw(AFU3!_@pyl zelK!q@tgCFTTu~XR zj8?`f*H!MSe7^F7vjb;0oc+$(U%#;Vg_~boe;%t{aoP0~sGq9j7t|l9)*t@U_0g06 z*AK@Sw%gxbY!@45`xbl;GUt1kz15eoZsx(v2+**Pd6~)l%+0ba&3afHi-L9)%vlYK zVb(&dmNl{rs|SU4usCLJ5oU8SOR)s2V+9swLDmUA;bM7~W6i9KMX(<2tckTS6@*7L z{r~&NLlYoos?*Rzl;b$81FL{~$zerU1+zttsJ4RHBS(Cvf;~@;cuvLbIIJA2fU3!1 z4Ozu-99EN62p6@Ay;`9%IIJ+MP#GN7npLPi99ErG2o4VG&ngkeff86H<~YyR^=`#}UV>)H;rKU!~4*pdD5rI5kx>^S0|m3GI0Dp_TT<3OLR(&so(Dy#H64m8Uu1CAq3QCaOc&@rnFIt~=g zD(f5v+Gdrljsumm$`y_Sy|c=&<3RbWGU7Pw0ah7x9Cib%j5!Ybf>o|_95JoRU5>+E zVU^E24!ed`e&9IlA9fb~B!`{E&TeoV_7pq&9mf&3JNs+LVV|)VHaiYGj=gZRc$Z;t*Vb};sfxE8-B z5lmc3GxL) z9BbgQXso+b?&sxFPqtJpl@(P{b9uE?j>Z%%H*TE?>8q38fFPATsiv-$T z%us%jGUywNHgd|(<)e85Cp-~?$V9p+AIT!+DP?MkYD8m*QuS^HwJ05pNl)kBw`=zS z*MZ%;-j{D~UYI!d)m2;T8?p@{-$3#5cvIi{8tHLqcT+rtpl1E4t*bo60bd9JwfVTN;v&1FC2BLa2?~FF^G-ByGSSzDYyhlWI0BqsGMA zo$t%%InU?cw{!24d(cfMv1`whzgU&=xO08E)?n?sdOMQg(W$N0$qmx z)&*K~eOWE0Ceka@&3@4$f_o-fj_wH}=5Iz`jgrZ%GHZhX%eiAp%>}TdEfWAcn^1pl zL#|oX#I2-nXTPWdZsqE&_La8U8Rw98^u^Z9cVxCs&c_z?~FcJty zyHkZyG0>Bfeqyy)Es8Iw@~`l(s3CJk_ge2cp?kghdv))t+#5zrd>3gh_-mG|1wnuO zX={<{4N6|!`qUR~i0|^cU`i+LohWK!we za-K=&ddj@iU5Lhb)Xfpr^Hi~?w2bpqA?iT&lwu3w(j$rBOgv~U3dU!G2`~SUH=qS% z1lCIHhl9ZcpGgDHP#Ok!5{xPn6PFN zP4ReBq8bp-K0o7ve9U&T2iVuxx7pvbpJEK4^>PWjDwj|DIKp;Lv+Kj=$>%Z%O^%I3 zK|K#+Peo&@Vh4p49AN`r#tWqt*psnnH^P37{Yk-c-jh>J2_S?gt(wBeGx>Hw2_Mg6 ztG9~|UM%-ZXp<@z%Kc&m?~XMHO03{9@P-D_$RlW41%m)@Xy+361|mqBTw0K?w)376 zO|taFRjS_Waryg0H6j1ja3n0J<2zz$8L=$^ykM=yW|w%DMt%N@|I z{tKX2#p>(d8Ay2ilDoGbI84)@j=DmZhg{LL-!wykE&aW2$?r)7uDa@v!FGiI7|dF^ z_a-53+UxjRCWV;X;`pVtoUbi8eoLt|R4VabQ_sV#f&L&j&~fTbjK*m2V1J+$MKr|u zeuw4(=SS!OhMc(|!28gnWXgwb8>%+fZA~>WI$tU|Keo34;hy;s?7hj_Ge3kalYC%) z45hWtavH@@$==&DE)M!jketBNDi$_^l}rWT6-wAT#hzS#iI5)go9AYHA>LHWhv9|l z-TXPVsZN^FtfW>Ss%_%dX?P)@G~*2*;_#POr28dKr?Z@Im$2=+3o+V@kubQlt zSGV4_Z+iXu>3z2ye8;=Z-r-%hPb|Ia_A9Tv{i@48d;Rq!ADn+!+ApnQgY0hh5#Z@c zr9rQO9-A=x<>kCzqRkzN;=oW;igp3FqM{AQ$2Ot3DKgv?DsiR;0oFvPTDb>wpX=#& zVT=?3S0F}~A-YAhUldEk)pGU`m~RI&F$KErQoF=QtdAy_EQ*6;dF$icY;J8yhPbab z9c<|}gray=h?Bx}Qgu+CqV{SmL@ z%3>u}&M_&+@`xa*unpXCJmne{AYBK5PM@suoE&;INQ>t&>UPdveWNWZ*J)f4X<-to?4QT50!WxM3! zx~oN!Jsv5Z`OwJ3$7|fpiW5J2x<)tMiTCf_aa*GUy+c)Gi8o8KG()HtG<7b!pp7Tc zCjXRMy?m1M-Rl#=1?0`by+iRRF135xK`v(YtL|S)F14`jfRlJVa0};>ByCqbq$^bU zKh0qVvT+CG{w2^TFM^!51#>$2*0Z{h*M>l}`35dW5YWs;V%?a>KoOHm6PoGgQa9r5 zTt*>^AiF^Z&E*wv@j?j)NI%EcDS?}(mA9SbCr*7%l0J9J_TRrm-ZFUQwDrQ89g4DJ zP4d4hS6qDY70Qc)+vGm=+MD|1ZG$_n=aQ)`ja<>fa zz1{l#&@H*}?SGlOd1%kO_!qrKys&sqGZ6;Ie@g}obl77zryY#RWL`;Du z7blIwE%I)zN~vNdk_xyndGG?=#qNmoS?hA^@)&=ZKO9?cz3?9E1-_f_`H!cpzp);B z@+k=QQ`Y-y_`9r=HP%f({V6}hd#&$T-{55)w_dQm|5G~L(cUcDlSmumDICk~kar+( zlSGxvLoNXilJ1*je2<&^B5v!5+s!|uMf}`teN1v0J|DlA_o~qVSFO9XxMtn01fnWm z=8O4ke(CUY9Xf0h%4HYNtAR`)ukvzNwkj6oF)9#43ZzgJ*tGFy(*IP$Wx<~bo9Avf zLr_j~_0qNVImittl>Fyj`KN^STGy7}n&Ghd;)^H%z;7Xc5r4kW9<;3x@1AQh*2N*# zgV_g6PQq9*&=0w!m?65XwhmeG4_xL>4}Qb{`pg+K%tO=%3eKEy8nS!BbG*lTZN59d z5d-P4IlG@aBKBh%Wk1LzaXHN(FMs7 z10k!Ha4iTosF*Er|mK#}sk4M(FtV`EXYHh!m~P{}xaOrZ)z1py|qk973rEjsw}2)hSIfIi=^O z)8=YmXU^Oa!=kx!6pe6n8IF#y@&%_MM>=TIh1zsxu=}5FG^0)h^PEOLlX_G7`iQ2 zJum$px>XM>gG{FJ7BlUF1gZiyI@D+EMOA5sjBbnNkT5B!pAe!t8=sH)buH_3n5G8j|jU_|k?*PaKC z%dOA)jPtEag&Flx-ALd}AQ}x^OE|C16O#OyT(`|nZZe1Z(q*&^7eKRUVr=SgHEcp)yG|u>63gN zb>cEA^9sRz?e$La{k$&mgSvsbM`AU6OMm|s4nJN0FjB%!*2aHO+t@!O#1IOFxR)<$ zYlE_B`?G&td25A_*>*wYB!)e6Z=~o6@(W0r2o%a4cd- zDSYX$CY>7m^mRIRIRzU{jzp?3v_Tvo9o1u`+imdKwc=~s2tab2ZG?QMiGOh$#?={M(vG#yHc)_LE(k}nnG}|J{ycz4Lq`Si zg6@>fLi5G$nCuu6pojoie9iiR-JuEiH@`~JS23R1{S+gQkMvnLLLB1l8PSWdg-3(4 z-?OQ<~7F#fI506GIUH z9Ed#*p3w66|pyDBz0&YSN`Uz5tPhz6idZD9K`2Ur!@OF-SUdr2Lhk7U!>))+kf z1oU`NG5rK-9-PR!UqD|6nbQy23v?JLHc3k6{8U~_QiZ7az_xd6!*Am)XKul-zj1LR ze%8OZn)@Obbq4BMp-@T^RLR!5K<7n~C*LfSZ>!olhxtx;A8+yV#sEDEEcIorHHhyoSJ`ww9G%=Ug zACG=C5_eM3(8oiOIXu)i%Fp)I?ec_N5~r(fNEKE-i>J%;(s83r{PFtb+~h{(m7p`^qCNCC*DNPVg(L_K5AhdA67d)&=o9?F8r9>yof?%we(-u9!n+1|gZh zRS``&*(7hWZF)28514dVKgbLTrI*etaAxAuCPZtRAMiBL1||l&uR<_Y9^SwS#yR(G za~_%Z2*&2`WXmHnA5Cb?kr4v_l{6wfj>!=HqcYgu`+?0iN1~)u0FoG*A<+b75NaFHnJ9IDitOXru|c9p zp-lnGM_+)Bv{S^8My~Y3)rvl!5u1+&&mP~J_ zOF+Xml)+F9=QW|h`Fh^6FKgEuR@^n=%R;patC=0uYOBLkExbC|Am`k&w^NeJs@CC8 z_}sfmWOQHVhNS4<3D1Geyf+fYuXX%Hf)3I=Zw7EJvMh)!BS zb5iBT@t|@*FD#lE5`QZNk1vCMtnSmC+)@s?;&Bn0qHJyd&1O?*?>nN`h9^gJi-nsIm%sq!{#|Exgdq|dscb0Be=FfYN7dp1l!*$O6loWRg^Y>BFo_u#v8S7OE<-Xa|nj2<)P` zRl{vt4-B1Z8ceEK%9D|{JBkqI+E}z)Qp5cGPpoHTmFJ&+isxk2`lnz22^PvPW{;ynCm+{_rBni^~>kGXl1p$nlKn}@sx*NxiRsJKb+)*t-?&jQIm zKK&2YPow+(D7F?ATNGTHgkLw;sZQ;N`0k<;xM} zALspaL|EUV!bd5}R|IQuh3v@S=cQ9Haro)p8I~Fnv0Op28*7?5DJlslKL$O_hHbg-BR;d+MQ2M9gW`7eWy{M{ab^3ki42U2GL> zf6$ZzDVgN_>W~}>SjynQuy5HMX}W4ouFC_!p>LBU03#86qcwm2xA zs*-;ePZJz{;FL5g-SkGgOQ>pJsVe+MX`8MUS%G>stx2jJP%A65~PDaPl zLYN%|gM`X{)8I=C(=@Ed409>($nYhZ4vx@zEYq>%PZf%xKUK=#LkI~%_XXmCDndfc zmv{mJY4Kc}1VU{&MRqv*$e$?WfA|xH=O&y!`SgE;G2i=-7ly*o39JR(|Gy8i$gTGM zelqN6^+(vTn2Rj|< z#vKay0v-kw%Me~7xVtZu!GBAkC~+EG8Rk$Wlk@R%Ar`gu^Xyz@wL6y25LkCqE+T@j z)LnEQ9B{BAB^Cy5sv~vh&}uuxr!*SI!K1=jgr3A8xgfv~+EWAR0CwYo`>#02+wVQ~ zKu(cV!97D?vh;gmS&t_3XLf9raIIxXPyLYB3g6wT`g^JVGv9q|^CnnLY7!ps7WLDz zrgR8Zx~#pvKbedqRG4yR3m0GFQbpP$Ne|Z7Kd80|MOw?-Kbh%M)WmJ~B_fL9TFx(B zGXT3BkEOlw#dq8-NzFM=Cc;N9UG36DkKw;$dU4}lbZoXxMnZ1CE)2O)h^9|<-MHhT zezeXn-=rw-J$n6>U5mbOYc$%{uPC=2`LXZ&$-!(*Er&%#bM^Pv)!GF%qRUV(S`&7Q*#WM}N5b*gX0f{afO2|vS2h#M2VFAn z-Xrz2{Tas_$2omsg6{J|j=dV@ENEijiD^(sdOfc2kJnyO%TIV~noR2f6W$lhCb5Si z@2{!hC(KMOM*-lr*!TBjqjmHRveB-FOfbrhlZ{q>8|~or+6C#>q*Pq643Y)y^)R@b zeuD<`w&gQ#p-}KU@4TQ=kk;Vn8F%9Nu&#QmI*+_XLGmq?3G0yyMTFb5JyL0KdMzj; z#0%7uh1K3rG{1(&=*1US46i=u6pLXiVGCn1rLXF7-MZSkT94zF@U-mFJu*M7i~YK8 zUBmCt!zdk=@j+%BD2U-h$DATgvk)H?b;9-)qt38yux>EwB09ep34X6G4gl8;{1!ce zvVFRpPiW|!$#Zzik;G|x31bd3x0jSm!p{AHE#)B0WJr0vUG zNQ5vpi_%)^444p30?dw!z(OV7}hnz=SBn{K0lJuxsdbb`6YTK>RkESC`E=Kji@;RCR9;)CBhE@t_+xJk~cGQ+D-_U9#p#LqoDbkt1<6owe(J)kc$R zQsWVfzDg&j#Z&ZZ&t~R$)`f1P)8QCKq(G9v(=lk0F$H5pfD#J3OF@!OrPJ*_wK=`8 zG`=#sc9^@4d}U>o!)wDK zb@#@6N86<_5fUqQ!dTw3N~CjK$~L?Cq6ZC6lik1bFG+tTUS-RWsLm%&vl3|)uy@!D z4p%&wcFG{RvIjP~E<6Z8#~}ljp$_BL?nrL9*xljQw1A#lwCg&NYP5bCDut|HHm1aN zyO3dq&F1yP#nSM)=H?u)P3=kX+FWz9_)NArn=>D5oE z+-0Bb`J!!v0Ns>v4-qYQId%ln2=MK)EeiHAkDM;s-T)jbxH~*mv9FNn_;y|!5tR`l z${}+=zAHzKV2+$y3!7BoIWL(M6%RA8w!lP3I9VU43E;(2qlhFnx(=vLF>`jKWRK)G|x+8#0dS$H& zsW%1{`33pE8YkP|N41+$beJsrJXA+^+x z)-95Rx3|ON<%yD6Fg-C32bV>F#5~-hy3zU;2hN-W6E2tV#1z4=5Q$J%i@zo04$1|W zOAGiV4I+O49qy8Y?huN)LJ7f5eN+cqoC6NX1&q_@=X1aXIp7XA2b!zE``qSEvHPMm zyYbp#O*-jTwV*o|FRbExRiSH@FkEUVAp7R__@9ft^wPNuhD{Ie=&}pUJI~LUO*JMz zY&LoMZd|^b*0;Yv0pI8GTK9UJYP@_9v`n_MXQfZz4A{ZG$o`r=Mv{PSJA;J)<}osB z*#Xfs3{GY6LL$9J=Y1O;4`iJJO_Bu)FMq05GFyVQO$ub-LdvA4D2;+{B*0qnuq_H~ zc=J|5s$9&01ycgHFg%N+6pj?1K)pON6g;0(kWwRrff8tQ1^PB`+p3Z*NV%Ph;^AOS zh{pP6Z_2yQ!#%La4+e3IFr?{A49|K`%6pONbMbf(a9r~HF7l?3%RNhUZ3wpwL0G$5 zkz9xB&GktxV!txdc|#KJ!+4iqoV)(g6b9Ei}JtDS@j0+P6`NjeX0=U*=qiwb8{`G8!!D{;b`Dq_-Q?184}jAhbk@f_|K25=HXR(QjOzs=9FeDj(j z7Op23s-D86YImpTaP4xet9fzEIbBWkJ zcP|yA9ZSzOv$SC;Dwr>HhZzc)cZ3?|B7Dv4_Cm2(5ck7B_iU<3+~1Ts_k`4wYMR~N zlzQ2D-a6%JN+4#v>cLyrMAM#-?~YJ?h~MrDg?zVjMDOs0?x`Xv5JK_5?3tz%unndM zDa6}aRP1!BcX{nMv$TxFADnqe;Qs=B4F3g~8zi2VT(A$=FMthYZBvTpA%<$_5h(U+@ zFi6%_93(WB6A=%jG8UtHz{~Hk(y5HFlZ58lusJtBb8}`w+j8V5`A+e5lC!f58LJzj zNsfOY$R7=Lh4{CE*{+av*g72Q%6>f&;*UZjS%G+v-(?*RI&Yn3?7Im^-`WV7!FioP z!gLD9ECgoKvlng!aI-v^9PwUo%I*@lT_au-5!a2+nOWvMo0XhU z$IH=KhS#A8B?{N5HHH=Zf#sR$$kq>*Zx&+na>q}% zwGFnl&EPR>6=#XskZy92&LM9%aF4KMS`RcCGj!pFkGS_8icnS>O@6(5@5i+o{+W54 z%Qyd=6V|~tqA~Cb*i&7wr}p9v9*cpj%GrKFLQAYOCVvbzzRgOgBHI*J$tFrsLLGopRT@UE*%Hv~s{3mfoq>q#N|s_jI2w?RUAx z%BQ>D+om_9Yt;>xu2BMu-Db%{vLK!dap8PNwXP88ZTI5sZu$R%SfqQ56p03i06S)0j1LI=U$;F zAd(6H+*v&5k|mS;XRR+N3LjFw2t$V_MHU#J?(^yAUN%grO+NRs4e67uaqjVamH-u0 zpcM$RpF0$fIR0%@jnf@*q#76Ci1pRDg#4yz+=V#)>q$tUbs2bl)wsg^T&l)( zww;Hnaf9Wsn5(D8MyAL1C9gV}JTy8vv43)6TAzyyjU6~KJ~B0zoC~*)O&vcpIg#vY z@0`oJcx+;9Y7Wows}B^Wr}roKPfZ?8t^vZa@$t#zv8lep}Y54nC5|4CF!aoG_%Osn?!v*rE0r$q7A;2HNABVtrgIdY4j-xHw8>b5nEI3;TU={j(CzC zv&#+x&nTeV@yAQ5b&M^=)qKbNi00ti?U5cOI$Dc4maqeol^Cy$OPCywpILTkszrl${0 z95}8|jbR0kj!o?A()N#BJvnt~dMrR>aeQ)WdcI6`YISKQWB15n|)y$$gX8 zOpH&C?CV+(FPNif>A>XF$%)CSqa)+~x#aP&aZu9OJ{w6vK7MdyYD^|XUCO?(>5)U@ z?n4vDr$-J9<4;`O&&kdz(K30%M_U&`Qb=hbO z6fLL+M#jg-rcS!6V`!Un4FZQY*DIMYq6hGgU8_!wOdP@dNZU5GDdUp|CQnSO)7KoD zo*tWW&rQ?u`S!ZSiDUDL9^=sDadh`U8&z7hZ{M+z17i|G>BO-v_2OzL)=XmaT!R*< JZ}_Vy`%f1xbL86g~4k{H>-9juUl}SaD=WG&rfLY#I`ZQktL&Xi2FBQVVkJXFHX@WWQ7i zAk|0|fmB3S5j$3hRROg^ND-ooNNi{pNa+F=p&Ps@feo+;*qnLqnM9HQ0b|e1x%ZxX z-@Vr}eh>isXhOx*!i9@-U$*b=0OBcX=gwW2Ow4@o{QH#Orku`}GqpnShf|ava=uq6 zt>)L2Uw#MF8s(3RMkY6e=~Z%RN3uwTds}^%_#4i#V%b~?5RkjYB~YqnGdPR;^e(=2R~q)t!Vor;IaUtHtXM?^SB0#{_p)M!jZnT-*f|8NI`5yE~aO zcbUB+{e(pS_hBFBai2fjk|NJKJJ-3ZZmKWh39Eh0Z)jrOjt|8>t32zYKk)byP@cXo7f z@uk3#K)`$7%Vq85*F@7|34P-`q3ASekG>*}dGWAxZmNIq z1`J^gvpC1h5`#=76m&Bu*Jz9hMNg!dSu*8(Ei>s$ZlHb&* zTPi{$B9W4EG^U8l>BZ}jv9ZYY#q|0fyu8(J>AE<&wIz<~db`#BRqXownyQ(aM|XSv z-iJen`vZ-`k=Q?7pq@P#%?>=yI9vPTwmbgR z_Gw;vKaLL_ED*%k4pwjo-#b{P{znIE#5)ew5fZ||E(FD(gMCPgV-EHsD&Fy(t{WNC z$c3-0hL^I{O1@e#eO+LzEEq)!3MDAB*(lhMm7O|Lo{MytuNsfWBtP8>yZpFSd0C#N?)yi+YkCb;C_?3n R!?kFXs+pXYU#jHD`xn;*Gc5oB diff --git a/src/Pixeval/Resources/interchange.zip b/src/Pixeval/Resources/interchange.zip deleted file mode 100644 index 54d33147b04ffc837c4471334ac9caf53625f4a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 78811 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

)P<^i=4QsKHr5O^qn8t& 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 E09q1ybN~PV diff --git a/src/Pixeval/Resources/logo-only.svg b/src/Pixeval/Resources/logo-only.svg deleted file mode 100644 index 3f51b366..00000000 --- a/src/Pixeval/Resources/logo-only.svg +++ /dev/null @@ -1,1216 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Pixeval/Resources/pixeval_ca.cer b/src/Pixeval/Resources/pixeval_ca.cer deleted file mode 100644 index 1ceebbc64b89243606a569192dafa0f4d54b3559..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 982 zcmXqLV!mY1#I$PxGZP~dlYr}v(!SHZ%llk5z9{?AsWQWWmyJ`a&7D}zCt zp_zdR8*?ZNGmoxIWlm~xhOt3OhJs7Jf?s}#LP$|*afyO+YEemMT4r)$NveWlX-P(Y zQD#Y{p^AYL+$c^)G0~LN~Pk)+Q)r1IUY9HM`eroGp zx&6hF&k9fMikd%`?cFHy>urI?|Ewu@C7$~!FTFd-?t0ZKZ>=>YrWy|eW!BFu+WvL3 zqwJr&e(|+0)~vX`ZNV`IUNP$`)yo?uM}I!Ob^6hz_G^}Vhb!f_T;CFZl8Kp-fpKwT zw?Siv0Ut0O$nrBX{%2ufW@6c3APeHFvWOXouyJU!0h0?mGZUP}XkY=77GyCr&~G9w z=|BwTV-aH!X__PY=%3c=N5TKZq6*_*PkwY++!HyzfJqb>UyKZW4%w)f2=E|rURW45>i{b-9&&k{= z_g@zlui|}T=Zq+W{o8%GU;p~K-lpXH)^`)7^`^LShfE6jVwldhtk`X5zCQoKBWcOb z6#})>u3k8)c~Q>$*2dj+L2KOW_eIU0@i5(D-*MTa4Qm!2Hx1VPuzBV6_H@OjOBId} ztvQ!Xe%7>XDobLlh+LkI&ZIKEsTaLY_GNvOOj`O&b4l3T&9M*s7@c?BpV*bDxOdw^Jrqg949<{aa>G<;TBAdb)zBBb9%Kz^?wE_TR CvV=7N diff --git a/src/Pixeval/Resources/pixeval_server_cert.pfx b/src/Pixeval/Resources/pixeval_server_cert.pfx deleted file mode 100644 index ec177e9fff456749dad225d0c3ed861c1490cec9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3758 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.--> - - - - - - 2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -45 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 10 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - premium - - - - - - - - - - - - - - - - - - - - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Pixeval/UI/MainWindow.xaml.cs b/src/Pixeval/UI/MainWindow.xaml.cs deleted file mode 100644 index 12b8749e..00000000 --- a/src/Pixeval/UI/MainWindow.xaml.cs +++ /dev/null @@ -1,1075 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Net; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Animation; -using System.Windows.Media.Effects; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Threading; -using MaterialDesignThemes.Wpf; -using MaterialDesignThemes.Wpf.Transitions; -using Microsoft.WindowsAPICodePack.Dialogs; -using Pixeval.Core; -using Pixeval.Data.ViewModel; -using Pixeval.Data.Web.Delegation; -using Pixeval.Data.Web.Request; -using Pixeval.Objects.Generic; -using Pixeval.Objects.I18n; -using Pixeval.Objects.Native; -using Pixeval.Objects.Primitive; -using Pixeval.Persisting; -using Pixeval.UI.UserControls; -using Refit; -using Xceed.Wpf.AvalonDock.Controls; -using static Pixeval.Objects.Primitive.UiHelper; - -#if RELEASE -using System.Net.Http; -using Pixeval.Objects.Exceptions; -using Pixeval.Objects.Exceptions.Logger; - -#endif - -namespace Pixeval.UI -{ - public partial class MainWindow - { - public static MainWindow Instance; - - public static readonly SnackbarMessageQueue MessageQueue = new SnackbarMessageQueue(TimeSpan.FromSeconds(2)) {IgnoreDuplicate = true}; - - public MainWindow() - { - Instance = this; - InitializeComponent(); - NavigatorList.SelectedItem = MenuTab; - MainWindowSnackBar.MessageQueue = MessageQueue; - - if (Dispatcher != null) Dispatcher.UnhandledException += Dispatcher_UnhandledException; - -#pragma warning disable 4014 - AcquireRecommendUser(); -#pragma warning restore 4014 - } - - private static void Dispatcher_UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) - { -#if RELEASE - switch (e.Exception) - { - case QueryNotRespondingException _: - MessageQueue.Enqueue(AkaI18N.QueryNotResponding); - break; - case ApiException apiException: - if (apiException.StatusCode == HttpStatusCode.BadRequest) - MessageQueue.Enqueue(AkaI18N.QueryNotResponding); - break; - case HttpRequestException _: break; - default: - ExceptionDumper.WriteException(e.Exception); - break; - } - - e.Handled = true; -#endif - } - - private void DoQueryButton_OnClick(object sender, RoutedEventArgs e) - { - CloseControls(TrendingTagPopup, AutoCompletionPopup); - - if (KeywordTextBox.Text.IsNullOrEmpty()) - { - MessageQueue.Enqueue(AkaI18N.InputIsEmpty); - return; - } - - var keyword = KeywordTextBox.Text; - if (QuerySingleArtistToggleButton.IsChecked == true) - ShowArtist(keyword); - else if (QueryArtistToggleButton.IsChecked == true) - TryQueryUser(keyword); - else if (QuerySingleWorkToggleButton.IsChecked == true) - TryQuerySingle(keyword); - else - QueryWorks(keyword); - } - - private async void ShowArtist(string userId) - { - if (!userId.IsNumber()) - { - MessageQueue.Enqueue(AkaI18N.UserIdIllegal); - return; - } - - try - { - await HttpClientFactory.AppApiService().GetUserInformation(new UserInformationRequest {Id = userId}); - } - catch (ApiException e) - { - if (e.StatusCode == HttpStatusCode.NotFound) - { - MessageQueue.Enqueue(AkaI18N.CannotFindUser); - return; - } - } - - OpenUserBrowser(); - SetUserBrowserContext(new User {Id = userId}); - } - - private void TryQueryUser(string keyword) - { - QueryStartUp(); - SearchingHistoryManager.EnqueueSearchHistory(keyword); - PixivHelper.Enumerate(new UserPreviewAsyncEnumerable(keyword), NewItemsSource(UserPreviewListView)); - } - - private async void TryQuerySingle(string illustId) - { - if (!int.TryParse(illustId, out _)) - { - MessageQueue.Enqueue(AkaI18N.IdIllegal); - return; - } - - try - { - OpenIllustBrowser(await PixivHelper.IllustrationInfo(illustId)); - } - catch (ApiException exception) - { - if (exception.StatusCode == HttpStatusCode.NotFound || exception.StatusCode == HttpStatusCode.BadRequest) - MessageQueue.Enqueue(AkaI18N.IdDoNotExists); - else - throw; - } - } - - private void QueryWorks(string keyword) - { - QueryStartUp(); - SearchingHistoryManager.EnqueueSearchHistory(keyword); - PixivHelper.Enumerate(Settings.Global.SortOnInserting ? (AbstractQueryAsyncEnumerable) new PopularityQueryAsyncEnumerable(keyword, Settings.Global.TagMatchOption, Session.Current.IsPremium, Settings.Global.QueryStart) : new PublishDateQueryAsyncEnumerable(keyword, Settings.Global.TagMatchOption, Session.Current.IsPremium, Settings.Global.QueryStart), NewItemsSource(ImageListView), Settings.Global.QueryPages); - } - - private void IllustrationContainer_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) - { - OpenIllustBrowser(sender.GetDataContext()); - e.Handled = true; - } - - private void IllustrationContainer_OnPreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e) - { - e.Handled = true; - } - - private async void MainWindow_OnLoaded(object sender, RoutedEventArgs e) - { - await AddUserNameAndAvatar(); - } - - private async Task AddUserNameAndAvatar() - { - if (!Session.Current.AvatarUrl.IsNullOrEmpty() && !Session.Current.Name.IsNullOrEmpty()) - { - UserName.Text = Session.Current.Name; - UserAvatar.Source = await PixivIO.FromUrl(Session.Current.AvatarUrl); - } - } - - private void PixevalSettingDialog_OnDialogClosing(object sender, DialogClosingEventArgs e) - { - SettingsTab.IsSelected = false; - } - - private void DownloadQueueDialogHost_OnDialogClosing(object sender, DialogClosingEventArgs e) - { - DownloadListTab.IsSelected = false; - } - - #region 主窗口 - - private async void UserPreviewPopupContent_OnLoaded(object sender, RoutedEventArgs e) - { - var userInfo = sender.GetDataContext(); - var ctrl = (UserPreviewPopupContent) sender; - var usr = await HttpClientFactory.AppApiService().GetUserInformation(new UserInformationRequest {Id = $"{sender.GetDataContext().Id}"}); - var usrEntity = new User - { - Avatar = usr.UserEntity.ProfileImageUrls.Medium, - Background = usr.UserEntity.ProfileImageUrls.Medium, - Follows = (int) usr.UserProfile.TotalFollowUsers, - Id = usr.UserEntity.Id.ToString(), - Introduction = usr.UserEntity.Comment, - IsFollowed = usr.UserEntity.IsFollowed, - IsPremium = usr.UserProfile.IsPremium, - Name = usr.UserEntity.Name, - Thumbnails = sender.GetDataContext().Thumbnails - }; - ctrl.DataContext = usrEntity; - var result = await Tasks.Of(userInfo.Thumbnails.Take(3)).Mapping(PixivIO.FromUrl).Construct().WhenAll(); - ctrl.SetImages(result[0], result[1], result[2]); - } - - private void RecommendIllustratorContainer_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) - { - SetUserBrowserContext(sender.GetDataContext()); - } - - private async void MainWindow_OnKeyDown(object sender, KeyEventArgs e) - { - // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault - switch (e.Key) - { - case Key.Oem5: - var inputBoxControl = BrowsingUser() ? UserBrowserConditionInputBox : ConditionInputBox; - inputBoxControl.Visibility = ConditionInputBox.Visibility == Visibility.Visible ? Visibility.Hidden : Visibility.Visible; - await Task.Delay(100); - if (inputBoxControl.Visibility == Visibility.Visible) - inputBoxControl.ConditionTextBox.Focus(); - else - inputBoxControl.Focus(); - return; - case Key.Escape when IllustBrowserDialogHost.IsOpen: - IllustBrowserDialogHost.CurrentSession.Close(); - return; - case Key.Escape: - if (PixevalSettingDialog.IsOpen) PixevalSettingDialog.CurrentSession.Close(); - break; - } - } - - private void NavigatorScrollViewer_OnPreviewMouseWheel(object sender, MouseWheelEventArgs e) - { - Scroll(NavigatorScrollViewer, e); - } - - private async void ReloadRecommendIllustratorButton_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) - { - var tb = (TextBlock) sender; - tb.Disable(); - await AcquireRecommendUser(); - tb.Enable(); - } - - private async void RecommendIllustratorAvatar_OnLoaded(object sender, RoutedEventArgs e) - { - var context = sender.GetDataContext(); - SetImageSource(sender, await PixivIO.FromUrl(context.Avatar)); - } - - private async void KeywordTextBox_OnGotFocus(object sender, RoutedEventArgs e) - { - if (AppContext.TrendingTags.IsNullOrEmpty()) AppContext.TrendingTags.AddRange(await PixivClient.Instance.GetTrendingTags()); - TrendingTagPopup.OpenControl(); - } - - private async void KeywordTextBox_OnTextChanged(object sender, TextChangedEventArgs e) - { - if (!KeywordTextBox.Text.IsNullOrEmpty()) TrendingTagPopup.CloseControl(); - - if (QueryArtistToggleButton.IsChecked == true || QuerySingleArtistToggleButton.IsChecked == true || QuerySingleWorkToggleButton.IsChecked == true) return; - - var word = KeywordTextBox.Text; - - try - { - var result = await HttpClientFactory.AppApiService().GetAutoCompletion(new AutoCompletionRequest {Word = word}); - if (result.Tags.Any()) - { - AutoCompletionPopup.OpenControl(); - AutoCompletionListBox.ItemsSource = result.Tags.Select(p => new AutoCompletion {Tag = p.Name, TranslatedName = p.TranslatedName}); - } - } - catch (ApiException) - { - AutoCompletionPopup.CloseControl(); - } - } - - private void KeywordTextBox_OnPreviewKeyDown(object sender, KeyEventArgs e) - { - var key = e.Key; - if (key == Key.Enter) - if (AutoCompletionListBox.SelectedIndex != -1) - KeywordTextBox.Text = ((AutoCompletion) AutoCompletionListBox.SelectedItem).Tag; - - AutoCompletionListBox.SelectedIndex = key switch - { - var x when x == Key.Down || x == Key.S => AutoCompletionListBox.SelectedIndex == -1 ? 0 : AutoCompletionListBox.SelectedIndex + 1, - var x when x == Key.Up || x == Key.A => AutoCompletionListBox.SelectedIndex != -1 && AutoCompletionListBox.SelectedIndex != 0 ? AutoCompletionListBox.SelectedIndex - 1 : AutoCompletionListBox.SelectedIndex, - _ => AutoCompletionListBox.SelectedIndex - }; - } - - private void AutoCompletionElement_OnPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) - { - KeywordTextBox.Text = sender.GetDataContext().Tag; - } - - private void QuerySingleWorkToggleButton_OnChecked(object sender, RoutedEventArgs e) - { - QueryArtistToggleButton.IsChecked = false; - QuerySingleArtistToggleButton.IsChecked = false; - } - - private void QueryArtistToggleButton_OnUnchecked(object sender, RoutedEventArgs e) - { - ReleaseItemsSource(UserPreviewListView); - } - - private void QueryArtistToggleButton_OnChecked(object sender, RoutedEventArgs e) - { - QuerySingleWorkToggleButton.IsChecked = false; - QuerySingleArtistToggleButton.IsChecked = false; - } - - private void QuerySingleArtistToggleButton_OnChecked(object sender, RoutedEventArgs e) - { - QuerySingleWorkToggleButton.IsChecked = false; - QueryArtistToggleButton.IsChecked = false; - } - - private void MainWindow_OnMouseDown(object sender, MouseButtonEventArgs e) - { - DeactivateControl(); - } - - private void MainWindow_OnDeactivated(object sender, EventArgs e) - { - DeactivateControl(); - } - - private void DeactivateControl() - { - ConditionInputBox.Visibility = Visibility.Hidden; - UserBrowserConditionInputBox.Visibility = Visibility.Hidden; - ToLoseFocus.Focus(); - CloseControls(TrendingTagPopup, AutoCompletionPopup); - DownloadListTab.IsSelected = false; - } - - private void Hyperlink_OnRequestNavigate(object sender, RequestNavigateEventArgs e) - { - Process.Start(new ProcessStartInfo("cmd", $"/c start {e.Uri.AbsoluteUri}") {CreateNoWindow = true}); - } - - #endregion - - #region 导航栏 - - private void SettingsTab_OnSelected(object sender, RoutedEventArgs e) - { - PixevalSettingDialog.IsOpen = true; - } - - private void DownloadListTab_OnSelected(object sender, RoutedEventArgs e) - { - DownloadQueueDialogHost.IsOpen = true; - } - - private void UpdateIllustTab_OnSelected(object sender, RoutedEventArgs e) - { - QueryStartUp(); - MessageQueue.Enqueue(AkaI18N.SearchingUserUpdates); - - PixivHelper.Enumerate(new UserUpdateAsyncEnumerable(), NewItemsSource(ImageListView)); - } - - private void GalleryTab_OnSelected(object sender, RoutedEventArgs e) - { - QueryStartUp(); - MessageQueue.Enqueue(AkaI18N.SearchingGallery); - - PixivHelper.Enumerate(AbstractGalleryAsyncEnumerable.Of(Session.Current.Id, PublicRestrictPolicy.IsChecked is true ? RestrictPolicy.Public : RestrictPolicy.Private), NewItemsSource(ImageListView)); - } - - private void RecommendTab_OnSelected(object sender, RoutedEventArgs e) - { - QueryStartUp(); - MessageQueue.Enqueue(AkaI18N.SearchingRecommend); - - PixivHelper.Enumerate(Settings.Global.SortOnInserting ? (AbstractRecommendAsyncEnumerable) new PopularityRecommendAsyncEnumerable() : new PublishDateRecommendAsyncEnumerable(), NewItemsSource(ImageListView), 10); - } - - private void SpotlightTab_OnSelected(object sender, RoutedEventArgs e) - { - QueryStartUp(); - - var iterator = new SpotlightQueryAsyncEnumerable(Settings.Global.SpotlightQueryStart); - PixivHelper.Enumerate(iterator, NewItemsSource(SpotlightListView), 10); - } - - private void FollowingTab_OnSelected(object sender, RoutedEventArgs e) - { - QueryStartUp(); - MessageQueue.Enqueue(AkaI18N.SearchingFollower); - - PixivHelper.Enumerate(AbstractUserFollowingAsyncEnumerable.Of(Session.Current.Id, PublicRestrictPolicy.IsChecked is true ? RestrictPolicy.Public : RestrictPolicy.Private), NewItemsSource(UserPreviewListView)); - } - - private void FollowingTab_OnUnselected(object sender, RoutedEventArgs e) - { - ReleaseItemsSource(UserPreviewListView); - } - - private void SignOutTab_OnSelected(object sender, RoutedEventArgs e) - { - Session.Clear(); - Settings.Initialize(); - BrowsingHistoryAccessor.GlobalLifeTimeScope.Dispose(); - BrowsingHistoryAccessor.GlobalLifeTimeScope.DropDb(); - var login = new SignIn(); - login.Show(); - Close(); - } - - private void NavigatorList_OnSelectionChanged(object sender, SelectionChangedEventArgs e) - { - TopBarRetract((TranslateTransform) RestrictPolicySelector.RenderTransform); - TopBarRetract((TranslateTransform) RankOptionSelector.RenderTransform); - TrendingTagPopup.CloseControl(); - if (NavigatorList.SelectedItem is ListViewItem current) - { - var translateTransform = (TranslateTransform) HomeDisplayContainer.RenderTransform; - if (current == MenuTab && !translateTransform.Y.Equals(0)) - { - ReleaseItemsSource(SpotlightListView); - ReleaseItemsSource(ImageListView); - ReleaseItemsSource(UserPreviewListView); - EnumeratingSchedule.CancelCurrent(); - HomeContainerMoveUp(); - } - else if (current != MenuTab && translateTransform.Y.Equals(0)) - { - HomeContainerMoveDown(); - } - } - } - - private void NavigatorList_OnKeyDown(object sender, KeyEventArgs e) - { - e.Handled = true; - } - - private void ExternalNavigatorList_OnKeyDown(object sender, KeyEventArgs e) - { - e.Handled = true; - } - - private void HomeContainerMoveDown() - { - DoQueryButton.Disable(); - if (((TranslateTransform) HomeDisplayContainer.RenderTransform).Y.Equals(0)) HomeDisplayContainer.GetResources("MoveDownAnimation").Begin(); - } - - private void HomeContainerMoveUp() - { - DoQueryButton.Enable(); - if (!((TranslateTransform) HomeDisplayContainer.RenderTransform).Y.Equals(0)) HomeDisplayContainer.GetResources("MoveUpAnimation")?.Begin(); - } - - #endregion - - #region 图片预览 - - private async void Thumbnail_OnLoaded(object sender, RoutedEventArgs e) - { - var dataContext = sender.GetDataContext(); - - if (dataContext != null && Uri.IsWellFormedUriString(dataContext.Thumbnail, UriKind.Absolute)) - if (dataContext.Thumbnail != null && Uri.IsWellFormedUriString(dataContext.Thumbnail, UriKind.Absolute)) - SetImageSource(sender, await PixivIO.FromUrl(dataContext.Thumbnail)); - - StartDoubleAnimationUseCubicEase(sender, "(Image.Opacity)", 0, 1, 800); - StartDoubleAnimationUseCubicEase(sender, "(Image.RenderTransform).(ScaleTransform.ScaleX)", 1.2, 1, 800); - StartDoubleAnimationUseCubicEase(sender, "(Image.RenderTransform).(ScaleTransform.ScaleY)", 1.2, 1, 800); - } - - private void Thumbnail_OnUnloaded(object sender, RoutedEventArgs e) - { - ReleaseImage(sender); - } - - private void FavorButton_OnPreviewMouseLeftButtonDown(object sender, RoutedEventArgs e) - { - PixivClient.Instance.PostFavoriteAsync(sender.GetDataContext(), RestrictPolicy.Public); - e.Handled = true; - } - - private void DisfavorButton_OnPreviewMouseLeftButtonDown(object sender, RoutedEventArgs e) - { - PixivClient.Instance.RemoveFavoriteAsync(sender.GetDataContext()); - e.Handled = true; - } - - #endregion - - #region Spotlight - - private async void SpotlightThumbnail_OnLoaded(object sender, RoutedEventArgs e) - { - SetImageSource((Image) sender, await PixivIO.FromUrl(sender.GetDataContext().Thumbnail)); - } - - private async void SpotlightContainer_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) - { - MessageQueue.Enqueue(AkaI18N.SearchingSpotlight); - - var article = sender.GetDataContext(); - - var tasks = await Tasks.Of(await PixivClient.Instance.GetArticleWorks(article.Id.ToString())).Mapping(PixivHelper.IllustrationInfo).Construct().WhenAll(); - var result = tasks.Peek(i => - { - i.IsManga = true; - i.FromSpotlight = true; - i.SpotlightTitle = article.Title; - }).ToArray(); - - PixivHelper.RecordTimelineInternal(new BrowsingHistory - { - BrowseObjectId = article.Id.ToString(), - BrowseObjectState = article.Title, - BrowseObjectThumbnail = article.Thumbnail, - IsReferToSpotlight = true, - Type = "spotlight" - }); - - OpenIllustBrowser(result[0].Apply(r => r.MangaMetadata = result.ToArray())); - } - - private void DownloadSpotlightItem_OnClick(object sender, RoutedEventArgs e) - { - sender.GetDataContext().Download(); - MessageQueue.Enqueue(AkaI18N.QueuedDownload); - } - - #endregion - - #region 右键菜单 - - private void DownloadNowMenuItem_OnClick(object sender, RoutedEventArgs e) - { - DownloadOption option = null; - if (BrowsingUser() && IsAtUploadCheckerPosition()) option = new DownloadOption {CreateNewWhenFromUser = Settings.Global.CreateNewFolderWhenDownloadFromUser}; - DownloadManager.EnqueueDownloadItem(sender.GetDataContext(), option); - MessageQueue.Enqueue(AkaI18N.QueuedDownload); - } - - private void DownloadToMenuItem_OnClick(object sender, RoutedEventArgs e) - { - using var fileDialog = new CommonOpenFileDialog(AkaI18N.PleaseSelectLocation) {InitialDirectory = Settings.Global.DownloadLocation ?? Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), IsFolderPicker = true}; - - if (fileDialog.ShowDialog() == CommonFileDialogResult.Ok) - { - DownloadManager.EnqueueDownloadItem(sender.GetDataContext(), new DownloadOption {RootDirectory = fileDialog.FileName}); - MessageQueue.Enqueue(AkaI18N.QueuedDownload); - } - } - - private async void DownloadAllNowMenuItem_OnClick(object sender, RoutedEventArgs e) - { - DownloadOption option = null; - if (BrowsingUser() && IsAtUploadCheckerPosition()) option = new DownloadOption {CreateNewWhenFromUser = Settings.Global.CreateNewFolderWhenDownloadFromUser}; - - await Task.Run(async () => - { - var source = await Dispatcher.InvokeAsync(GetImageSourceCopy); - foreach (var illustration in source) - if (illustration != null) - DownloadManager.EnqueueDownloadItem(illustration, option); - }); - MessageQueue.Enqueue(AkaI18N.QueuedAllToDownload); - } - - #endregion - - #region 用户预览 - - private void UserIllustsImageListView_OnPreviewMouseWheel(object sender, MouseWheelEventArgs e) - { - Scroll(UserBrowserPageScrollViewer, e); - } - - private void CloseUserBrowserAnimation_OnCompleted(object sender, EventArgs e) - { - UserBrowserPageScrollViewer.DataContext = null; - ReleaseImage(UserBrowserUserAvatar); - ReleaseItemsSource(UserIllustsImageListView); - } - - private async void PrivateFollow_OnClick(object sender, RoutedEventArgs e) - { - var usr = sender.GetDataContext(); - await PixivClient.Instance.FollowArtist(usr, RestrictPolicy.Private); - } - - private bool animating; - - private void ContentDisplay_OnMouseMove(object sender, MouseEventArgs e) - { - if (!(Navigating(GalleryTab) || Navigating(FollowingTab) || Navigating(RankingTab)) || animating) return; - var transform = (TranslateTransform) (Navigating(RankingTab) ? RankOptionSelector.RenderTransform : RestrictPolicySelector.RenderTransform); - if (e.GetPosition(this).Y <= 40 && Width - e.GetPosition(this).X >= 60) - TopBarExpand(transform); - else if (e.GetPosition(this).Y > 60) TopBarRetract(transform); - } - - private void PrivateRestrictPolicy_OnChecked(object sender, RoutedEventArgs e) - { - if (!IsLoaded) return; - if (Navigating(GalleryTab)) - { - MessageQueue.Enqueue(AkaI18N.SearchingGallery); - PixivHelper.Enumerate(AbstractGalleryAsyncEnumerable.Of(Session.Current.Id, RestrictPolicy.Private), NewItemsSource(ImageListView)); - } - else if (Navigating(FollowingTab)) - { - MessageQueue.Enqueue(AkaI18N.SearchingFollower); - PixivHelper.Enumerate(AbstractUserFollowingAsyncEnumerable.Of(Session.Current.Id, RestrictPolicy.Private), NewItemsSource(UserPreviewListView)); - } - } - - private void PublicRestrictPolicy_OnChecked(object sender, RoutedEventArgs e) - { - if (!IsLoaded) return; - if (Navigating(GalleryTab)) - { - MessageQueue.Enqueue(AkaI18N.SearchingGallery); - PixivHelper.Enumerate(AbstractGalleryAsyncEnumerable.Of(Session.Current.Id, RestrictPolicy.Public), NewItemsSource(ImageListView)); - } - else if (Navigating(FollowingTab)) - { - MessageQueue.Enqueue(AkaI18N.SearchingFollower); - PixivHelper.Enumerate(AbstractUserFollowingAsyncEnumerable.Of(Session.Current.Id, RestrictPolicy.Public), NewItemsSource(UserPreviewListView)); - } - } - - private void UserBrowserPageScrollViewer_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) - { - DeactivateControl(); - } - - private void UserPrevItem_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) - { - var usrDateContext = sender.GetDataContext(); - - SetUserBrowserContext(usrDateContext); - } - - private void SetupUserUploads(string id) - { - PixivHelper.Enumerate(new UploadAsyncEnumerable(id), NewItemsSource(UserIllustsImageListView)); - } - - private void SetupUserGallery(string id) - { - PixivHelper.Enumerate(AbstractGalleryAsyncEnumerable.Of(id, RestrictPolicy.Public), NewItemsSource(UserIllustsImageListView)); - } - - private async void UserPrevItem_OnLoaded(object sender, RoutedEventArgs e) - { - var (avatar, thumbnails) = GetUserPrevImageControls(sender); - var dataContext = sender.GetDataContext(); - - SetImageSource(avatar, await PixivIO.FromUrl(dataContext.Avatar)); - - var counter = 0; - foreach (var thumbnail in thumbnails) - if (counter < dataContext.Thumbnails.Length) - SetImageSource(thumbnail, await PixivIO.FromUrl(dataContext.Thumbnails[counter++])); - } - - private void UploadChecker_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) - { - if (!IsAtUploadCheckerPosition()) - UserBrowserPageScrollViewer.GetResources("CheckerIncreaseWidthAnimation").Apply(s => s.Completed += (o, args) => - { - CheckerSnackBar.HorizontalAlignment = HorizontalAlignment.Left; - UserBrowserPageScrollViewer.GetResources("CheckerDecreaseWidthAnimation").Begin(); - }).Begin(); - - SetupUserUploads(sender.GetDataContext().Id); - } - - private void GalleryChecker_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) - { - if (IsAtUploadCheckerPosition()) - UserBrowserPageScrollViewer.GetResources("CheckerIncreaseWidthAnimation").Apply(s => s.Completed += (o, args) => - { - CheckerSnackBar.HorizontalAlignment = HorizontalAlignment.Right; - UserBrowserPageScrollViewer.GetResources("CheckerDecreaseWidthAnimation").Begin(); - }).Begin(); - - SetupUserGallery(sender.GetDataContext().Id); - } - - private bool IsAtUploadCheckerPosition() - { - return CheckerSnackBar.HorizontalAlignment == HorizontalAlignment.Left && CheckerSnackBar.Width.Equals(100); - } - - private async void FollowButton_OnClick(object sender, RoutedEventArgs e) - { - var usr = sender.GetDataContext(); - await PixivClient.Instance.FollowArtist(usr, RestrictPolicy.Public); - } - - private async void UnFollowButton_OnClick(object sender, RoutedEventArgs e) - { - var usr = sender.GetDataContext(); - await PixivClient.Instance.UnFollowArtist(usr); - } - - private void ShareUserButton_OnPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) - { - Clipboard.SetDataObject($"https://www.pixiv.net/users/{sender.GetDataContext().Id}"); - MessageQueue.Enqueue(AkaI18N.ShareLinkCopiedToClipboard); - } - - - private void ViewUserInBrowserButton_OnPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) - { - Process.Start(new ProcessStartInfo("cmd", $"/c start https://www.pixiv.net/users/{sender.GetDataContext().Id}") {CreateNoWindow = true}); - } - - #endregion - - #region 作品浏览器 - - private async void SetAsWallPaperButton_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) - { - var trans = (IllustTransitioner) IllustBrowserContainer.Children[1]; - var transitions = (IEnumerable) trans.IllustTransition.ItemsSource; - var selectedIndex = transitions.ToList()[trans.IllustTransition.SelectedIndex]; - var location = Path.Combine(AppContext.PermanentlyFolder, "wallpaper.bmp"); - var wallPaper = new WallpaperManager(location, (BitmapSource) ((IllustPresenter) selectedIndex.Content).ImgSource); - await wallPaper.Execute(); - } - - private async void IllustBrowserDialogHost_OnDialogOpened(object sender, DialogOpenedEventArgs e) - { - var context = sender.GetDataContext(); - - var list = new ObservableCollection(); - - var template = new IllustTransitioner(list); - IllustBrowserContainer.Children.Insert(1, template); - - if (context.IsManga) - { - if (context.MangaMetadata.IsNullOrEmpty()) context = await PixivHelper.IllustrationInfo(context.Id); - list.AddRange(context.MangaMetadata.Select(InitTransitionerSlide)); - } - else - { - list.Add(InitTransitionerSlide(context)); - } - } - - private static TransitionerSlide InitTransitionerSlide(Illustration illust) - { - return new TransitionerSlide {ForwardWipe = new FadeWipe(), BackwardWipe = new FadeWipe(), Content = new IllustPresenter(illust)}; - } - - private void IllustBrowserDialogHost_OnDialogClosing(object sender, DialogClosingEventArgs e) - { - IllustBrowserContainer.Children.RemoveAt(1); - ReleaseImage(IllustBrowserUserAvatar); - IllustBrowserDialogHost.DataContext = null; - } - - private async void TagNavigateHyperlink_OnClick(object sender, RoutedEventArgs e) - { - var txt = ((Tag) ((Hyperlink) sender).DataContext).Name; - - if (!UserBrowserPageScrollViewer.Opacity.Equals(0)) BackToMainPageButton.RaiseEvent(new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, MouseButton.Left) {RoutedEvent = Mouse.MouseDownEvent, Source = this}); - - IllustBrowserDialogHost.CurrentSession.Close(); - NavigatorList.SelectedItem = Instance.MenuTab; - - await Task.Delay(300); - KeywordTextBox.Text = txt; - } - - private void ShareButton_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) - { - Clipboard.SetDataObject($"https://www.pixiv.net/artworks/{sender.GetDataContext().Id}"); - MessageQueue.Enqueue(AkaI18N.ShareLinkCopiedToClipboard); - } - - private void ImageBrowserUserAvatar_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) - { - var usr = new User {Id = sender.GetDataContext().UserId}; - IllustBrowserDialogHost.CurrentSession.Close(); - SetUserBrowserContext(usr); - } - - private void ViewInBrowserButton_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) - { - Process.Start(new ProcessStartInfo("cmd", $"/c start https://www.pixiv.net/artworks/{sender.GetDataContext().Id}") {CreateNoWindow = true}); - } - - private void DownloadButton_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) - { - DownloadManager.EnqueueDownloadItem(sender.GetDataContext()); - MessageQueue.Enqueue(AkaI18N.QueuedDownload); - } - - private void IllustBrowserFavorButton_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) - { - PixivClient.Instance.PostFavoriteAsync(sender.GetDataContext(), RestrictPolicy.Public); - } - - private void IllustBrowserPrivateFavorButton_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) - { - PixivClient.Instance.PostFavoriteAsync(sender.GetDataContext(), RestrictPolicy.Private); - } - - private void IllustBrowserDisfavorButton_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) - { - PixivClient.Instance.RemoveFavoriteAsync(sender.GetDataContext()); - } - - #endregion - - #region 动态 - - private async void ReferImage_OnLoaded(object sender, RoutedEventArgs e) - { - var trend = sender.GetDataContext(); - var img = (Image) sender; - if (trend.IsReferToUser) img.Effect = new BlurEffect {KernelType = KernelType.Gaussian, Radius = 50, RenderingBias = RenderingBias.Quality}; - - SetImageSource(sender, await PixivIO.FromUrl(trend.TrendObjectThumbnail)); - } - - private async void ReferUserAvatar_OnLoaded(object sender, RoutedEventArgs e) - { - var trend = sender.GetDataContext(); - if (trend.IsReferToUser) SetImageSource(sender, await PixivIO.FromUrl(trend.TrendObjectThumbnail)); - } - - private async void PostUserAvatar_OnLoaded(object sender, RoutedEventArgs e) - { - SetImageSource(sender, await PixivIO.FromUrl(sender.GetDataContext().PostUserThumbnail)); - } - - private void TrendsTab_OnSelected(object sender, RoutedEventArgs e) - { - QueryStartUp(); - MessageQueue.Enqueue(AkaI18N.SearchingTrends); - - PixivHelper.Enumerate(new TrendsAsyncEnumerable(), NewItemsSource(TrendsListView), 20); - } - - private async void ReferImage_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) - { - OpenIllustBrowser(await PixivHelper.IllustrationInfo(sender.GetDataContext().TrendObjectId)); - e.Handled = true; - } - - private void ReferUser_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) - { - OpenUserBrowser(); - SetUserBrowserContext(new User {Id = sender.GetDataContext().TrendObjectId}); - e.Handled = true; - } - - private void Hyperlink_OnClick(object sender, RoutedEventArgs e) - { - OpenUserBrowser(); - SetUserBrowserContext(new User {Id = ((Trends) ((Hyperlink) sender).DataContext).PostUserId}); - e.Handled = true; - } - - #endregion - - #region 榜单 - - private void RankDatePicker_OnSelectedDateChanged(object sender, SelectionChangedEventArgs e) - { - if (Navigating(RankingTab)) GetRanking(); - } - - private void RankOptionPicker_OnSelectionChanged(object sender, SelectionChangedEventArgs e) - { - if (Navigating(RankingTab)) GetRanking(); - } - - private void GetRanking() - { - var option = RankOptionPicker.SelectedItem.GetDataContext().First(p => p.IsSelected); - var dateTime = RankDatePicker.SelectedDate; - - if (option.Corresponding.AttributeAttached() && Settings.Global.ExcludeTag.Any(t => t.ToUpper() == "R-18" || t.ToUpper() == "R-18G")) - { - MessageQueue.Enqueue(AkaI18N.RankNeedR18On); - NewItemsSource(ImageListView); - return; - } - - if (dateTime is { } time) - { - PixivHelper.Enumerate(new RankingAsyncEnumerable(option.Corresponding, time), NewItemsSource(ImageListView)); - return; - } - - MessageQueue.Enqueue(AkaI18N.RankDateCannotBeNull); - } - - private void RankingTab_OnSelected(object sender, RoutedEventArgs e) - { - GetRanking(); - } - - #endregion - - #region 工具 - - private void TopBarRetract(TranslateTransform transform) - { - if (transform.Y > -60) - { - var animation = new DoubleAnimation(transform.Y, -60, TimeSpan.FromMilliseconds(300)) {EasingFunction = new CubicEase()}; - animation.Completed += (o, args) => animating = false; - animating = true; - transform.BeginAnimation(TranslateTransform.YProperty, animation); - } - } - - private void TopBarExpand(TranslateTransform transform) - { - if (transform.Y < 0) - { - var animation = new DoubleAnimation(transform.Y, 0, TimeSpan.FromMilliseconds(300)) {EasingFunction = new CubicEase()}; - animation.Completed += (o, args) => animating = false; - animating = true; - transform.BeginAnimation(TranslateTransform.YProperty, animation); - } - } - - private async Task AcquireRecommendUser() - { - var list = NewItemsSource(RecommendIllustratorListBox); - list.AddRange(await RecommendIllustratorDeferrer.Instance.Acquire(6)); - } - - private IEnumerable GetImageSourceCopy() - { - var lst = (IEnumerable) (BrowsingUser() ? UserIllustsImageListView : ImageListView)?.ItemsSource; - return lst != null ? lst.ToList() : new List(); - } - - private void QueryStartUp() - { - MenuTab.IsSelected = false; - HomeContainerMoveDown(); - } - - private bool BrowsingUser() - { - return !UserBrowserPageScrollViewer.Opacity.Equals(0D); - } - - private static (Image avatar, Image[] thumbnails) GetUserPrevImageControls(object sender) - { - var list = ((Card) sender).FindVisualChildren().ToArray(); - - return (list.First(p => p.Name == "UserAvatar"), list.Where(p => p.Name != "UserAvatar").ToArray()); - } - - public async void SetUserBrowserContext(User user) - { - var usr = await HttpClientFactory.AppApiService().GetUserInformation(new UserInformationRequest {Id = $"{user.Id}"}); - var usrEntity = new User - { - Avatar = usr.UserEntity.ProfileImageUrls.Medium, - Background = usr.UserEntity.ProfileImageUrls.Medium, - Follows = (int) usr.UserProfile.TotalFollowUsers, - Id = usr.UserEntity.Id.ToString(), - Introduction = usr.UserEntity.Comment, - IsFollowed = usr.UserEntity.IsFollowed, - IsPremium = usr.UserProfile.IsPremium, - Name = usr.UserEntity.Name, - Thumbnails = user.Thumbnails - }; - PixivHelper.RecordTimelineInternal(new BrowsingHistory - { - BrowseObjectId = usrEntity.Id, - BrowseObjectState = usrEntity.Name, - BrowseObjectThumbnail = usrEntity.Avatar, - IsReferToUser = true, - Type = "user" - }); - UserBrowserPageScrollViewer.DataContext = usrEntity; - SetImageSource(UserBrowserUserAvatar, await PixivIO.FromUrl(usrEntity.Avatar)); - SetupUserUploads(usrEntity.Id); - } - - public void OpenUserBrowser() - { - this.GetResources("OpenUserBrowserAnimation").Begin(); - } - - public async void OpenIllustBrowser(Illustration illustration, bool record = true) - { - if (!illustration.FromSpotlight && record) - PixivHelper.RecordTimelineInternal(new BrowsingHistory - { - BrowseObjectId = illustration.Id, - BrowseObjectState = illustration.Title, - BrowseObjectThumbnail = illustration.Thumbnail, - IllustratorName = illustration.UserName, - IsReferToIllust = true, - Type = "illust" - }); - - IllustBrowserDialogHost.DataContext = illustration; - await Task.Delay(100); - IllustBrowserDialogHost.OpenControl(); - var userInfo = await HttpClientFactory.AppApiService().GetUserInformation(new UserInformationRequest {Id = illustration.UserId}); - if (await PixivIO.FromUrl(userInfo.UserEntity.ProfileImageUrls.Medium) is { } avatar) SetImageSource(IllustBrowserUserAvatar, avatar); - } - - private bool Navigating(ListViewItem item) - { - return NavigatorList.SelectedItem?.Equals(item) is true; - } - - #endregion - } -} \ No newline at end of file diff --git a/src/Pixeval/UI/SignIn.xaml b/src/Pixeval/UI/SignIn.xaml deleted file mode 100644 index 298f40f2..00000000 --- a/src/Pixeval/UI/SignIn.xaml +++ /dev/null @@ -1,153 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Pixeval/UI/UserControls/UserPreviewPopupContent.xaml.cs b/src/Pixeval/UI/UserControls/UserPreviewPopupContent.xaml.cs deleted file mode 100644 index d703cb59..00000000 --- a/src/Pixeval/UI/UserControls/UserPreviewPopupContent.xaml.cs +++ /dev/null @@ -1,65 +0,0 @@ -#region Copyright (C) 2019-2020 Dylech30th. All rights reserved. - -// Pixeval - A Strong, Fast and Flexible Pixiv Client -// Copyright (C) 2019-2020 Dylech30th -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#endregion - -using System.Windows; -using System.Windows.Media.Imaging; -using Pixeval.Core; -using Pixeval.Data.ViewModel; -using Pixeval.Data.Web.Delegation; -using Pixeval.Objects.Primitive; - -namespace Pixeval.UI.UserControls -{ - public partial class UserPreviewPopupContent - { - public UserPreviewPopupContent() - { - InitializeComponent(); - } - - public async void SetImages(BitmapImage left, BitmapImage center, BitmapImage right) - { - UiHelper.SetImageSource(ImgLeft, left); - UiHelper.SetImageSource(ImgCenter, center); - UiHelper.SetImageSource(ImgRight, right); - UiHelper.SetImageSource(UserAvatar, await PixivIO.FromUrl(this.GetDataContext().Avatar)); - try - { - UiHelper.SetImageSource(Banner, await PixivIO.FromUrl((await HttpClientFactory.WebApiService().GetWebApiUserDetail(this.GetDataContext().Id)).ResponseBody.UserDetails.CoverImage.ProfileCoverImage.The720X360)); - } - catch - { - /* ignore */ - } - } - - private async void FollowButton_OnClick(object sender, RoutedEventArgs e) - { - var usr = sender.GetDataContext(); - await PixivClient.Instance.FollowArtist(usr, RestrictPolicy.Public); - } - - private async void UnFollowButton_OnClick(object sender, RoutedEventArgs e) - { - var usr = sender.GetDataContext(); - await PixivClient.Instance.UnFollowArtist(usr); - } - } -} \ No newline at end of file diff --git a/src/Pixeval/app.manifest b/src/Pixeval/app.manifest deleted file mode 100644 index b90e8a86..00000000 --- a/src/Pixeval/app.manifest +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Pixeval/build.ps1 b/src/Pixeval/build.ps1 deleted file mode 100644 index 5c81abc6..00000000 --- a/src/Pixeval/build.ps1 +++ /dev/null @@ -1 +0,0 @@ -dotnet publish /p:Platform=x64 Pixeval.csproj -c Release -f netcoreapp3.1 --no-self-contained -r win-x64 \ No newline at end of file diff --git a/src/pixeval-backend/.gradle/6.1/executionHistory/executionHistory.bin b/src/pixeval-backend/.gradle/6.1/executionHistory/executionHistory.bin deleted file mode 100644 index ee87eb4a86a30deaa465db00850dfaf5b5bec5e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 111278 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

Uph9s(rD6%xez;YpRrqD(i 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 diff --git a/src/pixeval-backend/.gradle/6.1/executionHistory/executionHistory.lock b/src/pixeval-backend/.gradle/6.1/executionHistory/executionHistory.lock deleted file mode 100644 index 3f07ddbd9231869b9a85d3a9ce904836a7a16285..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17 UcmZRc{XNw5yT!`W3=psy06ZuKZU6uP diff --git a/src/pixeval-backend/.gradle/6.1/fileChanges/last-build.bin b/src/pixeval-backend/.gradle/6.1/fileChanges/last-build.bin deleted file mode 100644 index f76dd238ade08917e6712764a16a22005a50573d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1 IcmZPo000310RR91 diff --git a/src/pixeval-backend/.gradle/6.1/fileContent/fileContent.lock b/src/pixeval-backend/.gradle/6.1/fileContent/fileContent.lock deleted file mode 100644 index 75415ad32d703614310c019db9db55cdc882cebc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17 TcmZQR?7nE4bw&AZ1}FdkG&}?= diff --git a/src/pixeval-backend/.gradle/6.1/fileHashes/fileHashes.bin b/src/pixeval-backend/.gradle/6.1/fileHashes/fileHashes.bin deleted file mode 100644 index 1de68a54167f5ba3a3f88d6b878fbf3f3de848c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20847 zcmeI4dpK0<9>-_IFh+6>soiB$$$b|F+j-K(ogwMQjzo^aj!N}RWn)K?5#=0;a4MHl zZY2?8XN$xsqHOnTHz^cKnDefA*P6Y}^56dNJn#EFvu2*pyx;YE-_N@6Jl1Oyg`zCO z!yDz#rugSa^a&Y229N<{02x3AkO5=>89)Y*0b~FfKn9QjWB?gJ29N<{02x3A{$C8Z zfQd-L$tY`yU>_D7rBL*wzz5wZr;om+issSqYiobv?+4LxERV^n5j8kZC3rk1$3wKS zPYH6HX#r2(=JvJK?JUlp5Inh@ySM-CLodi}_YgcS=BaDDS#34stXl%!rrULq8CHb% z*Clw?roGJgA^iZzoy-WHt3BF$t=FO!ayt!z=XG3IBf$y(0do8A1-$b;kM8@z29D!3(FjEtP?<&q2NvmKY-H=-yBKY{1*WzL#&5I#-SVC|~ z=gz*y_ir2^cl<-ZUHet8P3z-+oEQXWEKHa6ylVdi_P28-_(I3EJ)<@SckuljA-GaS z$uYNF!yLRWOTe47ly?<{YeH`0L-6lhUTz66n!E-%ONrns!awA#($~fJW8FY-o$UeR z!!FTl@%;}F-0<>^{H}Zbt&rQh5Zvgq-~P^l&)$$b$`ahz(p>T>&G0Vdb}<4TmXSDF z&>sQ0?FE9H%UUpR@=6mSw|YtNjlae|y|g=bALKSk1h*XeCug$Wvy9Kr?wCpNL#aQ0b&ugJgWREz;Kz=gmh(%i9EaRyo`Cmq^}au# zod>yX6~WnsvGvCL+8QBebqV;hXEEkGI`i@U7!W*Uq)si;DJdOttLp?O-YFE(89)Y*0b~FfKn9QjWB?gJ29N<{02x3AkO5=>89)Y* z0b~FfKn9QjWB?gJ29N<{02x3Akb%Er0DJga1H6`FFBz`x0)x8p;Y|Of5+knbGm0q` zYLHsFlrgNpI0fEyW+y_*HIt5#OAXG!+r21iTgG2>qpDBfc+Hod6Dm6H&g};&$eSz^Vp)u!NKk3P| zCCrxvPjrKMd^{xv6Owa`%F~UK{j+L(EDiJ6Tsu?&n-*j0B$-@5X8+WrG}v~NSybzltun7JUa#)O<`%H8|O z=A`l4gA(oH^2=L>@x%sLL)({}$c|G`uwkz7QAkr#8x!V)?5mtTVM6hO{w8c}_;UrCUIlKnGPDC7A4pB=n0zs4zLlb z(HXZ!N@TeE)JmV?U}l~sSp5QyAW#1VKR^+|R-XtZMpN$6R@39v?+2Jw4oh!NnVq0t zASdR#1q7wnimPULNR*t~`9zzan3z5bYcSrB6Y-|Sg?jJyoNqXkVtw|JUl2_2@Fhkx z?Ej4kjVk(eylKxCZ?*j`Yl~GXmxSX92CPB6aMySTk@ukXB-YN6NCP!)MQ+~bpsK7hcXxK(5ar$NuYh>#;jfL#} zY8Gm0Z)YdyW8?(Kp=RjC#uZ*YEu{vGd^E@rK?PQ>x2>> zk#+qmB;sbJHf=-+_BM|Cr;hB-O}?dhd|wHCdwDJEC@V~e9h*10HuPR~+)V&4Y* zs+}w0H58j*PhF?A{lp@JpsfD-*@?N1$I;8dDc4Uv>hxjt*}f^=1Fi=!DnX68j>oW^ z&wDH5V*eiJC)M8>1=`?=DE>4ka~+RX6RO1zW(TFSi&EN(ZUt->N_dcG{>$o`A7k6w zO`JYNwpiUsSdS&l66yF)PP!>MQJ~r~etRFK;^M8mmCl;2{JW3YCHHTjC)Vcp4Itl( g+o|LyX1DmQ!)N8BE(v~(OWtgL|Ndlb^_0&40O}o|H~;_u diff --git a/src/pixeval-backend/.gradle/6.1/fileHashes/fileHashes.lock b/src/pixeval-backend/.gradle/6.1/fileHashes/fileHashes.lock deleted file mode 100644 index 9633c7a3a27b095804407b7c8e31b55115a791f0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17 VcmZQpfA76h>+Q4O3}C>h2LL=;1w{Y= diff --git a/src/pixeval-backend/.gradle/6.1/gc.properties b/src/pixeval-backend/.gradle/6.1/gc.properties deleted file mode 100644 index e69de29b..00000000 diff --git a/src/pixeval-backend/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/src/pixeval-backend/.gradle/buildOutputCleanup/buildOutputCleanup.lock deleted file mode 100644 index 86c7dc8104479cc81ee1d201eb0af06f9a9a9797..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17 UcmZSHx8U&q<-!H=3=j|p06p6U3jhEB diff --git a/src/pixeval-backend/.gradle/buildOutputCleanup/cache.properties b/src/pixeval-backend/.gradle/buildOutputCleanup/cache.properties deleted file mode 100644 index 462689eb..00000000 --- a/src/pixeval-backend/.gradle/buildOutputCleanup/cache.properties +++ /dev/null @@ -1,2 +0,0 @@ -#Mon May 18 06:25:33 CST 2020 -gradle.version=6.1 diff --git a/src/pixeval-backend/.gradle/buildOutputCleanup/outputFiles.bin b/src/pixeval-backend/.gradle/buildOutputCleanup/outputFiles.bin deleted file mode 100644 index 06a7de032d700dd48e4b2b3b49a965d793b6912f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18839 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 diff --git a/src/pixeval-backend/.gradle/checksums/sha1-checksums.bin b/src/pixeval-backend/.gradle/checksums/sha1-checksums.bin deleted file mode 100644 index 2eca42b1f3434e73910c6bc9d7e25a294a4da8dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33779 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 - - - - - - - - - \ No newline at end of file diff --git a/src/pixeval-backend/.idea/codeStyles/codeStyleConfig.xml b/src/pixeval-backend/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123c..00000000 --- a/src/pixeval-backend/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/pixeval-backend/.idea/compiler.xml b/src/pixeval-backend/.idea/compiler.xml deleted file mode 100644 index 61a9130c..00000000 --- a/src/pixeval-backend/.idea/compiler.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/src/pixeval-backend/.idea/dictionaries/26532.xml b/src/pixeval-backend/.idea/dictionaries/26532.xml deleted file mode 100644 index 9ff59430..00000000 --- a/src/pixeval-backend/.idea/dictionaries/26532.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - pixeval - - - \ No newline at end of file diff --git a/src/pixeval-backend/.idea/gradle.xml b/src/pixeval-backend/.idea/gradle.xml deleted file mode 100644 index 13a8247e..00000000 --- a/src/pixeval-backend/.idea/gradle.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/src/pixeval-backend/.idea/jarRepositories.xml b/src/pixeval-backend/.idea/jarRepositories.xml deleted file mode 100644 index fdc392fe..00000000 --- a/src/pixeval-backend/.idea/jarRepositories.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/src/pixeval-backend/.idea/misc.xml b/src/pixeval-backend/.idea/misc.xml deleted file mode 100644 index 2266f6bc..00000000 --- a/src/pixeval-backend/.idea/misc.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/src/pixeval-backend/.idea/workspace.xml b/src/pixeval-backend/.idea/workspace.xml deleted file mode 100644 index 7f164012..00000000 --- a/src/pixeval-backend/.idea/workspace.xml +++ /dev/null @@ -1,313 +0,0 @@ - - - - - - - - - - - - - - - - - - -