diff --git a/.github/workflows/dotnet-desktop.yml b/.github/workflows/dotnet-desktop.yml
new file mode 100644
index 0000000..9b5ed4c
--- /dev/null
+++ b/.github/workflows/dotnet-desktop.yml
@@ -0,0 +1,117 @@
+# This workflow uses actions that are not certified by GitHub.
+# They are provided by a third-party and are governed by
+# separate terms of service, privacy policy, and support
+# documentation.
+
+# This workflow will build, test, sign and package a WPF or Windows Forms desktop application
+# built on .NET Core.
+# To learn how to migrate your existing application to .NET Core,
+# refer to https://docs.microsoft.com/en-us/dotnet/desktop-wpf/migration/convert-project-from-net-framework
+#
+# To configure this workflow:
+#
+# 1. Configure environment variables
+# GitHub sets default environment variables for every workflow run.
+# Replace the variables relative to your project in the "env" section below.
+#
+# 2. Signing
+# Generate a signing certificate in the Windows Application
+# Packaging Project or add an existing signing certificate to the project.
+# Next, use PowerShell to encode the .pfx file using Base64 encoding
+# by running the following Powershell script to generate the output string:
+#
+# $pfx_cert = Get-Content '.\SigningCertificate.pfx' -Encoding Byte
+# [System.Convert]::ToBase64String($pfx_cert) | Out-File 'SigningCertificate_Encoded.txt'
+#
+# Open the output file, SigningCertificate_Encoded.txt, and copy the
+# string inside. Then, add the string to the repo as a GitHub secret
+# and name it "Base64_Encoded_Pfx."
+# For more information on how to configure your signing certificate for
+# this workflow, refer to https://github.com/microsoft/github-actions-for-desktop-apps#signing
+#
+# Finally, add the signing certificate password to the repo as a secret and name it "Pfx_Key".
+# See "Build the Windows Application Packaging project" below to see how the secret is used.
+#
+# For more information on GitHub Actions, refer to https://github.com/features/actions
+# For a complete CI/CD sample to get started with GitHub Action workflows for Desktop Applications,
+# refer to https://github.com/microsoft/github-actions-for-desktop-apps
+
+name: .NET Core Desktop
+
+on:
+ push:
+ tags:
+ - 'v*.*.*' # 仅在推送版本标签时触发
+
+jobs:
+
+ build:
+
+ strategy:
+ matrix:
+ configuration: [ Release]
+
+ runs-on: windows-latest # For a list of available runner types, refer to
+ # https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on
+
+ env:
+ Solution_Name: src/BlueCatKoKo.sln # Replace with your solution name, i.e. MyWpfApp.sln.
+ Wap_Project_Directory: src/BlueCatKoKo.Ui/ # Replace with the Wap project directory relative to the solution, i.e. MyWpfApp.Package.
+ Wap_Project_Path: src/BlueCatKoKo.Ui/BlueCatKoKo.Ui.csproj # Replace with the path to your Wap project, i.e. MyWpf.App.Package\MyWpfApp.Package.wapproj.
+ Wap_Project_Release_Directory: src/BlueCatKoKo.Ui/bin/Release/net8.0-windows
+ App_Name: BlueCatKoKo
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Install .NET Core
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: 8.0.x
+
+ - name: Restore NuGet Packages
+ run: dotnet restore $env:Solution_Name
+
+ - name: Setup MSBuild.exe
+ uses: microsoft/setup-msbuild@v2
+
+ - name: Restore the application
+ run: msbuild $env:Solution_Name /t:Restore /p:Configuration=$env:Configuration
+ env:
+ Configuration: ${{ matrix.configuration }}
+
+ - name: Decode the pfx
+ run: |
+ $pfx_cert_byte = [System.Convert]::FromBase64String("${{ secrets.Base64_Encoded_Pfx }}")
+ $certificatePath = Join-Path -Path $env:Wap_Project_Directory -ChildPath GitHubActionsWorkflow.pfx
+ [IO.File]::WriteAllBytes("$certificatePath", $pfx_cert_byte)
+
+ - name: Create the app package
+ run: msbuild $env:Wap_Project_Path /p:Configuration=$env:Configuration /p:UapAppxPackageBuildMode=$env:Appx_Package_Build_Mode /p:AppxBundle=$env:Appx_Bundle /p:PackageCertificateKeyFile=GitHubActionsWorkflow.pfx /p:PackageCertificatePassword=${{ secrets.Pfx_Key }}
+ env:
+ Appx_Bundle: Always
+ Appx_Bundle_Platforms: x86|x64
+ Appx_Package_Build_Mode: StoreUpload
+ Configuration: ${{ matrix.configuration }}
+
+ - name: Remove the pfx
+ run: Remove-Item -path $env:Wap_Project_Directory\GitHubActionsWorkflow.pfx
+
+ - name: Create ZIP file
+ run: |
+ Compress-Archive -Path $env:Wap_Project_Release_Directory/* -DestinationPath $env:Wap_Project_Release_Directory/$env:App_Name.zip
+
+ - name: Upload build artifacts
+ uses: actions/upload-artifact@v3
+ with:
+ name: ${{ env.App_Name }}
+ path: ${{ env.Wap_Project_Release_Directory }}/${{ env.App_Name }}.zip
+
+ - name: Release
+ uses: softprops/action-gh-release@v2
+ if: startsWith(github.ref, 'refs/tags/')
+ with:
+ files: ${{ env.Wap_Project_Release_Directory }}/${{ env.App_Name }}.zip
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..4f27a85
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,8 @@
+### Example user template template
+### Example user template
+
+# IntelliJ project files
+.idea
+*.iml
+out
+gen
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..89ae041
--- /dev/null
+++ b/README.md
@@ -0,0 +1,16 @@
+# 蓝猫KoKo下载器
+
+![_20240824121208.png](https://s2.loli.net/2024/08/24/DnSyxsaIHd972oL.jpg)
+
+蓝猫KoKo下载器(BlueCatKoKo)是一个简单易用的抖音视频下载工具,具有简洁的界面,流畅的操作逻辑。可以下载几乎所有的抖音视频,并输出mp4格式的文件。
+> 因为包含了LibVLC库播放视频,所以比较大
+## 下载
+https://github.com/K12f/BlueCatKoKo/releases
+
+## 免责申明
+
+1. 本软件只提供视频解析,不提供任何资源上传、存储到服务器的功能。
+2. 本软件仅解析来自抖音的内容,不会对解析到的音视频进行二次编码,部分视频会进行有限的格式转换、拼接等操作。
+3. 本软件解析得到的所有内容均来自抖音UP主上传、分享,其版权均归原作者所有。内容提供者、上传者(UP主)应对其提供、上传的内容承担全部责任。
+4. **本软件提供的所有内容,仅可用作学习交流使用,未经原作者授权,禁止用于其他用途。请在下载24小时内删除。为尊重作者版权,请前往资源的原始发布网站观看,支持原创,谢谢。**
+5. 因使用本软件产生的版权问题,软件作者概不负责。
diff --git a/src/.gitignore b/src/.gitignore
new file mode 100644
index 0000000..0890165
--- /dev/null
+++ b/src/.gitignore
@@ -0,0 +1,401 @@
+### Csharp template
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.tlog
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+*.ncb
+*.aps
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# Visual Studio History (VSHistory) files
+.vshistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# VS Code files for those working on multiple tools
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
+
+.idea
diff --git a/src/BlueCatKoKo.Ui/.gitignore b/src/BlueCatKoKo.Ui/.gitignore
new file mode 100644
index 0000000..5e8067b
--- /dev/null
+++ b/src/BlueCatKoKo.Ui/.gitignore
@@ -0,0 +1,801 @@
+### Csharp template
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.tlog
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+*.ncb
+*.aps
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# Visual Studio History (VSHistory) files
+.vshistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# VS Code files for those working on multiple tools
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
+
+.idea### Csharp template
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.tlog
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+*.ncb
+*.aps
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# Visual Studio History (VSHistory) files
+.vshistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# VS Code files for those working on multiple tools
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
+
+.idea
\ No newline at end of file
diff --git a/src/BlueCatKoKo.Ui/App.xaml b/src/BlueCatKoKo.Ui/App.xaml
new file mode 100644
index 0000000..bd6d013
--- /dev/null
+++ b/src/BlueCatKoKo.Ui/App.xaml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/BlueCatKoKo.Ui/App.xaml.cs b/src/BlueCatKoKo.Ui/App.xaml.cs
new file mode 100644
index 0000000..4230440
--- /dev/null
+++ b/src/BlueCatKoKo.Ui/App.xaml.cs
@@ -0,0 +1,120 @@
+using System.Windows;
+using System.Windows.Threading;
+
+using BlueCatKoKo.Ui.Models;
+using BlueCatKoKo.Ui.Services;
+using BlueCatKoKo.Ui.ViewModels;
+using BlueCatKoKo.Ui.ViewModels.Pages;
+using BlueCatKoKo.Ui.Views;
+using BlueCatKoKo.Ui.Views.Pages;
+
+using CommunityToolkit.Mvvm.Messaging;
+
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+
+using Serilog;
+
+using Wpf.Ui;
+
+using HomeViewModel = BlueCatKoKo.Ui.ViewModels.Pages.HomeViewModel;
+using LogLevel = Microsoft.Extensions.Logging.LogLevel;
+
+namespace BlueCatKoKo.Ui
+{
+ using HomeViewModel = ViewModels.Pages.HomeViewModel;
+
+ ///
+ /// Interaction logic for App.xaml
+ ///
+ public partial class App : Application
+ {
+ private static readonly IHost _host = Host.CreateDefaultBuilder()
+ .ConfigureHostConfiguration(builder =>
+ {
+ // builder.AddJsonFile("appsettings.json");
+ })
+ .ConfigureLogging(logging =>
+ {
+ logging.ClearProviders();
+ Log.Logger = new LoggerConfiguration()
+ .WriteTo.Console()
+ .WriteTo.File("log.txt", rollingInterval: RollingInterval.Day)
+ .CreateLogger();
+ logging.Services.AddSingleton(Log.Logger);
+ })
+ .ConfigureServices((context, container) =>
+ {
+ container.AddHostedService();
+ // configuration
+ container.Configure(context.Configuration.GetSection(nameof(AppConfig)));
+ container.AddSingleton();
+
+ // Service containing
+ container.AddSingleton();
+ container.AddSingleton();
+
+ // Main window with navigation
+ container.AddSingleton();
+ container.AddSingleton();
+
+
+ //view and viewmodels
+ container.AddSingleton();
+ container.AddSingleton();
+
+ container.AddSingleton();
+ container.AddSingleton();
+
+ container.AddSingleton();
+ container.AddSingleton();
+
+ container.AddSingleton();
+ container.AddSingleton();
+
+ container.AddSingleton();
+ container.AddSingleton();
+
+ // messager
+ container.AddSingleton();
+ container.AddSingleton(sp => sp.GetRequiredService());
+
+ container.AddSingleton(_ => Current.Dispatcher);
+ }).Build();
+
+ public static new App Current => (App)Application.Current;
+
+ ///
+ /// Gets services.
+ ///
+ public static IServiceProvider Services => _host.Services;
+
+
+ ///
+ /// Occurs when the application is loading.
+ ///
+ private async void OnStartup(object sender, StartupEventArgs e)
+ {
+ await _host.StartAsync();
+ }
+
+ ///
+ /// Occurs when the application is closing.
+ ///
+ private async void OnExit(object sender, ExitEventArgs e)
+ {
+ await _host.StopAsync();
+
+ _host.Dispose();
+ }
+
+ ///
+ /// Occurs when an exception is thrown by an application but not handled.
+ ///
+ private void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
+ {
+ // For more info see https://docs.microsoft.com/en-us/dotnet/api/system.windows.application.dispatcherunhandledexception?view=windowsdesktop-6.0
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/BlueCatKoKo.Ui/AssemblyInfo.cs b/src/BlueCatKoKo.Ui/AssemblyInfo.cs
new file mode 100644
index 0000000..4a05c7d
--- /dev/null
+++ b/src/BlueCatKoKo.Ui/AssemblyInfo.cs
@@ -0,0 +1,10 @@
+using System.Windows;
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
\ No newline at end of file
diff --git a/src/BlueCatKoKo.Ui/Assets/applicationicon.jpg b/src/BlueCatKoKo.Ui/Assets/applicationicon.jpg
new file mode 100644
index 0000000..774677a
Binary files /dev/null and b/src/BlueCatKoKo.Ui/Assets/applicationicon.jpg differ
diff --git a/src/BlueCatKoKo.Ui/Assets/douyin.js b/src/BlueCatKoKo.Ui/Assets/douyin.js
new file mode 100644
index 0000000..357c508
--- /dev/null
+++ b/src/BlueCatKoKo.Ui/Assets/douyin.js
@@ -0,0 +1,434 @@
+// All the content in this article is only for learning and communication use, not for any other purpose, strictly prohibited for commercial use and illegal use, otherwise all the consequences are irrelevant to the author!
+function rc4_encrypt(plaintext, key) {
+ var s = [];
+ for (var i = 0; i < 256; i++) {
+ s[i] = i;
+ }
+ var j = 0;
+ for (var i = 0; i < 256; i++) {
+ j = (j + s[i] + key.charCodeAt(i % key.length)) % 256;
+ var temp = s[i];
+ s[i] = s[j];
+ s[j] = temp;
+ }
+
+ var i = 0;
+ var j = 0;
+ var cipher = [];
+ for (var k = 0; k < plaintext.length; k++) {
+ i = (i + 1) % 256;
+ j = (j + s[i]) % 256;
+ var temp = s[i];
+ s[i] = s[j];
+ s[j] = temp;
+ var t = (s[i] + s[j]) % 256;
+ cipher.push(String.fromCharCode(s[t] ^ plaintext.charCodeAt(k)));
+ }
+ return cipher.join('');
+}
+
+function le(e, r) {
+ return (e << (r %= 32) | e >>> 32 - r) >>> 0
+}
+
+function de(e) {
+ return 0 <= e && e < 16 ? 2043430169 : 16 <= e && e < 64 ? 2055708042 : void console['error']("invalid j for constant Tj")
+}
+
+function pe(e, r, t, n) {
+ return 0 <= e && e < 16 ? (r ^ t ^ n) >>> 0 : 16 <= e && e < 64 ? (r & t | r & n | t & n) >>> 0 : (console['error']('invalid j for bool function FF'),
+ 0)
+}
+
+function he(e, r, t, n) {
+ return 0 <= e && e < 16 ? (r ^ t ^ n) >>> 0 : 16 <= e && e < 64 ? (r & t | ~r & n) >>> 0 : (console['error']('invalid j for bool function GG'),
+ 0)
+}
+
+function reset() {
+ this.reg[0] = 1937774191,
+ this.reg[1] = 1226093241,
+ this.reg[2] = 388252375,
+ this.reg[3] = 3666478592,
+ this.reg[4] = 2842636476,
+ this.reg[5] = 372324522,
+ this.reg[6] = 3817729613,
+ this.reg[7] = 2969243214,
+ this["chunk"] = [],
+ this["size"] = 0
+}
+
+function write(e) {
+ var a = "string" == typeof e ? function (e) {
+ n = encodeURIComponent(e)['replace'](/%([0-9A-F]{2})/g, (function (e, r) {
+ return String['fromCharCode']("0x" + r)
+ }
+ ))
+ , a = new Array(n['length']);
+ return Array['prototype']['forEach']['call'](n, (function (e, r) {
+ a[r] = e.charCodeAt(0)
+ }
+ )),
+ a
+ }(e) : e;
+ this.size += a.length;
+ var f = 64 - this['chunk']['length'];
+ if (a['length'] < f)
+ this['chunk'] = this['chunk'].concat(a);
+ else
+ for (this['chunk'] = this['chunk'].concat(a.slice(0, f)); this['chunk'].length >= 64;)
+ this['_compress'](this['chunk']),
+ f < a['length'] ? this['chunk'] = a['slice'](f, Math['min'](f + 64, a['length'])) : this['chunk'] = [],
+ f += 64
+}
+
+function sum(e, t) {
+ e && (this['reset'](),
+ this['write'](e)),
+ this['_fill']();
+ for (var f = 0; f < this.chunk['length']; f += 64)
+ this._compress(this['chunk']['slice'](f, f + 64));
+ var i = null;
+ if (t == 'hex') {
+ i = "";
+ for (f = 0; f < 8; f++)
+ i += se(this['reg'][f]['toString'](16), 8, "0")
+ } else
+ for (i = new Array(32),
+ f = 0; f < 8; f++) {
+ var c = this.reg[f];
+ i[4 * f + 3] = (255 & c) >>> 0,
+ c >>>= 8,
+ i[4 * f + 2] = (255 & c) >>> 0,
+ c >>>= 8,
+ i[4 * f + 1] = (255 & c) >>> 0,
+ c >>>= 8,
+ i[4 * f] = (255 & c) >>> 0
+ }
+ return this['reset'](),
+ i
+}
+
+function _compress(t) {
+ if (t < 64)
+ console.error("compress error: not enough data");
+ else {
+ for (var f = function (e) {
+ for (var r = new Array(132), t = 0; t < 16; t++)
+ r[t] = e[4 * t] << 24,
+ r[t] |= e[4 * t + 1] << 16,
+ r[t] |= e[4 * t + 2] << 8,
+ r[t] |= e[4 * t + 3],
+ r[t] >>>= 0;
+ for (var n = 16; n < 68; n++) {
+ var a = r[n - 16] ^ r[n - 9] ^ le(r[n - 3], 15);
+ a = a ^ le(a, 15) ^ le(a, 23),
+ r[n] = (a ^ le(r[n - 13], 7) ^ r[n - 6]) >>> 0
+ }
+ for (n = 0; n < 64; n++)
+ r[n + 68] = (r[n] ^ r[n + 4]) >>> 0;
+ return r
+ }(t), i = this['reg'].slice(0), c = 0; c < 64; c++) {
+ var o = le(i[0], 12) + i[4] + le(de(c), c)
+ , s = ((o = le(o = (4294967295 & o) >>> 0, 7)) ^ le(i[0], 12)) >>> 0
+ , u = pe(c, i[0], i[1], i[2]);
+ u = (4294967295 & (u = u + i[3] + s + f[c + 68])) >>> 0;
+ var b = he(c, i[4], i[5], i[6]);
+ b = (4294967295 & (b = b + i[7] + o + f[c])) >>> 0,
+ i[3] = i[2],
+ i[2] = le(i[1], 9),
+ i[1] = i[0],
+ i[0] = u,
+ i[7] = i[6],
+ i[6] = le(i[5], 19),
+ i[5] = i[4],
+ i[4] = (b ^ le(b, 9) ^ le(b, 17)) >>> 0
+ }
+ for (var l = 0; l < 8; l++)
+ this['reg'][l] = (this['reg'][l] ^ i[l]) >>> 0
+ }
+}
+
+function _fill() {
+ var a = 8 * this['size']
+ , f = this['chunk']['push'](128) % 64;
+ for (64 - f < 8 && (f -= 64); f < 56; f++)
+ this.chunk['push'](0);
+ for (var i = 0; i < 4; i++) {
+ var c = Math['floor'](a / 4294967296);
+ this['chunk'].push(c >>> 8 * (3 - i) & 255)
+ }
+ for (i = 0; i < 4; i++)
+ this['chunk']['push'](a >>> 8 * (3 - i) & 255)
+
+}
+
+function SM3() {
+ this.reg = [];
+ this.chunk = [];
+ this.size = 0;
+ this.reset()
+}
+SM3.prototype.reset = reset;
+SM3.prototype.write = write;
+SM3.prototype.sum = sum;
+SM3.prototype._compress = _compress;
+SM3.prototype._fill = _fill;
+
+function result_encrypt(long_str, num = null) {
+ let s_obj = {
+ "s0": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
+ "s1": "Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe=",
+ "s2": "Dkdpgh4ZKsQB80/Mfvw36XI1R25-WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe=",
+ "s3": "ckdp1h4ZKsUB80/Mfvw36XIgR25+WQAlEi7NLboqYTOPuzmFjJnryx9HVGDaStCe",
+ "s4": "Dkdpgh2ZmsQB80/MfvV36XI1R45-WUAlEixNLwoqYTOPuzKFjJnry79HbGcaStCe"
+ }
+ let constant = {
+ "0": 16515072,
+ "1": 258048,
+ "2": 4032,
+ "str": s_obj[num],
+ }
+
+ let result = "";
+ let lound = 0;
+ let long_int = get_long_int(lound, long_str);
+ for (let i = 0; i < long_str.length / 3 * 4; i++) {
+ if (Math.floor(i / 4) !== lound) {
+ lound += 1;
+ long_int = get_long_int(lound, long_str);
+ }
+ let key = i % 4;
+ switch (key) {
+ case 0:
+ temp_int = (long_int & constant["0"]) >> 18;
+ result += constant["str"].charAt(temp_int);
+ break;
+ case 1:
+ temp_int = (long_int & constant["1"]) >> 12;
+ result += constant["str"].charAt(temp_int);
+ break;
+ case 2:
+ temp_int = (long_int & constant["2"]) >> 6;
+ result += constant["str"].charAt(temp_int);
+ break;
+ case 3:
+ temp_int = long_int & 63;
+ result += constant["str"].charAt(temp_int);
+ break;
+ default:
+ break;
+ }
+ }
+ return result;
+}
+
+function get_long_int(round, long_str) {
+ round = round * 3;
+ return (long_str.charCodeAt(round) << 16) | (long_str.charCodeAt(round + 1) << 8) | (long_str.charCodeAt(round + 2));
+}
+
+function gener_random(random, option) {
+ return [
+ (random & 255 & 170) | option[0] & 85, // 163
+ (random & 255 & 85) | option[0] & 170, //87
+ (random >> 8 & 255 & 170) | option[1] & 85, //37
+ (random >> 8 & 255 & 85) | option[1] & 170, //41
+ ]
+}
+
+//////////////////////////////////////////////
+function generate_rc4_bb_str(url_search_params, user_agent, window_env_str, suffix = "cus", Arguments = [0, 1, 14]) {
+ let sm3 = new SM3()
+ let start_time = Date.now()
+ /**
+ * 进行3次加密处理
+ * 1: url_search_params两次sm3之的结果
+ * 2: 对后缀两次sm3之的结果
+ * 3: 对ua处理之后的结果
+ */
+ // url_search_params两次sm3之的结果
+ let url_search_params_list = sm3.sum(sm3.sum(url_search_params + suffix))
+ // 对后缀两次sm3之的结果
+ let cus = sm3.sum(sm3.sum(suffix))
+ // 对ua处理之后的结果
+ let ua = sm3.sum(result_encrypt(rc4_encrypt(user_agent, String.fromCharCode.apply(null, [0.00390625, 1, Arguments[2]])), "s3"))
+ //
+ let end_time = Date.now()
+ // b
+ let b = {
+ 8: 3, // 固定
+ 10: end_time, //3次加密结束时间
+ 15: {
+ "aid": 6383,
+ "pageId": 6241,
+ "boe": false,
+ "ddrt": 7,
+ "paths": {
+ "include": [
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {}
+ ],
+ "exclude": []
+ },
+ "track": {
+ "mode": 0,
+ "delay": 300,
+ "paths": []
+ },
+ "dump": true,
+ "rpU": ""
+ },
+ 16: start_time, //3次加密开始时间
+ 18: 44, //固定
+ 19: [1, 0, 1, 5],
+ }
+
+ //3次加密开始时间
+ b[20] = (b[16] >> 24) & 255
+ b[21] = (b[16] >> 16) & 255
+ b[22] = (b[16] >> 8) & 255
+ b[23] = b[16] & 255
+ b[24] = (b[16] / 256 / 256 / 256 / 256) >> 0
+ b[25] = (b[16] / 256 / 256 / 256 / 256 / 256) >> 0
+
+ // 参数Arguments [0, 1, 14, ...]
+ // let Arguments = [0, 1, 14]
+ b[26] = (Arguments[0] >> 24) & 255
+ b[27] = (Arguments[0] >> 16) & 255
+ b[28] = (Arguments[0] >> 8) & 255
+ b[29] = Arguments[0] & 255
+
+ b[30] = (Arguments[1] / 256) & 255
+ b[31] = (Arguments[1] % 256) & 255
+ b[32] = (Arguments[1] >> 24) & 255
+ b[33] = (Arguments[1] >> 16) & 255
+
+ b[34] = (Arguments[2] >> 24) & 255
+ b[35] = (Arguments[2] >> 16) & 255
+ b[36] = (Arguments[2] >> 8) & 255
+ b[37] = Arguments[2] & 255
+
+ // (url_search_params + "cus") 两次sm3之的结果
+ /**let url_search_params_list = [
+ 91, 186, 35, 86, 143, 253, 6, 76,
+ 34, 21, 167, 148, 7, 42, 192, 219,
+ 188, 20, 182, 85, 213, 74, 213, 147,
+ 37, 155, 93, 139, 85, 118, 228, 213
+ ]*/
+ b[38] = url_search_params_list[21]
+ b[39] = url_search_params_list[22]
+
+ // ("cus") 对后缀两次sm3之的结果
+ /**
+ * let cus = [
+ 136, 101, 114, 147, 58, 77, 207, 201,
+ 215, 162, 154, 93, 248, 13, 142, 160,
+ 105, 73, 215, 241, 83, 58, 51, 43,
+ 255, 38, 168, 141, 216, 194, 35, 236
+ ]*/
+ b[40] = cus[21]
+ b[41] = cus[22]
+
+ // 对ua处理之后的结果
+ /**
+ * let ua = [
+ 129, 190, 70, 186, 86, 196, 199, 53,
+ 99, 38, 29, 209, 243, 17, 157, 69,
+ 147, 104, 53, 23, 114, 126, 66, 228,
+ 135, 30, 168, 185, 109, 156, 251, 88
+ ]*/
+ b[42] = ua[23]
+ b[43] = ua[24]
+
+ //3次加密结束时间
+ b[44] = (b[10] >> 24) & 255
+ b[45] = (b[10] >> 16) & 255
+ b[46] = (b[10] >> 8) & 255
+ b[47] = b[10] & 255
+ b[48] = b[8]
+ b[49] = (b[10] / 256 / 256 / 256 / 256) >> 0
+ b[50] = (b[10] / 256 / 256 / 256 / 256 / 256) >> 0
+
+
+ // object配置项
+ b[51] = b[15]['pageId']
+ b[52] = (b[15]['pageId'] >> 24) & 255
+ b[53] = (b[15]['pageId'] >> 16) & 255
+ b[54] = (b[15]['pageId'] >> 8) & 255
+ b[55] = b[15]['pageId'] & 255
+
+ b[56] = b[15]['aid']
+ b[57] = b[15]['aid'] & 255
+ b[58] = (b[15]['aid'] >> 8) & 255
+ b[59] = (b[15]['aid'] >> 16) & 255
+ b[60] = (b[15]['aid'] >> 24) & 255
+
+ // 中间进行了环境检测
+ // 代码索引: 2496 索引值: 17 (索引64关键条件)
+ // '1536|747|1536|834|0|30|0|0|1536|834|1536|864|1525|747|24|24|Win32'.charCodeAt()得到65位数组
+ /**
+ * let window_env_list = [49, 53, 51, 54, 124, 55, 52, 55, 124, 49, 53, 51, 54, 124, 56, 51, 52, 124, 48, 124, 51,
+ * 48, 124, 48, 124, 48, 124, 49, 53, 51, 54, 124, 56, 51, 52, 124, 49, 53, 51, 54, 124, 56,
+ * 54, 52, 124, 49, 53, 50, 53, 124, 55, 52, 55, 124, 50, 52, 124, 50, 52, 124, 87, 105, 110,
+ * 51, 50]
+ */
+ let window_env_list = [];
+ for (let index = 0; index < window_env_str.length; index++) {
+ window_env_list.push(window_env_str.charCodeAt(index))
+ }
+ b[64] = window_env_list.length
+ b[65] = b[64] & 255
+ b[66] = (b[64] >> 8) & 255
+
+ b[69] = [].length
+ b[70] = b[69] & 255
+ b[71] = (b[69] >> 8) & 255
+
+ b[72] = b[18] ^ b[20] ^ b[26] ^ b[30] ^ b[38] ^ b[40] ^ b[42] ^ b[21] ^ b[27] ^ b[31] ^ b[35] ^ b[39] ^ b[41] ^ b[43] ^ b[22] ^
+ b[28] ^ b[32] ^ b[36] ^ b[23] ^ b[29] ^ b[33] ^ b[37] ^ b[44] ^ b[45] ^ b[46] ^ b[47] ^ b[48] ^ b[49] ^ b[50] ^ b[24] ^
+ b[25] ^ b[52] ^ b[53] ^ b[54] ^ b[55] ^ b[57] ^ b[58] ^ b[59] ^ b[60] ^ b[65] ^ b[66] ^ b[70] ^ b[71]
+ let bb = [
+ b[18], b[20], b[52], b[26], b[30], b[34], b[58], b[38], b[40], b[53], b[42], b[21], b[27], b[54], b[55], b[31],
+ b[35], b[57], b[39], b[41], b[43], b[22], b[28], b[32], b[60], b[36], b[23], b[29], b[33], b[37], b[44], b[45],
+ b[59], b[46], b[47], b[48], b[49], b[50], b[24], b[25], b[65], b[66], b[70], b[71]
+ ]
+ bb = bb.concat(window_env_list).concat(b[72])
+ return rc4_encrypt(String.fromCharCode.apply(null, bb), String.fromCharCode.apply(null, [121]));
+}
+
+function generate_random_str() {
+ let random_str_list = []
+ random_str_list = random_str_list.concat(gener_random(Math.random() * 10000, [3, 45]))
+ random_str_list = random_str_list.concat(gener_random(Math.random() * 10000, [1, 0]))
+ random_str_list = random_str_list.concat(gener_random(Math.random() * 10000, [1, 5]))
+ return String.fromCharCode.apply(null, random_str_list)
+}
+
+function sign(url_search_params, user_agent, arguments) {
+ /**
+ * url_search_params:"device_platform=webapp&aid=6383&channel=channel_pc_web&update_version_code=170400&pc_client_type=1&version_code=170400&version_name=17.4.0&cookie_enabled=true&screen_width=1536&screen_height=864&browser_language=zh-CN&browser_platform=Win32&browser_name=Chrome&browser_version=123.0.0.0&browser_online=true&engine_name=Blink&engine_version=123.0.0.0&os_name=Windows&os_version=10&cpu_core_num=16&device_memory=8&platform=PC&downlink=10&effective_type=4g&round_trip_time=50&webid=7362810250930783783&msToken=VkDUvz1y24CppXSl80iFPr6ez-3FiizcwD7fI1OqBt6IICq9RWG7nCvxKb8IVi55mFd-wnqoNkXGnxHrikQb4PuKob5Q-YhDp5Um215JzlBszkUyiEvR"
+ * user_agent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"
+ */
+ let result_str = generate_random_str() + generate_rc4_bb_str(
+ url_search_params,
+ user_agent,
+ "1536|747|1536|834|0|30|0|0|1536|834|1536|864|1525|747|24|24|Win32",
+ "cus",
+ arguments
+ );
+ return result_encrypt(result_str, "s4") + "=";
+}
+
+function sign_datail(params, userAgent) {
+ return sign(params, userAgent, [0, 1, 14])
+}
+
+function sign_reply(params, userAgent) {
+ return sign(params, userAgent, [0, 1, 8])
+}
\ No newline at end of file
diff --git a/src/BlueCatKoKo.Ui/BlueCatKoKo.Ui.csproj b/src/BlueCatKoKo.Ui/BlueCatKoKo.Ui.csproj
new file mode 100644
index 0000000..1228399
--- /dev/null
+++ b/src/BlueCatKoKo.Ui/BlueCatKoKo.Ui.csproj
@@ -0,0 +1,58 @@
+
+
+
+ WinExe
+ net8.0-windows
+ enable
+ enable
+ applicationIcon.ico
+ AnyCPU;x64
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ BlueCatKoKo
+
+
+
+
+ Always
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/BlueCatKoKo.Ui/Constants/DownloaderEnum.cs b/src/BlueCatKoKo.Ui/Constants/DownloaderEnum.cs
new file mode 100644
index 0000000..373e6f6
--- /dev/null
+++ b/src/BlueCatKoKo.Ui/Constants/DownloaderEnum.cs
@@ -0,0 +1,11 @@
+namespace BlueCatKoKo.Ui.Constants
+{
+ public enum DownloaderEnum
+ {
+ Init,
+ Downloading,
+ Success,
+ Warning,
+ Error,
+ }
+}
\ No newline at end of file
diff --git a/src/BlueCatKoKo.Ui/Models/AppConfig.cs b/src/BlueCatKoKo.Ui/Models/AppConfig.cs
new file mode 100644
index 0000000..8adf856
--- /dev/null
+++ b/src/BlueCatKoKo.Ui/Models/AppConfig.cs
@@ -0,0 +1,13 @@
+namespace BlueCatKoKo.Ui.Models
+{
+ public class AppConfig
+ {
+ public string? Name { get; set; }
+ public string? TrayTitle { get; set; }
+ public string? Version { get; set; }
+ public string? Description { get; set; }
+ public string? DownloadPath { get; set; }
+ public string? RepositoryUrl { get; set; }
+ public List? Cookies { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/BlueCatKoKo.Ui/Models/DouyinShareRouterData.cs b/src/BlueCatKoKo.Ui/Models/DouyinShareRouterData.cs
new file mode 100644
index 0000000..d4af007
--- /dev/null
+++ b/src/BlueCatKoKo.Ui/Models/DouyinShareRouterData.cs
@@ -0,0 +1,297 @@
+using Newtonsoft.Json;
+
+namespace BlueCatKoKo.Ui.Models
+{
+ ///
+ /// 抖音 分享文本中的视频数据
+ ///
+ public class DouyinShareRouterData
+ {
+ [JsonProperty("loaderData")] public LoaderData LoaderData { get; set; }
+ }
+
+ public class LoaderData
+ {
+ [JsonProperty("video_(id)/page")] public VideoIdPage VideoIdPage { get; set; }
+ }
+
+ public class VideoIdPage
+ {
+ [JsonProperty("isAutoOpenApp")] public bool IsAutoOpenApp { get; set; }
+
+ [JsonProperty("appName")] public string AppName { get; set; }
+
+ [JsonProperty("query")] public Query Query { get; set; }
+
+ [JsonProperty("isSpider")] public bool IsSpider { get; set; }
+
+ [JsonProperty("ua")] public string Ua { get; set; }
+
+ [JsonProperty("isVideoOptimize")] public bool IsVideoOptimize { get; set; }
+
+ [JsonProperty("commonContext")] public CommonContext CommonContext { get; set; }
+
+ [JsonProperty("itemId")] public string ItemId { get; set; }
+
+ [JsonProperty("webId")] public string WebId { get; set; }
+
+ [JsonProperty("renderInSSR")] public long RenderInSsr { get; set; }
+
+ [JsonProperty("host")] public string Host { get; set; }
+
+ [JsonProperty("videoInfoRes")] public VideoInfoRes VideoInfoRes { get; set; }
+
+ [JsonProperty("darkModeAdaptation")] public bool DarkModeAdaptation { get; set; }
+
+ [JsonProperty("lastPath")] public string LastPath { get; set; }
+
+ [JsonProperty("isNotSupportWebp")] public bool IsNotSupportWebp { get; set; }
+
+ [JsonProperty("serverToken")] public string ServerToken { get; set; }
+ }
+
+ public class CommonContext
+ {
+ [JsonProperty("webId")] public string WebId { get; set; }
+
+ [JsonProperty("renderInSSR")] public long RenderInSsr { get; set; }
+
+ [JsonProperty("appName")] public string AppName { get; set; }
+
+ [JsonProperty("query")] public Query Query { get; set; }
+
+ [JsonProperty("host")] public string Host { get; set; }
+
+ [JsonProperty("isSpider")] public bool IsSpider { get; set; }
+
+ [JsonProperty("lastPath")] public string LastPath { get; set; }
+
+ [JsonProperty("isNotSupportWebp")] public bool IsNotSupportWebp { get; set; }
+
+ [JsonProperty("ua")] public string Ua { get; set; }
+ }
+
+ public class Query
+ {
+ [JsonProperty("titleType")] public string TitleType { get; set; }
+
+ [JsonProperty("iid")] public string Iid { get; set; }
+
+ [JsonProperty("u_code")] public string UCode { get; set; }
+
+ [JsonProperty("from_ssr")] public long FromSsr { get; set; }
+
+ [JsonProperty("mid")] public string Mid { get; set; }
+
+ [JsonProperty("share_sign")] public string ShareSign { get; set; }
+
+ [JsonProperty("with_sec_did")] public long WithSecDid { get; set; }
+
+ [JsonProperty("from_aid")] public long FromAid { get; set; }
+
+ [JsonProperty("from")] public string From { get; set; }
+
+ [JsonProperty("region")] public string Region { get; set; }
+
+ [JsonProperty("did")] public string Did { get; set; }
+
+ [JsonProperty("share_version")] public long ShareVersion { get; set; }
+
+ [JsonProperty("ts")] public long Ts { get; set; }
+ }
+
+ public class VideoInfoRes
+ {
+ [JsonProperty("status_code")] public long StatusCode { get; set; }
+
+ [JsonProperty("filter_list")] public List