├── .dockerignore ├── .gitattributes ├── .github ├── Dockerfile ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── -----.md │ └── bug---.md └── workflows │ ├── check.yml │ ├── docker-publish-tagged.yml │ ├── publish.yml │ └── update-sponsors.yml ├── .gitignore ├── Dockerfile ├── GitVersion.yml ├── LICENSE ├── README.md ├── WFBot.Tests ├── FunctionTest.cs └── WFBot.Tests.csproj ├── WFBot.sln ├── WFBot ├── 7zip │ ├── Common │ │ └── CRC.cs │ ├── Compress │ │ ├── LZ │ │ │ ├── IMatchFinder.cs │ │ │ └── LzOutWindow.cs │ │ ├── LZMA │ │ │ ├── LzmaBase.cs │ │ │ └── LzmaDecoder.cs │ │ └── RangeCoder │ │ │ ├── RangeCoder.cs │ │ │ ├── RangeCoderBit.cs │ │ │ └── RangeCoderBitTree.cs │ └── ICoder.cs ├── Config.cs ├── Dll │ ├── PininSharp.dll │ └── SuffixTreeSharp.dll ├── Features │ ├── Commands │ │ ├── BotCommands.cs │ │ ├── CommandsBase.cs │ │ ├── KookSpecificCommands.cs │ │ ├── NotificationCommands.cs │ │ ├── SearchCommands.cs │ │ ├── StatusCommands.cs │ │ └── WikiCommand.cs │ ├── Common │ │ ├── RMSearcher.cs │ │ ├── WFNotificationHandler.cs │ │ ├── WMASearcher.cs │ │ ├── WMSearcher.cs │ │ └── WildCardSearcher.cs │ ├── CustomCommandContent │ │ └── CustomCommandContentHandler.cs │ ├── Events │ │ ├── ISender.cs │ │ ├── MessageReceivedEvent.cs │ │ └── PrivateMessageReceivedEvent.cs │ ├── ImageRendering │ │ ├── ImageRenderHelper.cs │ │ ├── ImageRenderProfiler.cs │ │ ├── ImageRenderingPGO.cs │ │ └── RichMessage.cs │ ├── Other │ │ └── CustomCommandMatcherHandler.cs │ ├── Resource │ │ ├── IWFResource.cs │ │ ├── SlangManager.cs │ │ ├── WFResource.cs │ │ ├── WFResources.cs │ │ └── WFResourcesManager.cs │ ├── Telemetry │ │ ├── Memory.cs │ │ └── TelemetryClient.cs │ ├── Timers │ │ ├── Base │ │ │ └── WFBotTimer.cs │ │ ├── BotMarketHeartbeatTimer.cs │ │ ├── ImageRenderingPGOTimer.cs │ │ ├── NotificationTimer.cs │ │ ├── WFATimer.cs │ │ └── WFResourcesTimer.cs │ └── Utils │ │ ├── CommitsGetter.cs │ │ ├── MessageProcessors.cs │ │ ├── Messenger.cs │ │ ├── ReleaseGetter.cs │ │ ├── WFAApi.cs │ │ ├── WFChineseAPI.cs │ │ ├── WFFormatter.cs │ │ ├── WFObjects.cs │ │ └── WFTranslator.cs ├── FodyWeavers.xml ├── FodyWeavers.xsd ├── GroupInfo.cs ├── MahuaEvents │ ├── GroupJoiningInvitationReceivedMahuaEvent1.cs │ └── GroupJoiningRequestReceivedMahuaEvent1.cs ├── Orichalt │ ├── KookVerifyServer.cs │ ├── MiguelNetwork.cs │ ├── OrichaltConnectors │ │ ├── BasicConnector.cs │ │ ├── KookConnector.cs │ │ ├── MiraiHTTPConnector.cs │ │ ├── MiraiHTTPv1Connector.cs │ │ ├── OneBotConnector.cs │ │ └── QQChannelConnector.cs │ ├── OrichaltContextExtension.cs │ └── OrichaltContextManager.cs ├── Properties │ ├── AssemblyInfo.cs │ └── PublishProfiles │ │ ├── FolderProfile.pubxml │ │ └── FolderProfile1.pubxml ├── Resources │ ├── Factions │ │ ├── corpus.png │ │ ├── corrupted.png │ │ ├── crossfire.png │ │ ├── grineer.png │ │ ├── infested.png │ │ ├── orokin.png │ │ └── sentient.png │ ├── Fissures │ │ ├── 1.png │ │ ├── 2.png │ │ ├── 3.png │ │ ├── 4.png │ │ └── 5.png │ ├── InvasionRewards │ │ ├── FORMA.png │ │ ├── OROKIN催化剂.png │ │ ├── OROKIN反应堆.png │ │ ├── 卡拉克 亡魂.png │ │ ├── 双子蝰蛇 亡魂.png │ │ ├── 希芙.png │ │ ├── 异融ALAD V导航座标.png │ │ ├── 德拉 破坏者.png │ │ ├── 拉特昂 亡魂.png │ │ ├── 斯特朗 亡魂.png │ │ ├── 爆燃喷射器.png │ │ ├── 特殊功能槽连接器.png │ │ ├── 狙击特昂 破坏者.png │ │ ├── 电磁力场装置.png │ │ └── 突变原聚合物.png │ ├── WarframeMarket │ │ ├── Cubes.png │ │ ├── PlatinumLarge.png │ │ └── PlatinumSimple.png │ ├── Weathers │ │ ├── cold.png │ │ ├── night.png │ │ ├── sun.png │ │ └── warm.png │ └── network-unstable.gif ├── TextCommandCore │ ├── CommandException.cs │ ├── CommandHandlerHelper.cs │ ├── ICommandHandler.cs │ ├── Objects.cs │ └── Processors.cs ├── Utils │ ├── AsyncContext.cs │ ├── Cylib.cs │ ├── EnumerableExtensions.cs │ ├── GroupMessageSender.cs │ ├── LZMADecompress.cs │ ├── NTPClient.cs │ ├── Plugins.cs │ ├── StringExtensions.cs │ ├── WFBotResourceLock.cs │ └── WebHelper.cs ├── WFBot.csproj ├── WFBot.csproj.DotSettings ├── WFBotCore.cs ├── WebSocketHandler.cs ├── WebUI │ ├── App.razor │ ├── Pages │ │ ├── About.razor │ │ ├── CommandAlias.razor │ │ ├── CustomCommandContent.razor │ │ ├── Debug.razor │ │ ├── Error.cshtml │ │ ├── Error.cshtml.cs │ │ ├── Features.razor │ │ ├── Index.razor │ │ ├── MiraiSettings.razor │ │ ├── MiraiSettingsV1.razor │ │ ├── OntbotSettings.razor │ │ ├── Settings.razor │ │ ├── _Host.cshtml │ │ └── _Layout.cshtml │ ├── Shared │ │ ├── InputRadioForkMicrosoft.razor │ │ ├── MainLayout.razor │ │ ├── MainLayout.razor.css │ │ ├── NavMenu.razor │ │ └── NavMenu.razor.css │ ├── WFBotWebUIServer.cs │ ├── WebLogTraceListener.cs │ └── _Imports.razor ├── Windows │ ├── OriginalSettings.cs │ ├── Settings.Designer.cs │ ├── Settings.cs │ └── Settings.resx ├── wwwroot │ ├── css │ │ ├── bootstrap │ │ │ ├── bootstrap.min.css │ │ │ └── bootstrap.min.css.map │ │ ├── open-iconic │ │ │ ├── FONT-LICENSE │ │ │ ├── ICON-LICENSE │ │ │ ├── README.md │ │ │ └── font │ │ │ │ ├── css │ │ │ │ └── open-iconic-bootstrap.min.css │ │ │ │ └── fonts │ │ │ │ ├── open-iconic.eot │ │ │ │ ├── open-iconic.otf │ │ │ │ ├── open-iconic.svg │ │ │ │ ├── open-iconic.ttf │ │ │ │ └── open-iconic.woff │ │ └── site.css │ └── js │ │ └── editor.js └── wwwroot2 │ ├── WFBot.styles.css │ └── _content │ └── BlazorStrap │ ├── BlazorStrap.bundle.scp.css │ ├── blazorstrap.js │ ├── blazorstrap.min.js │ └── popper.min.js ├── WFBotExamplePlugin ├── Class1.cs ├── Properties │ └── AssemblyInfo.cs ├── WFBotExamplePlugin.csproj ├── app.config └── packages.config ├── build-wfbot-ci.bat ├── build-wfbot-nogitversion.bat ├── build-wfbot-test.bat ├── build-wfbot.bat ├── docs ├── docker-compose.yml ├── docker.md ├── faq.md ├── images │ ├── 2021-01-20-22-31-26.png │ ├── 2021-01-20-22-36-23.png │ ├── 2021-01-20-22-41-51.png │ ├── 2021-01-20-22-47-24.png │ ├── 2021-01-20-22-53-07.png │ ├── 2021-01-20-22-56-39.png │ ├── 2021-01-20-23-07-05.png │ ├── 2021-01-20-23-11-14.png │ ├── 2021-01-20-23-14-53.png │ ├── 2021-01-20-23-16-41.png │ ├── 2021-01-20-23-20-21.png │ ├── 2021-01-20-23-36-00.png │ ├── MONEY.png │ ├── QQ截图20211110000226.png │ ├── QQ截图20211110001258.png │ ├── QQ截图20211110001446.png │ ├── QQ截图20211110001645.png │ ├── QQ截图20220619213108.png │ ├── QQ截图20220621224220.png │ ├── QQ截图20220621224330.png │ ├── QQ截图20220621231503.png │ ├── QQ截图20220621232534.png │ ├── QQ截图20220621234016.png │ ├── QQ截图20220621235448.png │ ├── QQ截图20220627214408.png │ ├── QQ截图20220627214621.png │ ├── QQ截图20220627214806.png │ ├── QQ截图20220627214916.png │ ├── QQ截图20220627215234.png │ ├── jetbrains-variant-3-201x231.png │ ├── processon.png │ ├── token1.png │ ├── token2.png │ └── token3.png ├── install.md ├── plugin.md └── token.md └── privacy-policy.md /.dockerignore: -------------------------------------------------------------------------------- 1 | **/.classpath 2 | **/.dockerignore 3 | **/.env 4 | **/.gitignore 5 | **/.project 6 | **/.settings 7 | **/.toolstarget 8 | **/.vs 9 | **/.vscode 10 | **/*.*proj.user 11 | **/*.dbmdl 12 | **/*.jfm 13 | **/azds.yaml 14 | **/bin 15 | **/charts 16 | **/docker-compose* 17 | **/Dockerfile* 18 | **/node_modules 19 | **/npm-debug.log 20 | **/obj 21 | **/secrets.dev.yaml 22 | **/values.dev.yaml 23 | LICENSE 24 | README.md -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.github/Dockerfile: -------------------------------------------------------------------------------- 1 | #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. 2 | 3 | FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base 4 | ENV TZ=Asia/Shanghai 5 | RUN printf "deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye main contrib non-free\ndeb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-updates main contrib non-free\ndeb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-backports main contrib non-free\ndeb https://mirrors.tuna.tsinghua.edu.cn/debian-security bullseye-security main contrib non-free" > /etc/apt/sources.list 6 | RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone 7 | RUN apt update && apt install -y procps && rm -rf /var/lib/apt/lists/* 8 | WORKDIR /app 9 | 10 | FROM mcr.microsoft.com/dotnet/sdk:7.0 AS publish 11 | WORKDIR /src 12 | COPY . . 13 | RUN sed -i -e 's/net6.0/net7.0/g' WFBot/WFBot.csproj 14 | RUN dotnet restore "WFBot/WFBot.csproj" && rm -rf WFBot/wwwroot2 && mkdir WFBot/wwwroot2 && touch WFBot/wwwroot2/test 15 | ENV OFFICIAL_BUILD=official 16 | #WORKDIR "/src/WFBot" 17 | RUN dotnet publish "WFBot" -c "Linux Release" -o /app/publish && rm -rf .git 18 | 19 | FROM base AS final 20 | WORKDIR /app 21 | COPY --from=publish /app/publish . 22 | ENTRYPOINT ["dotnet", "WFBot.dll", "--", "--use-config-folder"] 23 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | custom: https://afdian.net/@TheRealKamisama 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/-----.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 新特性需求 3 | about: 给这个项目提出个新点子! 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **你的这个点子是否和你遇到了一些问题有关?请描述下问题(如无可忽略)** 11 | 对问题清晰并简要的描述. 比如: 我总是在 [...] 的时候遇到这个问题 [...]. 12 | 13 | **描述一下你想要的解决方案** 14 | 对你想要的解决方案(对问题)清晰并简要的描述. 比如: 我希望可以在 [...] 这个地方做出 [...] 这样的改动. 15 | 16 | **描述一下你考虑过的方案** 17 | 对你考虑过的任何的解决方案(对问题)或者任何新特性. 比如: 我认为在 [...] 这个地方可以 [...] 修改一下. 18 | 19 | **附加信息** 20 | 附加一些除以上之外关于此新特性需求的信息. 21 | 用户期望: [你的用户群体的呼声] 22 | 你能做的: [我很欢迎你们帮我来写这个项目的] 23 | 24 | ***欢迎PR*** 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug---.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: BUG 反馈 3 | about: 帮忙让这个项目变得更好! 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **描述一下这个BUG** 11 | 对这个BUG清晰并简要的描述. 12 | 13 | **如何重现这个BUG** 14 | 用来重现这个状态的步骤: 15 | 1. 前往 '...' 16 | 2. 点击 '....' 17 | 3. 下滑到 '....' 18 | 4. ERROR就在这里 19 | 20 | **期望的状态** 21 | 对你想要以后达到的效果清晰并简要的描述. 22 | 23 | **截图** 24 | 如果可以的话,留下一些截图来帮助你描述这个问题 25 | 26 | **运行环境 (请填写以下的信息):** 27 | - 系统: [比如: Windows7] 28 | - 平台: [比如: 酷Q Pro] 29 | - 版本: [比如: 酷Q Pro 5.12.9] 30 | 31 | **附加信息** 32 | 附加一些除以上之外关于此BUG的信息. 33 | LOG: ```[logs文件夹内最新最相关的内容]``` 34 | 设置: [插件设置界面的截图] 35 | 相关的都可以贴! 36 | 37 | ***欢迎PR*** 38 | -------------------------------------------------------------------------------- /.github/workflows/check.yml: -------------------------------------------------------------------------------- 1 | name: Build Check 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | runs-on: windows-latest 8 | 9 | steps: 10 | - uses: actions/checkout@v2 11 | with: 12 | fetch-depth: 0 13 | - name: Setup .NET 14 | uses: actions/setup-dotnet@v1 15 | with: 16 | dotnet-version: 7.0.x 17 | include-prerelease: true 18 | 19 | - name: Reset Tags 20 | run: git fetch --tags 21 | 22 | - name: Clean 1 23 | run: dotnet clean WFBot.sln --configuration "Windows Release" && dotnet nuget locals all --clear 24 | - name: Clean 2 25 | run: dotnet clean WFBot.sln --configuration "Linux Release" && dotnet nuget locals all --clear 26 | - name: Restore dependencies 27 | run: dotnet restore 28 | 29 | - name: Linux Build 30 | run: dotnet publish WFBot -c "Linux Release" -o LinuxPublish --self-contained false 31 | -------------------------------------------------------------------------------- /.github/workflows/docker-publish-tagged.yml: -------------------------------------------------------------------------------- 1 | name: Tagged Docker Publish 2 | 3 | on: 4 | push: 5 | tags: 6 | - '*' 7 | 8 | jobs: 9 | 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | with: 17 | fetch-depth: 0 18 | - name: Set up Docker Buildx 19 | uses: docker/setup-buildx-action@v1 20 | 21 | - name: Login to DockerHub 22 | uses: docker/login-action@v1 23 | with: 24 | username: ${{ secrets.DOCKERHUB_USERNAME }} 25 | password: ${{ secrets.DOCKERHUB_TOKEN }} 26 | 27 | - name: Use Custom Dockerfile 28 | run: | 29 | rm Dockerfile 30 | cp .github/Dockerfile . 31 | - name: Extract Git Tag 32 | run: echo "GIT_TAG=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_ENV 33 | 34 | - name: Build, tag, and push image to Amazon ECR 35 | env: 36 | IMAGE_TAG: ${{ env.GIT_TAG }} 37 | run: | 38 | docker build -t trksteam/wfbot::$IMAGE_TAG . 39 | docker push trksteam/wfbot:$IMAGE_TAG 40 | 41 | 42 | -------------------------------------------------------------------------------- /.github/workflows/update-sponsors.yml: -------------------------------------------------------------------------------- 1 | name: Deprecated-Update Sponsors 2 | 3 | on: workflow_dispatch 4 | # schedule: 5 | # # * is a special character in YAML so you have to quote this string 6 | # - cron: '35 7,19 * * *' 7 | 8 | jobs: 9 | build: 10 | runs-on: windows-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v2 14 | with: 15 | ref: 'universal' 16 | 17 | - name: Setup .NET 18 | uses: actions/setup-dotnet@v1 19 | with: 20 | dotnet-version: 5.0.x 21 | 22 | - name: Clone Updater 23 | run: git clone https://github.com/TRKS-Team/WFBotSponsorUpdater.git ../WFBotSponsorUpdater/ 24 | 25 | - name: Run Updater 26 | run: dotnet run -p ../WFBotSponsorUpdater 27 | 28 | - name: Get current date 29 | id: date 30 | run: echo "::set-output name=date::$('%Y-%m-%d')" 31 | 32 | - name: Create Pull Request 33 | uses: peter-evans/create-pull-request@v3 34 | with: 35 | commit-message: 更新赞助者名单 36 | delete-branch: true 37 | title: 更新赞助者名单 38 | body: 更新赞助者名单 by Cyl18 39 | labels: awsl, doc 40 | 41 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. 2 | 3 | FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base 4 | ENV TZ=Asia/Shanghai 5 | RUN printf "deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye main contrib non-free\ndeb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-updates main contrib non-free\ndeb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-backports main contrib non-free\ndeb https://mirrors.tuna.tsinghua.edu.cn/debian-security bullseye-security main contrib non-free" > /etc/apt/sources.list 6 | RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone 7 | RUN apt update && apt install -y procps && rm -rf /var/lib/apt/lists/* 8 | WORKDIR /app 9 | 10 | FROM mcr.microsoft.com/dotnet/sdk:7.0 AS publish 11 | WORKDIR /src 12 | COPY . . 13 | RUN sed -i -e 's/net6.0/net7.0/g' WFBot/WFBot.csproj 14 | RUN dotnet restore "WFBot/WFBot.csproj" && rm -rf WFBot/wwwroot2 && mkdir WFBot/wwwroot2 && touch WFBot/wwwroot2/test 15 | #WORKDIR "/src/WFBot" 16 | RUN dotnet publish "WFBot" -c "Linux Release" -o /app/publish && rm -rf .git 17 | 18 | FROM base AS final 19 | WORKDIR /app 20 | COPY --from=publish /app/publish . 21 | ENTRYPOINT ["dotnet", "WFBot.dll", "--", "--use-config-folder"] 22 | -------------------------------------------------------------------------------- /GitVersion.yml: -------------------------------------------------------------------------------- 1 | assembly-versioning-scheme: MajorMinorPatchTag 2 | assembly-file-versioning-scheme: MajorMinorPatchTag 3 | assembly-informational-format: "{MajorMinorPatch}+{ShortSha}+{env:OFFICIAL_BUILD ?? unofficial}" 4 | mode: Mainline 5 | branches: 6 | release: 7 | mode: ContinuousDelivery 8 | tag: "" 9 | master: 10 | regex: (^master$|^origin\/master$|^universal$|^origin\/universal$) 11 | mode: ContinuousDeployment 12 | tag: "main" 13 | is-mainline: true 14 | pull-request: 15 | mode: ContinuousDeployment 16 | tag: pr 17 | hotfix: 18 | mode: ContinuousDeployment 19 | tag: fix 20 | feature: 21 | mode: ContinuousDeployment 22 | tag: wip 23 | ignore: 24 | sha: [] 25 | -------------------------------------------------------------------------------- /WFBot.Tests/FunctionTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using GammaLibrary.Extensions; 9 | using Humanizer; 10 | using Microsoft.VisualStudio.TestTools.UnitTesting; 11 | using WFBot.Features.Common; 12 | using WFBot.Features.Events; 13 | using WFBot.Features.Utils; 14 | using WFBot.Orichalt; 15 | using WFBot.Utils; 16 | using TestContext = WFBot.Orichalt.OrichaltConnectors.TestContext; 17 | 18 | namespace WFBot.Tests 19 | { 20 | [TestClass] 21 | public class FunctionTest 22 | { 23 | [TestInitialize] 24 | public void Init() 25 | { 26 | core = new WFBotCore(true); 27 | core.Init().Wait(); 28 | Config.Instance.EnableImageRendering = false; 29 | } 30 | WFBotCore core; 31 | [TestMethod] 32 | public void TestFunctions() 33 | { 34 | InputCommand("/金星赏金"); 35 | InputCommand("/金星赏金 5"); 36 | InputCommand("/地球赏金"); 37 | InputCommand("/地球赏金 5"); 38 | InputCommand("/火卫赏金"); 39 | InputCommand("/火卫赏金 7"); 40 | InputCommand("/裂隙"); 41 | InputCommand("/裂隙 1"); 42 | InputCommand("/遗物 后纪L4"); // 我还有一个, 有没有人陪我开了? 43 | InputCommand("/翻译 致残突击"); 44 | InputCommand("/赤毒"); 45 | InputCommand("/警报"); 46 | InputCommand("/突击"); 47 | InputCommand("/入侵"); 48 | InputCommand("/仲裁"); 49 | InputCommand("/午夜电波"); 50 | InputCommand("/平原"); 51 | InputCommand("/活动"); 52 | InputCommand("/虚空商人"); 53 | InputCommand("/小小黑"); 54 | InputCommand("/s船"); 55 | InputCommand("/wiki"); 56 | InputCommand("/查询 Valkyr Prime 一套"); 57 | InputCommand("/紫卡 绝路"); 58 | InputCommand("/WFA紫卡 绝路"); 59 | InputCommand("/wiki Valkyr"); 60 | InputCommand("/status"); 61 | InputCommand("/help"); 62 | InputCommand("/查询 瓦尔基里"); 63 | InputCommand("/查询 电男"); 64 | InputCommand("/查询 致残"); 65 | InputCommand("/虚空风暴 1"); 66 | InputCommand("/钢铁裂缝 1"); 67 | InputCommand("/猎杀"); 68 | File.AppendAllText("TestResult.log", Environment.NewLine + "Done."); 69 | } 70 | 71 | private void InputCommand(string msg) 72 | { 73 | var o = OrichaltContextManager.PutPlatformContext(new TestContext { RawMessage = msg}); 74 | core.messageReceivedEvent.ProcessGroupMessage(o).Wait(); 75 | } 76 | [TestMethod] 77 | public void TestWildcards() 78 | { 79 | var test = new List(); 80 | Assert.IsTrue(WMSearcher.Search("凯旋将军破坏者", ref test)); // 破坏者不加p // 这玩意出错了 81 | test.Clear(); 82 | Assert.IsTrue(WMSearcher.Search("valkyrp", ref test)); // p自动补全为prime 83 | test.Clear(); 84 | Assert.IsTrue(WMSearcher.Search("valkyrp总图", ref test)); // 总图替换成蓝图且替换p 85 | test.Clear(); 86 | Assert.IsTrue(WMSearcher.Search("赫利俄斯p头", ref test)); // 头替换成头部且替换p 87 | test.Clear(); 88 | Assert.IsTrue(WMSearcher.Search("valkyrp头", ref test)); // 头替换成头部神经光元且替换p 89 | test.Clear(); 90 | Assert.IsTrue(WMSearcher.Search("vome", ref test)); // 纯英物品 91 | test.Clear(); 92 | Assert.IsTrue(WMSearcher.Search("hlesptb", ref test)); // 拼音匹配 93 | test.Clear(); 94 | Assert.IsTrue(WMSearcher.Search("hlesptbsjgy", ref test)); // 头部替换成头部神经光元 95 | test.Clear(); 96 | Assert.IsTrue(WMSearcher.Search("电男p", ref test)); // 黑话 97 | test.Clear(); 98 | Assert.IsTrue(WMSearcher.Search("瓦尔基里蓝图", ref test)); // 部件去p 99 | } 100 | } 101 | 102 | /*class MessageSender 103 | { 104 | public GroupID GroupID { get; } 105 | const string resultPath = "TestResult.log"; 106 | public void SendMessage(string msg) 107 | { 108 | 109 | Trace.WriteLine(msg); 110 | if (File.Exists(resultPath) && File.ReadLines(resultPath).Last() == "Done.") // 哈哈 Trick. 111 | { 112 | File.Delete(resultPath); 113 | } 114 | File.AppendAllText(resultPath, msg + Environment.NewLine); 115 | } 116 | }*/ 117 | } 118 | -------------------------------------------------------------------------------- /WFBot.Tests/WFBot.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /WFBot.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.2.32526.322 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WFBot", "WFBot\WFBot.csproj", "{795FA006-A765-48D7-A488-EFD37D7CA474}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WFBot.Tests", "WFBot.Tests\WFBot.Tests.csproj", "{21E1A018-8A75-4A8A-9D1E-7972B782665A}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Linux Release|Any CPU = Linux Release|Any CPU 14 | Release|Any CPU = Release|Any CPU 15 | Windows Release|Any CPU = Windows Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {795FA006-A765-48D7-A488-EFD37D7CA474}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {795FA006-A765-48D7-A488-EFD37D7CA474}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {795FA006-A765-48D7-A488-EFD37D7CA474}.Linux Release|Any CPU.ActiveCfg = Linux Release|Any CPU 21 | {795FA006-A765-48D7-A488-EFD37D7CA474}.Linux Release|Any CPU.Build.0 = Linux Release|Any CPU 22 | {795FA006-A765-48D7-A488-EFD37D7CA474}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {795FA006-A765-48D7-A488-EFD37D7CA474}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {795FA006-A765-48D7-A488-EFD37D7CA474}.Windows Release|Any CPU.ActiveCfg = Windows Release|Any CPU 25 | {795FA006-A765-48D7-A488-EFD37D7CA474}.Windows Release|Any CPU.Build.0 = Windows Release|Any CPU 26 | {21E1A018-8A75-4A8A-9D1E-7972B782665A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {21E1A018-8A75-4A8A-9D1E-7972B782665A}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {21E1A018-8A75-4A8A-9D1E-7972B782665A}.Linux Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {21E1A018-8A75-4A8A-9D1E-7972B782665A}.Linux Release|Any CPU.Build.0 = Release|Any CPU 30 | {21E1A018-8A75-4A8A-9D1E-7972B782665A}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {21E1A018-8A75-4A8A-9D1E-7972B782665A}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {21E1A018-8A75-4A8A-9D1E-7972B782665A}.Windows Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {21E1A018-8A75-4A8A-9D1E-7972B782665A}.Windows Release|Any CPU.Build.0 = Release|Any CPU 34 | EndGlobalSection 35 | GlobalSection(SolutionProperties) = preSolution 36 | HideSolutionNode = FALSE 37 | EndGlobalSection 38 | GlobalSection(ExtensibilityGlobals) = postSolution 39 | SolutionGuid = {58C7DA26-10AD-4042-920B-AFFFFCBA8B2A} 40 | EndGlobalSection 41 | EndGlobal 42 | -------------------------------------------------------------------------------- /WFBot/7zip/Common/CRC.cs: -------------------------------------------------------------------------------- 1 | // Common/CRC.cs 2 | 3 | namespace SevenZip 4 | { 5 | class CRC 6 | { 7 | public static readonly uint[] Table; 8 | 9 | static CRC() 10 | { 11 | Table = new uint[256]; 12 | const uint kPoly = 0xEDB88320; 13 | for (uint i = 0; i < 256; i++) 14 | { 15 | uint r = i; 16 | for (int j = 0; j < 8; j++) 17 | if ((r & 1) != 0) 18 | r = (r >> 1) ^ kPoly; 19 | else 20 | r >>= 1; 21 | Table[i] = r; 22 | } 23 | } 24 | 25 | uint _value = 0xFFFFFFFF; 26 | 27 | public void Init() { _value = 0xFFFFFFFF; } 28 | 29 | public void UpdateByte(byte b) 30 | { 31 | _value = Table[(((byte)(_value)) ^ b)] ^ (_value >> 8); 32 | } 33 | 34 | public void Update(byte[] data, uint offset, uint size) 35 | { 36 | for (uint i = 0; i < size; i++) 37 | _value = Table[(((byte)(_value)) ^ data[offset + i])] ^ (_value >> 8); 38 | } 39 | 40 | public uint GetDigest() { return _value ^ 0xFFFFFFFF; } 41 | 42 | static uint CalculateDigest(byte[] data, uint offset, uint size) 43 | { 44 | CRC crc = new CRC(); 45 | // crc.Init(); 46 | crc.Update(data, offset, size); 47 | return crc.GetDigest(); 48 | } 49 | 50 | static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size) 51 | { 52 | return (CalculateDigest(data, offset, size) == digest); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /WFBot/7zip/Compress/LZ/IMatchFinder.cs: -------------------------------------------------------------------------------- 1 | // IMatchFinder.cs 2 | 3 | using System; 4 | 5 | namespace SevenZip.Compression.LZ 6 | { 7 | interface IInWindowStream 8 | { 9 | void SetStream(System.IO.Stream inStream); 10 | void Init(); 11 | void ReleaseStream(); 12 | Byte GetIndexByte(Int32 index); 13 | UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit); 14 | UInt32 GetNumAvailableBytes(); 15 | } 16 | 17 | interface IMatchFinder : IInWindowStream 18 | { 19 | void Create(UInt32 historySize, UInt32 keepAddBufferBefore, 20 | UInt32 matchMaxLen, UInt32 keepAddBufferAfter); 21 | UInt32 GetMatches(UInt32[] distances); 22 | void Skip(UInt32 num); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /WFBot/7zip/Compress/LZ/LzOutWindow.cs: -------------------------------------------------------------------------------- 1 | // LzOutWindow.cs 2 | 3 | namespace SevenZip.Compression.LZ 4 | { 5 | public class OutWindow 6 | { 7 | byte[] _buffer = null; 8 | uint _pos; 9 | uint _windowSize = 0; 10 | uint _streamPos; 11 | System.IO.Stream _stream; 12 | 13 | public uint TrainSize = 0; 14 | 15 | public void Create(uint windowSize) 16 | { 17 | if (_windowSize != windowSize) 18 | { 19 | // System.GC.Collect(); 20 | _buffer = new byte[windowSize]; 21 | } 22 | _windowSize = windowSize; 23 | _pos = 0; 24 | _streamPos = 0; 25 | } 26 | 27 | public void Init(System.IO.Stream stream, bool solid) 28 | { 29 | ReleaseStream(); 30 | _stream = stream; 31 | if (!solid) 32 | { 33 | _streamPos = 0; 34 | _pos = 0; 35 | TrainSize = 0; 36 | } 37 | } 38 | 39 | public bool Train(System.IO.Stream stream) 40 | { 41 | long len = stream.Length; 42 | uint size = (len < _windowSize) ? (uint)len : _windowSize; 43 | TrainSize = size; 44 | stream.Position = len - size; 45 | _streamPos = _pos = 0; 46 | while (size > 0) 47 | { 48 | uint curSize = _windowSize - _pos; 49 | if (size < curSize) 50 | curSize = size; 51 | int numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize); 52 | if (numReadBytes == 0) 53 | return false; 54 | size -= (uint)numReadBytes; 55 | _pos += (uint)numReadBytes; 56 | _streamPos += (uint)numReadBytes; 57 | if (_pos == _windowSize) 58 | _streamPos = _pos = 0; 59 | } 60 | return true; 61 | } 62 | 63 | public void ReleaseStream() 64 | { 65 | Flush(); 66 | _stream = null; 67 | } 68 | 69 | public void Flush() 70 | { 71 | uint size = _pos - _streamPos; 72 | if (size == 0) 73 | return; 74 | _stream.Write(_buffer, (int)_streamPos, (int)size); 75 | if (_pos >= _windowSize) 76 | _pos = 0; 77 | _streamPos = _pos; 78 | } 79 | 80 | public void CopyBlock(uint distance, uint len) 81 | { 82 | uint pos = _pos - distance - 1; 83 | if (pos >= _windowSize) 84 | pos += _windowSize; 85 | for (; len > 0; len--) 86 | { 87 | if (pos >= _windowSize) 88 | pos = 0; 89 | _buffer[_pos++] = _buffer[pos++]; 90 | if (_pos >= _windowSize) 91 | Flush(); 92 | } 93 | } 94 | 95 | public void PutByte(byte b) 96 | { 97 | _buffer[_pos++] = b; 98 | if (_pos >= _windowSize) 99 | Flush(); 100 | } 101 | 102 | public byte GetByte(uint distance) 103 | { 104 | uint pos = _pos - distance - 1; 105 | if (pos >= _windowSize) 106 | pos += _windowSize; 107 | return _buffer[pos]; 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /WFBot/7zip/Compress/LZMA/LzmaBase.cs: -------------------------------------------------------------------------------- 1 | // LzmaBase.cs 2 | 3 | namespace SevenZip.Compression.LZMA 4 | { 5 | internal abstract class Base 6 | { 7 | public const uint kNumRepDistances = 4; 8 | public const uint kNumStates = 12; 9 | 10 | // static byte []kLiteralNextStates = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; 11 | // static byte []kMatchNextStates = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; 12 | // static byte []kRepNextStates = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; 13 | // static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; 14 | 15 | public struct State 16 | { 17 | public uint Index; 18 | public void Init() { Index = 0; } 19 | public void UpdateChar() 20 | { 21 | if (Index < 4) Index = 0; 22 | else if (Index < 10) Index -= 3; 23 | else Index -= 6; 24 | } 25 | public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); } 26 | public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); } 27 | public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); } 28 | public bool IsCharState() { return Index < 7; } 29 | } 30 | 31 | public const int kNumPosSlotBits = 6; 32 | public const int kDicLogSizeMin = 0; 33 | // public const int kDicLogSizeMax = 30; 34 | // public const uint kDistTableSizeMax = kDicLogSizeMax * 2; 35 | 36 | public const int kNumLenToPosStatesBits = 2; // it's for speed optimization 37 | public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits; 38 | 39 | public const uint kMatchMinLen = 2; 40 | 41 | public static uint GetLenToPosState(uint len) 42 | { 43 | len -= kMatchMinLen; 44 | if (len < kNumLenToPosStates) 45 | return len; 46 | return (uint)(kNumLenToPosStates - 1); 47 | } 48 | 49 | public const int kNumAlignBits = 4; 50 | public const uint kAlignTableSize = 1 << kNumAlignBits; 51 | public const uint kAlignMask = (kAlignTableSize - 1); 52 | 53 | public const uint kStartPosModelIndex = 4; 54 | public const uint kEndPosModelIndex = 14; 55 | public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; 56 | 57 | public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2); 58 | 59 | public const uint kNumLitPosStatesBitsEncodingMax = 4; 60 | public const uint kNumLitContextBitsMax = 8; 61 | 62 | public const int kNumPosStatesBitsMax = 4; 63 | public const uint kNumPosStatesMax = (1 << kNumPosStatesBitsMax); 64 | public const int kNumPosStatesBitsEncodingMax = 4; 65 | public const uint kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); 66 | 67 | public const int kNumLowLenBits = 3; 68 | public const int kNumMidLenBits = 3; 69 | public const int kNumHighLenBits = 8; 70 | public const uint kNumLowLenSymbols = 1 << kNumLowLenBits; 71 | public const uint kNumMidLenSymbols = 1 << kNumMidLenBits; 72 | public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + 73 | (1 << kNumHighLenBits); 74 | public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /WFBot/7zip/Compress/RangeCoder/RangeCoderBit.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SevenZip.Compression.RangeCoder 4 | { 5 | struct BitEncoder 6 | { 7 | public const int kNumBitModelTotalBits = 11; 8 | public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); 9 | const int kNumMoveBits = 5; 10 | const int kNumMoveReducingBits = 2; 11 | public const int kNumBitPriceShiftBits = 6; 12 | 13 | uint Prob; 14 | 15 | public void Init() { Prob = kBitModelTotal >> 1; } 16 | 17 | public void UpdateModel(uint symbol) 18 | { 19 | if (symbol == 0) 20 | Prob += (kBitModelTotal - Prob) >> kNumMoveBits; 21 | else 22 | Prob -= (Prob) >> kNumMoveBits; 23 | } 24 | 25 | public void Encode(Encoder encoder, uint symbol) 26 | { 27 | // encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol); 28 | // UpdateModel(symbol); 29 | uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob; 30 | if (symbol == 0) 31 | { 32 | encoder.Range = newBound; 33 | Prob += (kBitModelTotal - Prob) >> kNumMoveBits; 34 | } 35 | else 36 | { 37 | encoder.Low += newBound; 38 | encoder.Range -= newBound; 39 | Prob -= (Prob) >> kNumMoveBits; 40 | } 41 | if (encoder.Range < Encoder.kTopValue) 42 | { 43 | encoder.Range <<= 8; 44 | encoder.ShiftLow(); 45 | } 46 | } 47 | 48 | private static UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits]; 49 | 50 | static BitEncoder() 51 | { 52 | const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); 53 | for (int i = kNumBits - 1; i >= 0; i--) 54 | { 55 | UInt32 start = (UInt32)1 << (kNumBits - i - 1); 56 | UInt32 end = (UInt32)1 << (kNumBits - i); 57 | for (UInt32 j = start; j < end; j++) 58 | ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) + 59 | (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); 60 | } 61 | } 62 | 63 | public uint GetPrice(uint symbol) 64 | { 65 | return ProbPrices[(((Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; 66 | } 67 | public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; } 68 | public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; } 69 | } 70 | 71 | struct BitDecoder 72 | { 73 | public const int kNumBitModelTotalBits = 11; 74 | public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); 75 | const int kNumMoveBits = 5; 76 | 77 | uint Prob; 78 | 79 | public void UpdateModel(int numMoveBits, uint symbol) 80 | { 81 | if (symbol == 0) 82 | Prob += (kBitModelTotal - Prob) >> numMoveBits; 83 | else 84 | Prob -= (Prob) >> numMoveBits; 85 | } 86 | 87 | public void Init() { Prob = kBitModelTotal >> 1; } 88 | 89 | public uint Decode(RangeCoder.Decoder rangeDecoder) 90 | { 91 | uint newBound = (uint)(rangeDecoder.Range >> kNumBitModelTotalBits) * (uint)Prob; 92 | if (rangeDecoder.Code < newBound) 93 | { 94 | rangeDecoder.Range = newBound; 95 | Prob += (kBitModelTotal - Prob) >> kNumMoveBits; 96 | if (rangeDecoder.Range < Decoder.kTopValue) 97 | { 98 | rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); 99 | rangeDecoder.Range <<= 8; 100 | } 101 | return 0; 102 | } 103 | else 104 | { 105 | rangeDecoder.Range -= newBound; 106 | rangeDecoder.Code -= newBound; 107 | Prob -= (Prob) >> kNumMoveBits; 108 | if (rangeDecoder.Range < Decoder.kTopValue) 109 | { 110 | rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); 111 | rangeDecoder.Range <<= 8; 112 | } 113 | return 1; 114 | } 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /WFBot/7zip/Compress/RangeCoder/RangeCoderBitTree.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SevenZip.Compression.RangeCoder 4 | { 5 | struct BitTreeEncoder 6 | { 7 | BitEncoder[] Models; 8 | int NumBitLevels; 9 | 10 | public BitTreeEncoder(int numBitLevels) 11 | { 12 | NumBitLevels = numBitLevels; 13 | Models = new BitEncoder[1 << numBitLevels]; 14 | } 15 | 16 | public void Init() 17 | { 18 | for (uint i = 1; i < (1 << NumBitLevels); i++) 19 | Models[i].Init(); 20 | } 21 | 22 | public void Encode(Encoder rangeEncoder, UInt32 symbol) 23 | { 24 | UInt32 m = 1; 25 | for (int bitIndex = NumBitLevels; bitIndex > 0; ) 26 | { 27 | bitIndex--; 28 | UInt32 bit = (symbol >> bitIndex) & 1; 29 | Models[m].Encode(rangeEncoder, bit); 30 | m = (m << 1) | bit; 31 | } 32 | } 33 | 34 | public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol) 35 | { 36 | UInt32 m = 1; 37 | for (UInt32 i = 0; i < NumBitLevels; i++) 38 | { 39 | UInt32 bit = symbol & 1; 40 | Models[m].Encode(rangeEncoder, bit); 41 | m = (m << 1) | bit; 42 | symbol >>= 1; 43 | } 44 | } 45 | 46 | public UInt32 GetPrice(UInt32 symbol) 47 | { 48 | UInt32 price = 0; 49 | UInt32 m = 1; 50 | for (int bitIndex = NumBitLevels; bitIndex > 0; ) 51 | { 52 | bitIndex--; 53 | UInt32 bit = (symbol >> bitIndex) & 1; 54 | price += Models[m].GetPrice(bit); 55 | m = (m << 1) + bit; 56 | } 57 | return price; 58 | } 59 | 60 | public UInt32 ReverseGetPrice(UInt32 symbol) 61 | { 62 | UInt32 price = 0; 63 | UInt32 m = 1; 64 | for (int i = NumBitLevels; i > 0; i--) 65 | { 66 | UInt32 bit = symbol & 1; 67 | symbol >>= 1; 68 | price += Models[m].GetPrice(bit); 69 | m = (m << 1) | bit; 70 | } 71 | return price; 72 | } 73 | 74 | public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex, 75 | int NumBitLevels, UInt32 symbol) 76 | { 77 | UInt32 price = 0; 78 | UInt32 m = 1; 79 | for (int i = NumBitLevels; i > 0; i--) 80 | { 81 | UInt32 bit = symbol & 1; 82 | symbol >>= 1; 83 | price += Models[startIndex + m].GetPrice(bit); 84 | m = (m << 1) | bit; 85 | } 86 | return price; 87 | } 88 | 89 | public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex, 90 | Encoder rangeEncoder, int NumBitLevels, UInt32 symbol) 91 | { 92 | UInt32 m = 1; 93 | for (int i = 0; i < NumBitLevels; i++) 94 | { 95 | UInt32 bit = symbol & 1; 96 | Models[startIndex + m].Encode(rangeEncoder, bit); 97 | m = (m << 1) | bit; 98 | symbol >>= 1; 99 | } 100 | } 101 | } 102 | 103 | struct BitTreeDecoder 104 | { 105 | BitDecoder[] Models; 106 | int NumBitLevels; 107 | 108 | public BitTreeDecoder(int numBitLevels) 109 | { 110 | NumBitLevels = numBitLevels; 111 | Models = new BitDecoder[1 << numBitLevels]; 112 | } 113 | 114 | public void Init() 115 | { 116 | for (uint i = 1; i < (1 << NumBitLevels); i++) 117 | Models[i].Init(); 118 | } 119 | 120 | public uint Decode(RangeCoder.Decoder rangeDecoder) 121 | { 122 | uint m = 1; 123 | for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--) 124 | m = (m << 1) + Models[m].Decode(rangeDecoder); 125 | return m - ((uint)1 << NumBitLevels); 126 | } 127 | 128 | public uint ReverseDecode(RangeCoder.Decoder rangeDecoder) 129 | { 130 | uint m = 1; 131 | uint symbol = 0; 132 | for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) 133 | { 134 | uint bit = Models[m].Decode(rangeDecoder); 135 | m <<= 1; 136 | m += bit; 137 | symbol |= (bit << bitIndex); 138 | } 139 | return symbol; 140 | } 141 | 142 | public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex, 143 | RangeCoder.Decoder rangeDecoder, int NumBitLevels) 144 | { 145 | uint m = 1; 146 | uint symbol = 0; 147 | for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) 148 | { 149 | uint bit = Models[startIndex + m].Decode(rangeDecoder); 150 | m <<= 1; 151 | m += bit; 152 | symbol |= (bit << bitIndex); 153 | } 154 | return symbol; 155 | } 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /WFBot/7zip/ICoder.cs: -------------------------------------------------------------------------------- 1 | // ICoder.h 2 | 3 | using System; 4 | 5 | namespace SevenZip 6 | { 7 | /// 8 | /// The exception that is thrown when an error in input stream occurs during decoding. 9 | /// 10 | class DataErrorException : ApplicationException 11 | { 12 | public DataErrorException(): base("Data Error") { } 13 | } 14 | 15 | /// 16 | /// The exception that is thrown when the value of an argument is outside the allowable range. 17 | /// 18 | class InvalidParamException : ApplicationException 19 | { 20 | public InvalidParamException(): base("Invalid Parameter") { } 21 | } 22 | 23 | public interface ICodeProgress 24 | { 25 | /// 26 | /// Callback progress. 27 | /// 28 | /// 29 | /// input size. -1 if unknown. 30 | /// 31 | /// 32 | /// output size. -1 if unknown. 33 | /// 34 | void SetProgress(Int64 inSize, Int64 outSize); 35 | }; 36 | 37 | public interface ICoder 38 | { 39 | /// 40 | /// Codes streams. 41 | /// 42 | /// 43 | /// input Stream. 44 | /// 45 | /// 46 | /// output Stream. 47 | /// 48 | /// 49 | /// input Size. -1 if unknown. 50 | /// 51 | /// 52 | /// output Size. -1 if unknown. 53 | /// 54 | /// 55 | /// callback progress reference. 56 | /// 57 | /// 58 | /// if input stream is not valid 59 | /// 60 | void Code(System.IO.Stream inStream, System.IO.Stream outStream, 61 | Int64 inSize, Int64 outSize, ICodeProgress progress); 62 | }; 63 | 64 | /* 65 | public interface ICoder2 66 | { 67 | void Code(ISequentialInStream []inStreams, 68 | const UInt64 []inSizes, 69 | ISequentialOutStream []outStreams, 70 | UInt64 []outSizes, 71 | ICodeProgress progress); 72 | }; 73 | */ 74 | 75 | /// 76 | /// Provides the fields that represent properties idenitifiers for compressing. 77 | /// 78 | public enum CoderPropID 79 | { 80 | /// 81 | /// Specifies default property. 82 | /// 83 | DefaultProp = 0, 84 | /// 85 | /// Specifies size of dictionary. 86 | /// 87 | DictionarySize, 88 | /// 89 | /// Specifies size of memory for PPM*. 90 | /// 91 | UsedMemorySize, 92 | /// 93 | /// Specifies order for PPM methods. 94 | /// 95 | Order, 96 | /// 97 | /// Specifies Block Size. 98 | /// 99 | BlockSize, 100 | /// 101 | /// Specifies number of postion state bits for LZMA (0 <= x <= 4). 102 | /// 103 | PosStateBits, 104 | /// 105 | /// Specifies number of literal context bits for LZMA (0 <= x <= 8). 106 | /// 107 | LitContextBits, 108 | /// 109 | /// Specifies number of literal position bits for LZMA (0 <= x <= 4). 110 | /// 111 | LitPosBits, 112 | /// 113 | /// Specifies number of fast bytes for LZ*. 114 | /// 115 | NumFastBytes, 116 | /// 117 | /// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B". 118 | /// 119 | MatchFinder, 120 | /// 121 | /// Specifies the number of match finder cyckes. 122 | /// 123 | MatchFinderCycles, 124 | /// 125 | /// Specifies number of passes. 126 | /// 127 | NumPasses, 128 | /// 129 | /// Specifies number of algorithm. 130 | /// 131 | Algorithm, 132 | /// 133 | /// Specifies the number of threads. 134 | /// 135 | NumThreads, 136 | /// 137 | /// Specifies mode with end marker. 138 | /// 139 | EndMarker 140 | }; 141 | 142 | 143 | public interface ISetCoderProperties 144 | { 145 | void SetCoderProperties(CoderPropID[] propIDs, object[] properties); 146 | }; 147 | 148 | public interface IWriteCoderProperties 149 | { 150 | void WriteCoderProperties(System.IO.Stream outStream); 151 | } 152 | 153 | public interface ISetDecoderProperties 154 | { 155 | void SetDecoderProperties(byte[] properties); 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /WFBot/Config.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using GammaLibrary.Extensions; 5 | using Newtonsoft.Json; 6 | using WFBot.Features.Other; 7 | using WFBot.Orichalt; 8 | using WFBot.Utils; 9 | using WFBot.Windows; 10 | 11 | namespace WFBot 12 | { 13 | [Configuration("WFConfig")] 14 | public class Config : Configuration 15 | { 16 | public string ClientGUID = Guid.NewGuid().ToString("D"); 17 | public string WebUIPassword = ""; 18 | 19 | public List WFGroupList = new List(); 20 | 21 | public List InvationRewardList = new List(); 22 | 23 | public string Code = "*******"; 24 | 25 | public string QQ; 26 | 27 | public bool AcceptInvitation; 28 | 29 | public bool AcceptJoiningRequest; 30 | 31 | public string ClientId; 32 | 33 | public string ClientSecret; 34 | 35 | public string AcessToken; 36 | 37 | public DateTime Last_update; 38 | 39 | [JsonProperty("Git" + "hubOAuthKey")] 40 | public string GitHubOAuthKey; 41 | 42 | public bool IsSlashRequired = false; 43 | 44 | public int CallperMinute = 0; 45 | 46 | public Platform Platform = Platform.PC; 47 | 48 | public bool IsThirdPartyWM = false; 49 | 50 | public bool IsAlertRequiredRareItem = true; 51 | 52 | public bool AutoUpdate = true; 53 | 54 | public bool UpdateLexion = true; 55 | 56 | public string localsha; 57 | 58 | public int WMSearchCount = 5; 59 | 60 | public int WFASearchCount = 5; 61 | 62 | public bool IsPublicBot = false;// 大聪明用户, 别改这个参数. 63 | 64 | public DateTime SendSentientOutpostTime = DateTime.Now; 65 | 66 | public bool NotifyBeforeResult = true; 67 | 68 | public Dictionary CustomReplies = new Dictionary(); 69 | 70 | public bool UseTelemetry = true; 71 | public bool SendResourceUpdateNotification = true; 72 | public MessagePlatform Miguel_Platform = MessagePlatform.Unknown; 73 | public bool EnableCustomCommandContent = false; 74 | public bool EnableImageRendering = true; 75 | public string WFBotProxyToken = ""; 76 | public bool UseWFBotProxy = false; 77 | public bool UseKraber = true; 78 | public bool CleanMemoryAfterImageRendering = false; 79 | public bool UseImagePGO = false; 80 | public bool AtAllBroadcast = false; 81 | public string BotMarketUUID = ""; 82 | public bool BroadcastToAllGroup = false; 83 | 84 | protected override void AfterUpdate() 85 | { 86 | // 这里我写的好丑 87 | // It's not stupid if it works 88 | if (Code.IsNullOrWhiteSpace() || Code.Contains(' ')) 89 | { 90 | Trace.WriteLine("警告: 口令中包含空格, 可能会影响带口令指令的使用."); 91 | } 92 | 93 | if (GitHubOAuthKey.NotNullNorWhiteSpace() && GitHubOAuthKey.Length != 40) 94 | { 95 | Trace.WriteLine("警告: GitHubOauthKey 格式错误, 如果你不知道这是什么请不要乱填."); 96 | } 97 | } 98 | } 99 | 100 | } -------------------------------------------------------------------------------- /WFBot/Dll/PininSharp.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Dll/PininSharp.dll -------------------------------------------------------------------------------- /WFBot/Dll/SuffixTreeSharp.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Dll/SuffixTreeSharp.dll -------------------------------------------------------------------------------- /WFBot/Features/Commands/BotCommands.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Threading.Tasks; 5 | using WFBot.Features.ImageRendering; 6 | using WFBot.Features.Telemetry; 7 | using WFBot.Features.Utils; 8 | using WFBot.Orichalt; 9 | using WFBot.TextCommandCore; 10 | using WFBot.Utils; 11 | 12 | namespace WFBot.Features.Commands 13 | { 14 | public partial class CommandsHandler 15 | { 16 | string VersionText => WFBotCore.IsOfficial ? $"WFBot 官方 {(WFBotCore.Version)}" : $"WFBot 非官方 {(WFBotCore.Version)}"; 17 | 18 | [MatchersIgnoreCase("wfbotversion", "wfbot-version")] 19 | string Version() 20 | { 21 | return VersionText; 22 | } 23 | 24 | [Matchers("help", "帮助", "功能")] 25 | void HelpDoc() 26 | { 27 | MiguelNetwork.Reply(O, WFFormatter.HelpCommandSegment1()); 28 | if (AsyncContext.GetUseImageRendering()) 29 | { 30 | SendImage(ImageRenderHelper.SimpleImageRendering(WFFormatter.HelpCommandSegment2())); 31 | } 32 | else 33 | { 34 | MiguelNetwork.Reply(O, WFFormatter.HelpCommandSegment2()); 35 | } 36 | } 37 | 38 | [DoNotMeasureTime] 39 | [AddPlatformInfo] 40 | [Matchers("状态", "status", "机器人状态", "机器人信息", "我需要机器人")] 41 | async Task Status() 42 | { 43 | var sb = new StringBuilder(); 44 | var q1 = WebHelper.TryGet("https://warframestat.us"); 45 | var q2 = WebHelper.TryGet("https://api.warframe.market/v1/items/valkyr_prime_set/orders?include=item"); 46 | var q3 = WebHelper.TryGet("https://wfbot.kraber.top:8888/Resources/"); 47 | var commitTask = Task.Run(() => 48 | CommitsGetter.Get("https://api.github.com/repos/TRKS-Team/WFBot/commits?per_page=5")); 49 | // var q3 = Task.Run(() => WebHelper.TryGet("https://api.richasy.cn/wfa/rm/riven")); 50 | // var q4 = Task.Run(() => WebHelper.TryGet("https://10o.io/kuvalog.json")); 51 | 52 | var apistat = await q1; 53 | var wmstat = await q2; 54 | var cdnstat = await q3; 55 | var commitResult = await commitTask; 56 | // var wfastat = await q3; 57 | // var kuvastat = await q4; 58 | 59 | if (AsyncContext.GetUseImageRendering()) 60 | { 61 | SendImage(ImageRenderHelper.SimpleImageRendering(WFFormatter.FormatStatusCommand(apistat, wmstat, cdnstat, sb, commitResult))); 62 | OutputStringBuilder.Value.Clear(); 63 | return ""; 64 | } 65 | else 66 | { 67 | return WFFormatter.FormatStatusCommand(apistat, wmstat, cdnstat, sb, commitResult); 68 | } 69 | } 70 | 71 | 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /WFBot/Features/Commands/CommandsBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Threading.Tasks; 5 | using WarframeAlertingPrime.SDK.Models.GameInfo; 6 | using WFBot.Events; 7 | using WFBot.Features.Common; 8 | using WFBot.Features.ImageRendering; 9 | using WFBot.Features.Utils; 10 | using WFBot.Orichalt; 11 | using WFBot.TextCommandCore; 12 | using WFBot.Utils; 13 | using static WFBot.Features.Utils.Messenger; 14 | 15 | namespace WFBot.Features.Commands 16 | { 17 | public partial class CommandsHandler : ICommandHandler 18 | { 19 | public Action MessageSender { get; } 20 | public Action RichMessageSender { get; set; } 21 | public Action ErrorMessageSender { get; } 22 | public string Message { get; } 23 | public OrichaltContext O { get; private set; } 24 | public readonly Lazy OutputStringBuilder = new Lazy(() => new StringBuilder()); 25 | 26 | private static readonly WMSearcher _wmSearcher = new WMSearcher(); 27 | private static readonly RMSearcher _rmSearcher = new RMSearcher(); 28 | private static readonly WMASearcher _wmaSearcher = new WMASearcher(); 29 | 30 | 31 | void SendImage(byte[] bytes) 32 | { 33 | RichMessageSender(new RichMessages() { new ImageMessage() { Content = bytes } }); 34 | } 35 | 36 | void SendImageAndText(byte[] bytes, string s) 37 | { 38 | RichMessageSender(new RichMessages() { new ImageMessage() { Content = bytes }, new TextMessage() {Content = s} }); 39 | } 40 | 41 | void Append(string s) 42 | { 43 | OutputStringBuilder.Value.Append(s); 44 | } 45 | 46 | void AppendLine(string s) 47 | { 48 | OutputStringBuilder.Value.AppendLine(s); 49 | } 50 | 51 | void AppendLine() 52 | { 53 | OutputStringBuilder.Value.AppendLine(); 54 | } 55 | 56 | public CommandsHandler(OrichaltContext o, string message) 57 | { 58 | MessageSender = (msg) => 59 | { 60 | MiguelNetwork.Reply(AsyncContext.GetOrichaltContext(), msg.Content); 61 | }; 62 | RichMessageSender = (msg) => 63 | { 64 | MiguelNetwork.Reply(AsyncContext.GetOrichaltContext(), msg); 65 | }; 66 | Message = message; 67 | O = o; 68 | ErrorMessageSender = msg => SendDebugInfo(msg); 69 | } 70 | 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /WFBot/Features/Commands/KookSpecificCommands.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using Humanizer; 3 | using WFBot.Features.Utils; 4 | using WFBot.Orichalt; 5 | using WFBot.TextCommandCore; 6 | 7 | namespace WFBot.Features.Commands 8 | { 9 | public partial class CommandsHandler 10 | { 11 | [SkipBotChannelCheck] 12 | [SkipValidationCheck] 13 | [KookOnly] 14 | [Matchers("设置通知频道", "设置通知")] 15 | void AddNotifyChannel() 16 | { 17 | MiguelNetwork.KookCore.SetKookNotifyChannel(O); 18 | } 19 | 20 | [SkipBotChannelCheck] 21 | [SkipValidationCheck] 22 | [KookOnly] 23 | [Matchers("取消通知频道", "取消通知")] 24 | void RemoveNotifyChannel() 25 | { 26 | MiguelNetwork.KookCore.RemoveKookNotifyChannel(O); 27 | } 28 | 29 | [SkipBotChannelCheck] 30 | [SkipValidationCheck] 31 | [KookOnly] 32 | [Matchers("设置机器人频道", "设置机器人")] 33 | void AddBotChannel() 34 | { 35 | MiguelNetwork.KookCore.SetKookBotChannel(O); 36 | } 37 | 38 | [SkipBotChannelCheck] 39 | [SkipValidationCheck] 40 | [KookOnly] 41 | [Matchers("取消机器人频道", "取消机器人")] 42 | void RemoveBotChannel() 43 | { 44 | MiguelNetwork.KookCore.RemoveKookBotChannel(O); 45 | } 46 | 47 | [SkipBotChannelCheck] 48 | [SkipValidationCheck] 49 | [KookOnly] 50 | [Matchers("兑换")] 51 | [CombineParams] 52 | string Redeem(string code) 53 | { 54 | return MiguelNetwork.KookVerifyServer.RedeemCode(O, code).Result ? "兑换成功, 请输入 /有效期 查询有效期" : "兑换失败, 请检查兑换码有效性."; 55 | } 56 | [SkipBotChannelCheck] 57 | [SkipValidationCheck] 58 | [KookOnly] 59 | [Matchers("有效期")] 60 | string ExpireTime() 61 | { 62 | return $"本服务器的机器人有效期为: {MiguelNetwork.KookVerifyServer.GetGuildValidationTime(O).Result.Humanize()}\n状态: {(MiguelNetwork.KookVerifyServer.VerifyGuild(O).Result ? "未过期": "已过期")}"; 63 | } 64 | 65 | [SkipBotChannelCheck] 66 | [SkipValidationCheck] 67 | [KookOnly] 68 | [Matchers("试用")] 69 | string Trial() 70 | { 71 | return MiguelNetwork.KookVerifyServer.StartGuildTrial(O).Result ? "成功激活三天试用, 请输入 /有效期 查询有效期." : "激活试用失败, 此服务器已经试用过机器人."; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /WFBot/Features/Commands/NotificationCommands.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using WFBot.Features.Common; 7 | using WFBot.Features.ImageRendering; 8 | using WFBot.Features.Other; 9 | using WFBot.Features.Utils; 10 | using WFBot.TextCommandCore; 11 | using WFBot.Utils; 12 | 13 | namespace WFBot.Features.Commands 14 | { 15 | 16 | public partial class CommandsHandler 17 | { 18 | WFNotificationHandler WFNotificationHandler => WFBotCore.Instance.NotificationHandler; 19 | 20 | [Matchers("警报")] 21 | [AddPlatformInfo] 22 | async Task Alerts() 23 | { 24 | try 25 | { 26 | await WFNotificationHandler.UpdateAlertPool(); 27 | } 28 | catch (OperationCanceledException) 29 | { 30 | Append("操作超时."); 31 | return; 32 | } 33 | var alerts = WFNotificationHandler.AlertPool; 34 | 35 | AppendLine("指挥官, 下面是太阳系内所有的警报任务, 供您挑选."); 36 | foreach (var alert in alerts) 37 | { 38 | AppendLine(WFFormatter.ToString(alert)); 39 | AppendLine(); 40 | } 41 | 42 | if (AsyncContext.GetUseImageRendering()) 43 | { 44 | SendImage(ImageRenderHelper.SimpleImageRendering(OutputStringBuilder.Value.ToString())); 45 | OutputStringBuilder.Value.Clear(); 46 | } 47 | } 48 | 49 | [Matchers("入侵")] 50 | [AddPlatformInfo] 51 | async Task Invasions() 52 | { 53 | if (AsyncContext.GetUseImageRendering()) 54 | { 55 | var i = ImageRenderingPGO.Invasion(); 56 | if (i != null) 57 | { 58 | SendImage(i); 59 | return; 60 | } 61 | } 62 | try 63 | { 64 | await WFNotificationHandler.UpdateInvasionPool(); 65 | } 66 | catch (OperationCanceledException) 67 | { 68 | Append("操作超时."); 69 | return; 70 | } 71 | var invasions = WFNotificationHandler.InvasionPool; 72 | 73 | if (!AsyncContext.GetUseImageRendering()) 74 | { 75 | AppendLine("指挥官, 下面是太阳系内所有的入侵任务."); 76 | AppendLine(); 77 | 78 | foreach (var invasion in invasions.Where(invasion => !invasion.completed)) 79 | { 80 | AppendLine(WFFormatter.ToString(invasion)); 81 | AppendLine(); 82 | } 83 | } 84 | else 85 | { 86 | SendImage(ImageRenderHelper.Invasion(invasions.Where(invasion => !invasion.completed))); 87 | } 88 | 89 | } 90 | 91 | [Matchers("小小黑", "追随者")] 92 | async Task AllPersistentEnemies() 93 | { 94 | // ask toma 为什么这里不需要 UpdatePersistentEnemiePool 95 | // 我他妈忘了 96 | try 97 | { 98 | await WFNotificationHandler.UpdatePersistentEnemiePool(); 99 | } 100 | catch (OperationCanceledException) 101 | { 102 | Append("操作超时."); 103 | return; 104 | } 105 | var enemies = WFNotificationHandler.StalkerPool; 106 | if (!enemies.Any()) 107 | { 108 | Append("目前没有小小黑出现."); 109 | return; 110 | } 111 | 112 | AppendLine("下面是全太阳系内的小小黑, 快去锤爆?"); 113 | foreach (var enemy in enemies) 114 | { 115 | AppendLine(WFFormatter.ToString(enemy)); 116 | } 117 | if (AsyncContext.GetUseImageRendering()) 118 | { 119 | SendImage(ImageRenderHelper.SimpleImageRendering(OutputStringBuilder.Value.ToString())); 120 | OutputStringBuilder.Value.Clear(); 121 | } 122 | } 123 | 124 | } 125 | } -------------------------------------------------------------------------------- /WFBot/Features/Commands/WikiCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using WFBot.Features.Utils; 7 | using WFBot.TextCommandCore; 8 | using WFBot.Utils; 9 | 10 | namespace WFBot.Features.Commands 11 | { 12 | 13 | public partial class CommandsHandler 14 | { 15 | [Matchers("wiki", "wk")] 16 | [CombineParams] 17 | async Task Wiki(string word = "wiki") 18 | { 19 | if (word == "wiki") 20 | { 21 | return WFFormatter.GetWikiLink(); 22 | } 23 | 24 | var wiki = await GetWiki(word); 25 | return WFFormatter.FormatWikiCommand(word, wiki); 26 | /*return 27 | "灰机wiki的warframe分区由于不规范爬虫导致暂时隔离, warframe区全站不可访问, 具体信息请看: https://www.huijiwiki.com/wiki/Warframe%E4%B8%AD%E6%96%87%E7%BB%B4%E5%9F%BA:403";*/ 28 | // 这简直就是官方吞mod最形象的解释 29 | } 30 | 31 | 32 | 33 | private const string wikilink = "https://warframe.huijiwiki.com/wiki/"; 34 | 35 | 36 | Task GetWiki(string word) 37 | { 38 | return WebHelper.DownloadJsonAsync( 39 | $"http://warframe.huijiwiki.com/api.php?action=query&format=json&formatversion=2&list=search&srsearch={word}"); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /WFBot/Features/Common/WMASearcher.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using GammaLibrary.Extensions; 7 | using WFBot.Features.ImageRendering; 8 | using WFBot.Features.Resource; 9 | using WFBot.Features.Utils; 10 | using WFBot.Orichalt; 11 | using WFBot.Utils; 12 | 13 | namespace WFBot.Features.Common 14 | { 15 | public class RivenAuctionOption 16 | { 17 | // TODO 18 | } 19 | class WMASearcher 20 | { 21 | 22 | 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /WFBot/Features/Events/ISender.cs: -------------------------------------------------------------------------------- 1 | using WFBot.Features.Utils; 2 | 3 | namespace WFBot.Events 4 | { 5 | public interface ISender 6 | { 7 | UserID Sender { get; } 8 | } 9 | } -------------------------------------------------------------------------------- /WFBot/Features/Events/MessageReceivedEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | using GammaLibrary.Extensions; 6 | using Humanizer; 7 | using WFBot.Events; 8 | using WFBot.Features.Commands; 9 | using WFBot.Features.Common; 10 | using WFBot.Features.Telemetry; 11 | using WFBot.Features.Utils; 12 | using WFBot.Orichalt; 13 | using WFBot.TextCommandCore; 14 | using WFBot.Utils; 15 | using static WFBot.Features.Utils.Messenger; 16 | 17 | namespace WFBot.Features.Events 18 | { 19 | /// 20 | /// 群消息接收事件 21 | /// 22 | public class MessageReceivedEvent 23 | { 24 | int commandCount; 25 | bool showedSlashTip = false; 26 | 27 | public Task ProcessGroupMessage(OrichaltContext o) 28 | { 29 | // 检查每分钟最大调用 30 | // if (CheckCallPerMin(groupId)) return Task.CompletedTask; 31 | 32 | // 处理以 '/' 开头的消息 33 | RunAutoReply(o); 34 | if (Config.Instance.IsSlashRequired && !o.PlainMessage.StartsWith('/')) 35 | { 36 | if (!showedSlashTip) 37 | { 38 | Trace.WriteLine("提示: 设置中要求命令必须以 / 开头. "); 39 | showedSlashTip = true; 40 | } 41 | return Task.FromResult(""); 42 | } 43 | var message = o.PlainMessage.TrimStart('/', '、', '/'); 44 | var useImageRendering = Config.Instance.EnableImageRendering; 45 | if (message.EndsWith("*") || message.StartsWith("*")) 46 | { 47 | message = message.Trim('*'); 48 | useImageRendering = !useImageRendering; 49 | } 50 | var handler = new CommandsHandler(o, message); 51 | 52 | // TODO 优化task数量 53 | // TODO cancellation token 54 | return Task.Run(async () => 55 | { 56 | var sw = Stopwatch.StartNew(); 57 | var cancelSource = new CancellationTokenSource(); 58 | AsyncContext.SetCancellationToken(cancelSource.Token); 59 | AsyncContext.SetOrichaltContext(o); 60 | AsyncContext.SetUseImageRendering(useImageRendering); 61 | var commandProcessTask = handler.ProcessCommandInput(); 62 | var platforminfo = o.GetInfo(); 63 | using var locker = WFBotResourceLock.Create($"命令处理 #{Interlocked.Increment(ref commandCount)} {platforminfo}"); 64 | await Task.WhenAny(commandProcessTask, Task.Delay(TimeSpan.FromSeconds(60))); 65 | 66 | if (!commandProcessTask.IsCompleted) 67 | { 68 | cancelSource.Cancel(); 69 | await Task.Delay(10.Seconds()); 70 | if (!commandProcessTask.IsCompleted) 71 | { 72 | MiguelNetwork.Reply(o, $"命令 [{message}] 处理超时."); 73 | } 74 | Trace.WriteLine($"命令 {platforminfo} 处理超时."); 75 | return "超时"; 76 | } 77 | 78 | var result = ""; 79 | if (handler.OutputStringBuilder.IsValueCreated) 80 | { 81 | var s = handler.OutputStringBuilder.Value.ToString().Trim(); 82 | result = s; 83 | MiguelNetwork.Reply(o, s); 84 | } 85 | 86 | if (!commandProcessTask.Result.result.IsNullOrWhiteSpace()) 87 | { 88 | result = commandProcessTask.Result.result; 89 | } 90 | 91 | if (commandProcessTask.Result.matched) 92 | { 93 | Interlocked.Increment(ref WFBotCore.InstanceCommandsProcessed); 94 | #if !DEBUG 95 | TelemetryClient.ReportCommand(new CommandReport(o.GetGroupIdentifier().AnonymizeString(),o.GetSenderIdentifier().AnonymizeString() ,o.PlainMessage, result, DateTime.Now, sw.Elapsed.TotalSeconds.ToString("F1")+"s", TelemetryClient.ClientID)); 96 | #endif 97 | Trace.WriteLine($"命令 {platforminfo} 处理完成: {sw.Elapsed.Seconds:N1}s."); 98 | } 99 | 100 | 101 | return result; 102 | }); 103 | } 104 | 105 | void RunAutoReply(OrichaltContext o) 106 | { 107 | var message = o.PlainMessage.ToLowerInvariant(); 108 | if (Config.Instance.CustomReplies.ContainsKey(message)) 109 | { 110 | MiguelNetwork.Reply(o, Config.Instance.CustomReplies[message]); 111 | } 112 | } 113 | 114 | } 115 | 116 | 117 | } 118 | -------------------------------------------------------------------------------- /WFBot/Features/ImageRendering/ImageRenderProfiler.cs: -------------------------------------------------------------------------------- 1 | //#define PROFILE 2 | using System.Diagnostics; 3 | 4 | namespace WFBot.Features.ImageRendering 5 | { 6 | public class ImageRenderProfiler : IDisposable 7 | { 8 | Stopwatch sw; 9 | Stopwatch swBase; 10 | 11 | public ImageRenderProfiler() 12 | { 13 | sw = Stopwatch.StartNew(); 14 | swBase = Stopwatch.StartNew(); 15 | } 16 | 17 | public void Segment(string s) 18 | { 19 | #if PROFILE 20 | 21 | Console.WriteLine($"Profiler: {s} {sw.Elapsed.TotalSeconds:F2}s"); 22 | sw.Restart(); 23 | #endif 24 | } 25 | 26 | public void Dispose() 27 | { 28 | #if PROFILE 29 | Console.WriteLine($"Profiler: 完成渲染 {swBase.Elapsed.TotalSeconds:F2}s"); 30 | #endif 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /WFBot/Features/ImageRendering/RichMessage.cs: -------------------------------------------------------------------------------- 1 | using WFBot.Orichalt.OrichaltConnectors; 2 | 3 | namespace WFBot.Features.ImageRendering 4 | { 5 | public class RichMessages : List 6 | { 7 | 8 | public static implicit operator RichMessages(string s) 9 | { 10 | return new RichMessages{ new TextMessage{Content = s} }; 11 | } 12 | } 13 | 14 | public abstract class RichMessage 15 | { 16 | } 17 | 18 | public class TextMessage : RichMessage 19 | { 20 | public string Content { get; set; } 21 | } 22 | 23 | public class ImageMessage : RichMessage 24 | { 25 | public byte[] Content { get; set; } 26 | } 27 | 28 | public class AtMessage : RichMessage 29 | { 30 | public bool IsAll { get; set; } 31 | public string UserID { get; set; } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /WFBot/Features/Resource/IWFResource.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace WFBot.Features.Resource 4 | { 5 | public interface IWFResource 6 | { 7 | Task Update(); 8 | Task Reload(bool isFirstTime); 9 | public string Category { get; } 10 | public bool IsGitHub { get; } 11 | 12 | } 13 | } -------------------------------------------------------------------------------- /WFBot/Features/Resource/SlangManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Newtonsoft.Json; 8 | using WFBot.Features.Utils; 9 | using WFBot.Utils; 10 | 11 | namespace WFBot.Features.Resource 12 | { 13 | public static class SlangManager 14 | { 15 | /*public static WFResource> SlangResource; 16 | public static List LocalSlang => SlangConfig.Instance.AllSlang; 17 | 18 | public static IEnumerable AllSlang => SlangResource.Value.Concat(LocalSlang); 19 | 20 | 21 | public static async Task UpdateOnline() 22 | { 23 | if (SlangResource == null) 24 | { 25 | SlangResource = WFResource>.Create( 26 | "http://github.cdn.therealkamisama.top/https://github.com/TRKS-Team/WFBotSlang/blob/main/slang.json", 27 | category: nameof(WFTranslator), 28 | resourceLoader: s => 29 | { 30 | try 31 | { 32 | using var sr = new StreamReader(s); 33 | var str = sr.ReadToEnd(); 34 | return Task.FromResult(JsonConvert.DeserializeObject>(str)); 35 | } 36 | catch (Exception e) 37 | { 38 | Console.WriteLine("黑话辞典加载出错."); 39 | Console.WriteLine(e); 40 | return Task.FromResult(new List()); 41 | } 42 | }); 43 | await SlangResource.WaitForInited(); 44 | return; 45 | } 46 | 47 | await SlangResource.Reload(); 48 | } 49 | 50 | 51 | } 52 | 53 | [Configuration("slang")] 54 | public class SlangConfig : Configuration 55 | { 56 | public List AllSlang { get; set; } = new List(); 57 | } 58 | 59 | public class SlangItem 60 | { 61 | public string Source { get; } 62 | public string[] Slang { get; } 63 | 64 | public SlangItem(string source, string[] slang) => 65 | (Source, Slang) = (source, slang); 66 | }*/ 67 | } 68 | } -------------------------------------------------------------------------------- /WFBot/Features/Resource/WFResourcesManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using GammaLibrary.Extensions; 7 | using WFBot.Features.Utils; 8 | using WFBot.Utils; 9 | 10 | namespace WFBot.Features.Resource 11 | { 12 | public static class WFResourcesManager 13 | { 14 | public static ConcurrentDictionary> WFResourceDic = new ConcurrentDictionary>(); 15 | public static List WFResourceGitHubInfos = new List(); 16 | public static void AddInfo(string name, string kraber, string category, bool iskraber) 17 | { 18 | WFResourceGitHubInfos.Add(new GitHubInfo(name, kraber, category, iskraber)); 19 | } 20 | } 21 | 22 | public class GitHubInfo 23 | { 24 | public GitHubInfo(string name, string kraber, string category, bool iskraber) 25 | { 26 | LastUpdated = DateTime.Now; 27 | Name = name; 28 | Category = category; 29 | Kraber = kraber; 30 | IsKraber = iskraber; 31 | SHA = WFResources.GetSHA(this); 32 | } 33 | 34 | public string Name { get; set; } 35 | public DateTime LastUpdated { get; set; } 36 | public string Category { get; set; } 37 | public string SHA { get; set; } 38 | public string Kraber { get; set; } 39 | public bool IsKraber { get; set; } 40 | } 41 | 42 | [Configuration("GitHubInfos")] 43 | public class GitHubInfos : Configuration 44 | { 45 | public List Infos = new List(); 46 | protected override void AfterUpdate() 47 | { 48 | if (Infos.Select(i => i.Name).Except(WFResourcesManager.WFResourceGitHubInfos.Select(i => i.Name)).Any() || Infos.All(i => i.Kraber.IsNullOrEmpty())) 49 | { 50 | Infos = WFResourcesManager.WFResourceGitHubInfos; 51 | Save(); 52 | } 53 | } 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /WFBot/Features/Telemetry/Memory.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace WFBot.Features.Telemetry 5 | { 6 | //https://gunnarpeipman.com/dotnet-core-system-memory/ 7 | public class MemoryMetrics 8 | { 9 | public double Total; 10 | public double Used; 11 | public double Free; 12 | } 13 | 14 | public class MemoryMetricsClient 15 | { 16 | public MemoryMetrics GetMetrics() 17 | { 18 | if (IsUnix()) 19 | { 20 | return GetUnixMetrics(); 21 | } 22 | 23 | return GetWindowsMetrics(); 24 | } 25 | 26 | private bool IsUnix() 27 | { 28 | var isUnix = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || 29 | RuntimeInformation.IsOSPlatform(OSPlatform.Linux); 30 | 31 | return isUnix; 32 | } 33 | 34 | private MemoryMetrics GetWindowsMetrics() 35 | { 36 | var output = ""; 37 | 38 | var info = new ProcessStartInfo(); 39 | info.FileName = "wmic"; 40 | info.Arguments = "OS get FreePhysicalMemory,TotalVisibleMemorySize /Value"; 41 | info.RedirectStandardOutput = true; 42 | 43 | using (var process = Process.Start(info)) 44 | { 45 | output = process.StandardOutput.ReadToEnd(); 46 | } 47 | 48 | var lines = output.Trim().Split("\n"); 49 | var freeMemoryParts = lines[0].Split("=", StringSplitOptions.RemoveEmptyEntries); 50 | var totalMemoryParts = lines[1].Split("=", StringSplitOptions.RemoveEmptyEntries); 51 | 52 | var metrics = new MemoryMetrics(); 53 | metrics.Total = Math.Round(double.Parse(totalMemoryParts[1]) / 1024, 0); 54 | metrics.Free = Math.Round(double.Parse(freeMemoryParts[1]) / 1024, 0); 55 | metrics.Used = metrics.Total - metrics.Free; 56 | 57 | return metrics; 58 | } 59 | 60 | private MemoryMetrics GetUnixMetrics() 61 | { 62 | var output = ""; 63 | 64 | var info = new ProcessStartInfo("free -m"); 65 | info.FileName = "/bin/sh"; 66 | info.Arguments = "-c \"free -m\""; 67 | info.RedirectStandardOutput = true; 68 | 69 | using (var process = Process.Start(info)) 70 | { 71 | output = process.StandardOutput.ReadToEnd(); 72 | } 73 | 74 | var lines = output.Split("\n"); 75 | var memory = lines[1].Split(" ", StringSplitOptions.RemoveEmptyEntries); 76 | 77 | var metrics = new MemoryMetrics(); 78 | metrics.Total = double.Parse(memory[1]); 79 | metrics.Used = double.Parse(memory[2]); 80 | metrics.Free = double.Parse(memory[3]); 81 | 82 | return metrics; 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /WFBot/Features/Timers/Base/WFBotTimer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Timers; 7 | using Timer = System.Timers.Timer; 8 | 9 | namespace WFBot.Features.Timers.Base 10 | { 11 | abstract class WFBotTimer 12 | { 13 | internal readonly Timer timer; 14 | public WFBotTimer(TimeSpan delay) 15 | { 16 | timer = new Timer(delay.TotalMilliseconds); 17 | timer.Elapsed += (sender, args) => Tick(); 18 | timer.Start(); 19 | } 20 | 21 | protected abstract void Tick(); 22 | } 23 | 24 | [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)] 25 | sealed class CalledByTimerAttribute : Attribute 26 | { 27 | public CalledByTimerAttribute(Type type) 28 | { 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /WFBot/Features/Timers/BotMarketHeartbeatTimer.cs: -------------------------------------------------------------------------------- 1 | using GammaLibrary.Extensions; 2 | using Humanizer; 3 | using WFBot.Features.Timers.Base; 4 | using WFBot.Orichalt; 5 | using WFBot.Utils; 6 | 7 | namespace WFBot.Features.Timers 8 | { 9 | class BotMarketHeartbeatTimer : WFBotTimer 10 | { 11 | public BotMarketHeartbeatTimer() : base(30.Minutes()) 12 | { 13 | 14 | } 15 | 16 | protected override void Tick() 17 | { 18 | if (Config.Instance.Miguel_Platform == MessagePlatform.Kook && !Config.Instance.BotMarketUUID.IsNullOrEmpty()) 19 | { 20 | WebHelper.DownloadStringAsync("http://bot.gekj.net/api/v1/online.bot", 21 | new List> 22 | { 23 | new("uuid", Config.Instance.BotMarketUUID) 24 | }).Wait(); 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /WFBot/Features/Timers/ImageRenderingPGOTimer.cs: -------------------------------------------------------------------------------- 1 | using Humanizer; 2 | using WFBot.Features.ImageRendering; 3 | using WFBot.Features.Timers.Base; 4 | 5 | namespace WFBot.Features.Timers 6 | { 7 | class ImageRenderingPGOTimer : WFBotTimer 8 | { 9 | public ImageRenderingPGOTimer() : base(60.Seconds()) 10 | { 11 | } 12 | 13 | protected override void Tick() 14 | { 15 | ImageRenderingPGO.Tick(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /WFBot/Features/Timers/NotificationTimer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Humanizer; 7 | using WFBot.Features.Timers.Base; 8 | 9 | namespace WFBot.Features.Timers 10 | { 11 | class NotificationTimer : WFBotTimer 12 | { 13 | public NotificationTimer() : base(1.Minutes()) 14 | { 15 | } 16 | 17 | protected override void Tick() 18 | { 19 | WFBotCore.Instance.NotificationHandler.Update(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /WFBot/Features/Timers/WFATimer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Text; 5 | using Humanizer; 6 | using WFBot.Features.Resource; 7 | using WFBot.Features.Timers.Base; 8 | 9 | namespace WFBot.Features.Timers 10 | { 11 | class WFATimer : WFBotTimer 12 | { 13 | public WFATimer() : base(3.Hours()) 14 | { 15 | } 16 | protected override void Tick() 17 | { 18 | /*try 19 | { 20 | WFResources.WFAApi.UpdateClient(); 21 | } 22 | catch (Exception e) 23 | { 24 | Trace.WriteLine(e); 25 | }*/ 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /WFBot/Features/Timers/WFResourcesTimer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using GammaLibrary.Extensions; 7 | using Humanizer; 8 | using Manganese.Array; 9 | using WFBot.Features.Resource; 10 | using WFBot.Features.Timers.Base; 11 | 12 | namespace WFBot.Features.Timers 13 | { 14 | class WFResourcesTimer : WFBotTimer 15 | { 16 | public WFResourcesTimer() : base(10.Minutes()) 17 | { 18 | } 19 | 20 | protected override void Tick() 21 | { 22 | var resources = WFResourcesManager.WFResourceDic.Values 23 | .SelectMany(v => v) 24 | .GroupBy(v => v.Category) 25 | .Select(v => v.First().IsGitHub ? v.Take(1) : v) 26 | .SelectMany(v => v); 27 | Task.WhenAll(resources.Select(r => r.Update())); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /WFBot/Features/Utils/ReleaseGetter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Text; 4 | using WFBot.Utils; 5 | 6 | namespace WFBot.Features.Utils 7 | { 8 | public static class ReleaseGetter 9 | { 10 | public static ReleaseData Get() 11 | { 12 | var wc = new HttpClient(); 13 | wc.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36"); 14 | if (!string.IsNullOrWhiteSpace(Config.Instance.GitHubOAuthKey)) 15 | { 16 | wc.DefaultRequestHeaders.Add("Authorization", $"Token {Config.Instance.GitHubOAuthKey}"); 17 | } 18 | return wc.GetStringAsync("https://api.github.com/repos/TRKS-Team/WFBot/releases/latest").Result.JsonDeserialize(); 19 | } 20 | } 21 | 22 | public class ReleaseData 23 | { 24 | public string url { get; set; } 25 | public string assets_url { get; set; } 26 | public string upload_url { get; set; } 27 | public string html_url { get; set; } 28 | public int id { get; set; } 29 | public string tag_name { get; set; } 30 | public string target_commitish { get; set; } 31 | public object name { get; set; } 32 | public bool draft { get; set; } 33 | public Author2 author { get; set; } 34 | public bool prerelease { get; set; } 35 | public DateTime created_at { get; set; } 36 | public DateTime published_at { get; set; } 37 | public Asset[] assets { get; set; } 38 | public string tarball_url { get; set; } 39 | public string zipball_url { get; set; } 40 | public object body { get; set; } 41 | } 42 | 43 | public class Author2 44 | { 45 | public string login { get; set; } 46 | public int id { get; set; } 47 | public string avatar_url { get; set; } 48 | public string gravatar_id { get; set; } 49 | public string url { get; set; } 50 | public string html_url { get; set; } 51 | public string followers_url { get; set; } 52 | public string following_url { get; set; } 53 | public string gists_url { get; set; } 54 | public string starred_url { get; set; } 55 | public string subscriptions_url { get; set; } 56 | public string organizations_url { get; set; } 57 | public string repos_url { get; set; } 58 | public string events_url { get; set; } 59 | public string received_events_url { get; set; } 60 | public string type { get; set; } 61 | public bool site_admin { get; set; } 62 | } 63 | 64 | public class Asset 65 | { 66 | public string url { get; set; } 67 | public int id { get; set; } 68 | public string name { get; set; } 69 | public string label { get; set; } 70 | public Uploader uploader { get; set; } 71 | public string content_type { get; set; } 72 | public string state { get; set; } 73 | public int size { get; set; } 74 | public int download_count { get; set; } 75 | public DateTime created_at { get; set; } 76 | public DateTime updated_at { get; set; } 77 | public string browser_download_url { get; set; } 78 | } 79 | 80 | public class Uploader 81 | { 82 | public string login { get; set; } 83 | public int id { get; set; } 84 | public string avatar_url { get; set; } 85 | public string gravatar_id { get; set; } 86 | public string url { get; set; } 87 | public string html_url { get; set; } 88 | public string followers_url { get; set; } 89 | public string following_url { get; set; } 90 | public string gists_url { get; set; } 91 | public string starred_url { get; set; } 92 | public string subscriptions_url { get; set; } 93 | public string organizations_url { get; set; } 94 | public string repos_url { get; set; } 95 | public string events_url { get; set; } 96 | public string received_events_url { get; set; } 97 | public string type { get; set; } 98 | public bool site_admin { get; set; } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /WFBot/Features/Utils/WFAApi.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.CompilerServices; 3 | using System.Timers; 4 | using GammaLibrary.Extensions; 5 | using WarframeAlertingPrime.SDK.Models.Core; 6 | using WarframeAlertingPrime.SDK.Models.Enums; 7 | using WFBot.Features.Timers; 8 | using WFBot.Features.Timers.Base; 9 | using WFBot.TextCommandCore; 10 | using WFBot.Windows; 11 | 12 | namespace WFBot.Features.Utils 13 | { 14 | public class WFAApi 15 | { 16 | public bool isWFA => !Config.Instance.ClientId.IsNullOrWhiteSpace() && 17 | !Config.Instance.ClientSecret.IsNullOrWhiteSpace(); 18 | 19 | readonly object wfaClientLock = new object(); 20 | public Client WfaClient 21 | { 22 | get 23 | { 24 | lock (wfaClientLock) 25 | { 26 | if (wfaClient == null) 27 | throw new CommandException("WFAClient 没有被初始化成功."); 28 | 29 | return wfaClient; 30 | } 31 | } 32 | // ReSharper disable once InconsistentlySynchronizedField 33 | // I know what i'm doing 34 | private set => wfaClient = value; 35 | } 36 | 37 | Client wfaClient; 38 | 39 | public WFAApi() 40 | { 41 | // UpdateAccessToken(); 42 | UpdateClient(); 43 | } 44 | 45 | [CalledByTimer(typeof(WFATimer))] 46 | public void UpdateClient() 47 | { 48 | lock (wfaClientLock) 49 | { 50 | PlatformType wfaPlatform; 51 | switch (Config.Instance.Platform) 52 | { 53 | case Platform.PC: 54 | wfaPlatform = PlatformType.PC; 55 | break; 56 | case Platform.NS: 57 | wfaPlatform = PlatformType.Switch; 58 | break; 59 | case Platform.PS4: 60 | wfaPlatform = PlatformType.PS4; 61 | break; 62 | case Platform.XBOX: 63 | wfaPlatform = PlatformType.Xbox; 64 | break; 65 | default: 66 | wfaPlatform = PlatformType.PC; 67 | break; 68 | } 69 | 70 | if (isWFA) // 今后所有用到client的地方都要判断一次 71 | { 72 | if (DateTime.Now - Config.Instance.Last_update > TimeSpan.FromDays(7) || Config.Instance.AcessToken.IsNullOrEmpty()) 73 | { 74 | ReNew(); 75 | } 76 | else 77 | { 78 | WfaClient = new Client(Config.Instance.AcessToken, wfaPlatform); 79 | if (WfaClient.InitAsync().Result != InitResultType.Success) ReNew(); 80 | } 81 | 82 | } 83 | 84 | void ReNew() 85 | { 86 | WfaClient = new Client(Config.Instance.ClientId, Config.Instance.ClientSecret, new[] 87 | { 88 | "wfa.basic", "wfa.riven.query", "wfa.user.read", "wfa.lib.query" 89 | 90 | }, wfaPlatform); 91 | var initResult = WfaClient.InitAsync().Result; 92 | if (initResult != InitResultType.Success) 93 | { 94 | WfaClient = null; 95 | throw new Exception($"在初始化 WFAClient 时出现了问题. 返回的类型为 {initResult}"); 96 | } 97 | Config.Instance.Last_update = DateTime.Now; 98 | Config.Instance.AcessToken = WfaClient.Token; 99 | Config.Save(); 100 | } 101 | } 102 | 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /WFBot/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /WFBot/FodyWeavers.xsd: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. 16 | 17 | 18 | 19 | 20 | A comma-separated list of error codes that can be safely ignored in assembly verification. 21 | 22 | 23 | 24 | 25 | 'false' to turn off automatic generation of the XML Schema file. 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /WFBot/GroupInfo.cs: -------------------------------------------------------------------------------- 1 | namespace WFBot.Events 2 | { 3 | public class GroupInfo 4 | { 5 | public string Name { get; } 6 | public string ID { get; } 7 | 8 | public GroupInfo(string name, string id) 9 | { 10 | Name = name; 11 | ID = id; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /WFBot/MahuaEvents/GroupJoiningInvitationReceivedMahuaEvent1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using GammaLibrary.Extensions; 5 | using WFBot.Features.Utils; 6 | using WebSocket = WebSocketSharp.WebSocket; 7 | 8 | namespace WFBot.MahuaEvents 9 | { 10 | /// 11 | /// 入群邀请接收事件 12 | /// 13 | public class GroupJoiningInvitationReceivedMahuaEvent1 14 | { 15 | /* 16 | public void ProcessJoinGroupRequest() 17 | { 18 | void Accept() 19 | { 20 | 21 | } 22 | 23 | void Reject() 24 | { 25 | 26 | 27 | } 28 | //if (HotUpdateInfo.PreviousVersion) return; 29 | 30 | if (Config.Instance.IsPublicBot) 31 | { 32 | WebSocket ws = null; 33 | ws = new WebSocket("ws://127.0.0.1:15790/CheckGroup", default(CancellationToken), 102392, null, null, 34 | s => 35 | { 36 | var result = Boolean.Parse(s.Data.ReadToEnd()); 37 | if (result) 38 | { 39 | Accept(); 40 | } 41 | else 42 | { 43 | Reject(); 44 | } 45 | ws.Dispose(); 46 | return Task.CompletedTask; 47 | }); 48 | ws.Connect().Wait(); 49 | //ws.Send(context.ToGroup).Wait(); 50 | } 51 | 52 | 53 | Task.Delay(TimeSpan.FromSeconds(10)).ContinueWith(a => 54 | { 55 | if (Config.Instance.AcceptInvitation) 56 | { 57 | Accept(); 58 | if (!Config.Instance.WFGroupList.Contains(context.ToGroup)) 59 | { 60 | Config.Instance.WFGroupList.Add(context.ToGroup); 61 | } 62 | Messenger.SendDebugInfo($"接受了来自{context.FromQq}邀请加入群{context.ToGroup}的邀请."); 63 | Messenger.SendHelpdoc(context.ToGroup.ToGroupNumber()); 64 | } 65 | else 66 | { 67 | Reject(); 68 | } 69 | }); 70 | 71 | } 72 | */ 73 | } 74 | } -------------------------------------------------------------------------------- /WFBot/MahuaEvents/GroupJoiningRequestReceivedMahuaEvent1.cs: -------------------------------------------------------------------------------- 1 | using WFBot.Features.Utils; 2 | 3 | namespace WFBot.MahuaEvents 4 | { 5 | /// 6 | /// 入群申请接收事件 7 | /// 8 | public class GroupJoiningRequestReceivedMahuaEvent1 9 | { 10 | 11 | /* 12 | public void ProcessJoinGroupRequest() 13 | { 14 | if (Config.Instance.AcceptJoiningRequest) 15 | { 16 | _mahuaApi.AcceptGroupJoiningRequest(context.GroupJoiningRequestId, context.ToGroup, context.FromQq); 17 | Messenger.SendDebugInfo($"{context.FromQq}加入了群{context.ToGroup}."); 18 | } 19 | } 20 | */ 21 | } 22 | } -------------------------------------------------------------------------------- /WFBot/Orichalt/KookVerifyServer.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.SignalR.Client; 2 | using KookConfig = WFBot.Orichalt.OrichaltConnectors.KookConfig; 3 | 4 | namespace WFBot.Orichalt 5 | { 6 | public class KookVerifyServer 7 | { 8 | private HubConnection _connection = 9 | new HubConnectionBuilder() 10 | .WithUrl(KookConfig.Instance.VerifyServerUrl) 11 | .Build(); 12 | 13 | private bool connected; 14 | public void Init() 15 | { 16 | try 17 | { 18 | _connection.StartAsync(); 19 | connected = false; 20 | } 21 | catch (Exception e) 22 | { 23 | 24 | } 25 | _connection.Closed += async (error) => 26 | { 27 | connected = false; 28 | while (true) 29 | { 30 | await Task.Delay(new Random().Next(0, 5) * 1000); 31 | try 32 | { 33 | await _connection.StartAsync(); 34 | connected = true; 35 | break; 36 | } 37 | catch (Exception e) 38 | { 39 | MiguelNetwork.SendDebugInfo($"Kook验证服务器连接出错: {e}"); 40 | } 41 | } 42 | }; 43 | } 44 | 45 | private ulong GetGuildID(OrichaltContext o) 46 | { 47 | var kookContext = MiguelNetwork.OrichaltContextManager.GetKookContext(o); 48 | return kookContext.Guild.Id; 49 | } 50 | public async Task RedeemCode(OrichaltContext o, string code) 51 | { 52 | return await _connection.InvokeAsync("RedeemCode", GetGuildID(o), code); 53 | } 54 | 55 | public async Task VerifyGuild(OrichaltContext o) 56 | { 57 | return await _connection.InvokeAsync("VerifyGuild", GetGuildID(o)); 58 | } 59 | 60 | public async Task GetGuildValidationTime(OrichaltContext o) 61 | { 62 | return await _connection.InvokeAsync("GetGuildValidationTime", GetGuildID(o)); 63 | } 64 | public async Task StartGuildTrial(OrichaltContext o) 65 | { 66 | return await _connection.InvokeAsync("StartGuildTrial", GetGuildID(o)); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /WFBot/Orichalt/OrichaltConnectors/BasicConnector.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace WFBot.Orichalt.OrichaltConnectors 4 | { 5 | public class TestContext : PlatformContextBase 6 | { 7 | public string RawMessage { get; set; } 8 | } 9 | public class PlatformContextBase 10 | { 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /WFBot/Orichalt/OrichaltConnectors/QQChannelConnector.cs: -------------------------------------------------------------------------------- 1 | namespace WFBot.Orichalt.OrichaltConnectors 2 | { 3 | public class QQChannelContext 4 | { 5 | 6 | } 7 | 8 | public class QQChannelCore 9 | { 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /WFBot/Orichalt/OrichaltContextExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace WFBot.Orichalt 6 | { 7 | public static class OrichaltContextExtension 8 | { 9 | public static string GetInfo(this OrichaltContext o) 10 | { 11 | switch (o.Platform) 12 | { 13 | case MessagePlatform.OneBot: 14 | var onebotcontext = MiguelNetwork.OrichaltContextManager.GetOneBotContext(o); 15 | return 16 | $"平台[OneBot] 群[{onebotcontext.Group}] 用户[{onebotcontext.SenderID}] 内容[{onebotcontext.RawMessage}]"; 17 | case MessagePlatform.Kook: 18 | var kookcontext = MiguelNetwork.OrichaltContextManager.GetKookContext(o); 19 | return 20 | $"平台[Kook] 服务器[{kookcontext.Guild.Name}({kookcontext.Guild.Id})] 用户[{kookcontext.Author.Username}#{kookcontext.Author.IdentifyNumber}] 内容[{kookcontext.CleanContent}]"; 21 | case MessagePlatform.QQChannel: 22 | throw new NotImplementedException(); 23 | case MessagePlatform.MiraiHTTP: 24 | var miraihttpcontext = MiguelNetwork.OrichaltContextManager.GetMiraiHTTPContext(o); 25 | return 26 | $"平台[MiraiHTTP] 群[{miraihttpcontext.Group}] 用户[{miraihttpcontext.SenderID}] 内容[{miraihttpcontext.RawMessage}]"; 27 | case MessagePlatform.MiraiHTTPV1: 28 | var miraihttpcontext1 = MiguelNetwork.OrichaltContextManager.GetMiraiHTTPV1Context(o); 29 | return 30 | $"平台[MiraiHTTPV1] 群[{miraihttpcontext1.Group}] 用户[{miraihttpcontext1.SenderID}] 内容[{miraihttpcontext1.RawMessage}]"; 31 | } 32 | 33 | return ""; 34 | } 35 | public static string GetGroupIdentifier(this OrichaltContext o) 36 | { 37 | switch (o.Platform) 38 | { 39 | case MessagePlatform.OneBot: 40 | var onebotcontext = MiguelNetwork.OrichaltContextManager.GetOneBotContext(o); 41 | return $"QQ:{onebotcontext.Group}"; 42 | case MessagePlatform.Kook: 43 | var kookcontext = MiguelNetwork.OrichaltContextManager.GetKookContext(o); 44 | return $"频道ID:{kookcontext.Channel.Id}"; 45 | case MessagePlatform.QQChannel: 46 | throw new NotImplementedException(); 47 | case MessagePlatform.MiraiHTTP: 48 | var miraihttpcontext = MiguelNetwork.OrichaltContextManager.GetMiraiHTTPContext(o); 49 | return $"QQ:{miraihttpcontext.Group}"; 50 | 51 | case MessagePlatform.MiraiHTTPV1: 52 | var miraihttpcontext1 = MiguelNetwork.OrichaltContextManager.GetMiraiHTTPV1Context(o); 53 | return $"QQ:{miraihttpcontext1.Group}"; 54 | } 55 | 56 | return ""; 57 | } 58 | public static string GetSenderIdentifier(this OrichaltContext o) 59 | { 60 | switch (o.Platform) 61 | { 62 | case MessagePlatform.OneBot: 63 | var onebotcontext = MiguelNetwork.OrichaltContextManager.GetOneBotContext(o); 64 | return $"QQ:{onebotcontext.SenderID}"; 65 | case MessagePlatform.Kook: 66 | var kookContext = MiguelNetwork.OrichaltContextManager.GetKookContext(o); 67 | return $"用户:{kookContext.Author}"; 68 | case MessagePlatform.QQChannel: 69 | throw new NotImplementedException(); 70 | case MessagePlatform.MiraiHTTP: 71 | var miraihttpcontext = MiguelNetwork.OrichaltContextManager.GetMiraiHTTPContext(o); 72 | return $"QQ:{miraihttpcontext.SenderID}"; 73 | 74 | case MessagePlatform.MiraiHTTPV1: 75 | var miraihttpcontext1 = MiguelNetwork.OrichaltContextManager.GetMiraiHTTPV1Context(o); 76 | return $"QQ:{miraihttpcontext1.SenderID}"; 77 | } 78 | 79 | return ""; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /WFBot/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // 有关程序集的一般信息由以下 5 | // 控制。更改这些特性值可修改 6 | // 与程序集关联的信息。 7 | [assembly: AssemblyTitle("WFBot")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("WFBot")] 12 | [assembly: AssemblyCopyright("Copyright © TRKS-Team 2021")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // 将 ComVisible 设置为 false 会使此程序集中的类型 17 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 18 | //请将此类型的 ComVisible 特性设置为 true。 19 | [assembly: ComVisible(false)] 20 | 21 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 22 | [assembly: Guid("795fa006-a765-48d7-a488-efd37d7ca474")] 23 | 24 | // 程序集的版本信息由下列四个值组成: 25 | // 26 | // 主版本 27 | // 次版本 28 | // 生成号 29 | // 修订号 30 | // 31 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 32 | //通过使用 "*",如下所示: 33 | [assembly: AssemblyVersion("1.0.0.0")] 34 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /WFBot/Properties/PublishProfiles/FolderProfile.pubxml: -------------------------------------------------------------------------------- 1 |  2 | 5 | 6 | 7 | Release 8 | Any CPU 9 | bin\Release\net6.0\publish\ 10 | FileSystem 11 | 12 | -------------------------------------------------------------------------------- /WFBot/Properties/PublishProfiles/FolderProfile1.pubxml: -------------------------------------------------------------------------------- 1 |  2 | 5 | 6 | 7 | true 8 | false 9 | true 10 | Release 11 | Any CPU 12 | FileSystem 13 | bin\Release\net6.0\publish\ 14 | FileSystem 15 | <_TargetId>Folder 16 | 17 | net6.0 18 | 795fa006-a765-48d7-a488-efd37d7ca474 19 | false 20 | win-x64 21 | true 22 | 23 | -------------------------------------------------------------------------------- /WFBot/Resources/Factions/corpus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/Factions/corpus.png -------------------------------------------------------------------------------- /WFBot/Resources/Factions/corrupted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/Factions/corrupted.png -------------------------------------------------------------------------------- /WFBot/Resources/Factions/crossfire.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/Factions/crossfire.png -------------------------------------------------------------------------------- /WFBot/Resources/Factions/grineer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/Factions/grineer.png -------------------------------------------------------------------------------- /WFBot/Resources/Factions/infested.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/Factions/infested.png -------------------------------------------------------------------------------- /WFBot/Resources/Factions/orokin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/Factions/orokin.png -------------------------------------------------------------------------------- /WFBot/Resources/Factions/sentient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/Factions/sentient.png -------------------------------------------------------------------------------- /WFBot/Resources/Fissures/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/Fissures/1.png -------------------------------------------------------------------------------- /WFBot/Resources/Fissures/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/Fissures/2.png -------------------------------------------------------------------------------- /WFBot/Resources/Fissures/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/Fissures/3.png -------------------------------------------------------------------------------- /WFBot/Resources/Fissures/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/Fissures/4.png -------------------------------------------------------------------------------- /WFBot/Resources/Fissures/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/Fissures/5.png -------------------------------------------------------------------------------- /WFBot/Resources/InvasionRewards/FORMA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/InvasionRewards/FORMA.png -------------------------------------------------------------------------------- /WFBot/Resources/InvasionRewards/OROKIN催化剂.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/InvasionRewards/OROKIN催化剂.png -------------------------------------------------------------------------------- /WFBot/Resources/InvasionRewards/OROKIN反应堆.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/InvasionRewards/OROKIN反应堆.png -------------------------------------------------------------------------------- /WFBot/Resources/InvasionRewards/卡拉克 亡魂.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/InvasionRewards/卡拉克 亡魂.png -------------------------------------------------------------------------------- /WFBot/Resources/InvasionRewards/双子蝰蛇 亡魂.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/InvasionRewards/双子蝰蛇 亡魂.png -------------------------------------------------------------------------------- /WFBot/Resources/InvasionRewards/希芙.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/InvasionRewards/希芙.png -------------------------------------------------------------------------------- /WFBot/Resources/InvasionRewards/异融ALAD V导航座标.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/InvasionRewards/异融ALAD V导航座标.png -------------------------------------------------------------------------------- /WFBot/Resources/InvasionRewards/德拉 破坏者.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/InvasionRewards/德拉 破坏者.png -------------------------------------------------------------------------------- /WFBot/Resources/InvasionRewards/拉特昂 亡魂.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/InvasionRewards/拉特昂 亡魂.png -------------------------------------------------------------------------------- /WFBot/Resources/InvasionRewards/斯特朗 亡魂.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/InvasionRewards/斯特朗 亡魂.png -------------------------------------------------------------------------------- /WFBot/Resources/InvasionRewards/爆燃喷射器.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/InvasionRewards/爆燃喷射器.png -------------------------------------------------------------------------------- /WFBot/Resources/InvasionRewards/特殊功能槽连接器.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/InvasionRewards/特殊功能槽连接器.png -------------------------------------------------------------------------------- /WFBot/Resources/InvasionRewards/狙击特昂 破坏者.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/InvasionRewards/狙击特昂 破坏者.png -------------------------------------------------------------------------------- /WFBot/Resources/InvasionRewards/电磁力场装置.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/InvasionRewards/电磁力场装置.png -------------------------------------------------------------------------------- /WFBot/Resources/InvasionRewards/突变原聚合物.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/InvasionRewards/突变原聚合物.png -------------------------------------------------------------------------------- /WFBot/Resources/WarframeMarket/Cubes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/WarframeMarket/Cubes.png -------------------------------------------------------------------------------- /WFBot/Resources/WarframeMarket/PlatinumLarge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/WarframeMarket/PlatinumLarge.png -------------------------------------------------------------------------------- /WFBot/Resources/WarframeMarket/PlatinumSimple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/WarframeMarket/PlatinumSimple.png -------------------------------------------------------------------------------- /WFBot/Resources/Weathers/cold.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/Weathers/cold.png -------------------------------------------------------------------------------- /WFBot/Resources/Weathers/night.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/Weathers/night.png -------------------------------------------------------------------------------- /WFBot/Resources/Weathers/sun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/Weathers/sun.png -------------------------------------------------------------------------------- /WFBot/Resources/Weathers/warm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/Weathers/warm.png -------------------------------------------------------------------------------- /WFBot/Resources/network-unstable.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/Resources/network-unstable.gif -------------------------------------------------------------------------------- /WFBot/TextCommandCore/CommandException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace WFBot.TextCommandCore 4 | { 5 | public class CommandException : Exception 6 | { 7 | public CommandException(string message) : base(message) 8 | { 9 | } 10 | } 11 | 12 | public class CommandMismatchException : Exception 13 | { 14 | public CommandMismatchException() 15 | { 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /WFBot/TextCommandCore/ICommandHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using WFBot.Features.ImageRendering; 6 | using WFBot.Orichalt; 7 | 8 | namespace WFBot.TextCommandCore 9 | { 10 | public interface ICommandHandler where T : ICommandHandler 11 | { 12 | Action ErrorMessageSender { get; } 13 | Action MessageSender { get; } 14 | Action RichMessageSender { get; } 15 | string Message { get; } 16 | OrichaltContext O { get; } 17 | } 18 | 19 | public abstract class CommandHandlerBase : ICommandHandler where T : ICommandHandler 20 | { 21 | public abstract Action MessageSender { get; } 22 | public abstract Action RichMessageSender { get; } 23 | public abstract Action ErrorMessageSender { get; } 24 | public abstract string Message { get; } 25 | public abstract OrichaltContext O { get; } 26 | 27 | public virtual void OnProcessingMessage() { } 28 | 29 | public virtual void OnProcessedMessage() { } 30 | } 31 | 32 | public class CommandInfo 33 | { 34 | public List> Matchers { get; } 35 | public MethodInfo Method { get; } 36 | 37 | public CommandInfo(MethodInfo method) 38 | { 39 | Matchers = method.GetCustomAttributes().Select(attrib => attrib.Matcher).ToList(); 40 | Method = method; 41 | } 42 | } 43 | 44 | [AttributeUsage(AttributeTargets.Method)] 45 | public sealed class MatchersAttribute : MatcherAttribute 46 | { 47 | public string[] Matchers { get; } 48 | 49 | public MatchersAttribute(params string[] matchers) : base(msg => matchers.Any(match => match == msg)) 50 | { 51 | Matchers = matchers; 52 | } 53 | } 54 | 55 | [AttributeUsage(AttributeTargets.Method)] 56 | public sealed class MatchersIgnoreCaseAttribute : MatcherAttribute 57 | { 58 | public string[] Matchers { get; } 59 | 60 | public MatchersIgnoreCaseAttribute(params string[] matchers) : base(msg => matchers.Any(match => match.Equals(msg, StringComparison.OrdinalIgnoreCase))) 61 | { 62 | Matchers = matchers; 63 | } 64 | } 65 | 66 | [AttributeUsage(AttributeTargets.Method)] 67 | public class MatcherAttribute : Attribute 68 | { 69 | public Predicate Matcher { get; } 70 | 71 | public MatcherAttribute(Predicate matcher) 72 | { 73 | Matcher = matcher; 74 | } 75 | } 76 | 77 | [AttributeUsage(AttributeTargets.Method)] 78 | public sealed class CombineParamsAttribute : Attribute 79 | { 80 | } 81 | 82 | [AttributeUsage(AttributeTargets.Method)] 83 | public sealed class CombineStartAttribute : Attribute 84 | { 85 | } 86 | 87 | [AttributeUsage(AttributeTargets.Method)] 88 | public sealed class CombineEndAttribute : Attribute 89 | { 90 | } 91 | 92 | [AttributeUsage(AttributeTargets.Method)] 93 | public sealed class DoNotMeasureTimeAttribute : Attribute 94 | { 95 | } 96 | //TODO Timer' 请求比预计时间长 97 | 98 | [AttributeUsage(AttributeTargets.Method)] 99 | public class SkipValidationCheckAttribute : Attribute 100 | { 101 | } 102 | 103 | [AttributeUsage(AttributeTargets.Method)] 104 | public class SkipBotChannelCheckAttribute : Attribute 105 | { 106 | 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /WFBot/TextCommandCore/Objects.cs: -------------------------------------------------------------------------------- 1 | namespace WFBot.TextCommandCore 2 | { 3 | public class TargetID 4 | { 5 | public string ID { get; } 6 | 7 | public TargetID(string id) 8 | { 9 | ID = id; 10 | } 11 | 12 | public static implicit operator TargetID(string id) 13 | { 14 | return new TargetID(id); 15 | } 16 | 17 | public static implicit operator string(TargetID id) 18 | { 19 | return id.ID; 20 | } 21 | } 22 | 23 | public class Message 24 | { 25 | public string Content { get; } 26 | 27 | public Message(string content) 28 | { 29 | Content = content; 30 | } 31 | 32 | public static implicit operator Message(string msg) 33 | { 34 | return new Message(msg); 35 | } 36 | 37 | public static implicit operator string(Message msg) 38 | { 39 | return msg.Content; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /WFBot/TextCommandCore/Processors.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | 3 | namespace WFBot.TextCommandCore 4 | { 5 | public interface IPreProcessor 6 | { 7 | string Process(MethodInfo method, string msg, ICommandHandler handlers) where T : ICommandHandler; 8 | } 9 | 10 | public interface IPostProcessor 11 | { 12 | string Process(MethodInfo method, string msg, string result, ICommandHandler handlers) where T : ICommandHandler; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /WFBot/Utils/AsyncContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using WFBot.Orichalt; 4 | 5 | namespace WFBot.Utils 6 | { 7 | public static class AsyncContext 8 | { 9 | internal static readonly AsyncLocal> CurrentCancellationToken = 10 | new AsyncLocal>(); 11 | internal static readonly AsyncLocal> CurrentOrichaltContext = 12 | new AsyncLocal>(); 13 | internal static readonly AsyncLocal> UseImageRendering = 14 | new (); 15 | internal static readonly AsyncLocal> CommandIdentifier = 16 | new(); 17 | public static void SetOrichaltContext(OrichaltContext context) 18 | { 19 | CurrentOrichaltContext.Value = new Container(context); 20 | } 21 | 22 | public static OrichaltContext GetOrichaltContext() 23 | { 24 | return CurrentOrichaltContext.Value?.Value ?? throw new Exception("Message Sender not found."); 25 | } 26 | 27 | public static void SetCancellationToken(CancellationToken token) 28 | { 29 | CurrentCancellationToken.Value = new Container(token); 30 | } 31 | 32 | public static CancellationToken GetCancellationToken() 33 | { 34 | return CurrentCancellationToken.Value?.Value ?? CancellationToken.None; 35 | } 36 | 37 | public static void SetUseImageRendering(bool v) 38 | { 39 | UseImageRendering.Value = new Container(v); 40 | } 41 | public static bool GetUseImageRendering() 42 | { 43 | return UseImageRendering.Value?.Value ?? false; 44 | } 45 | public static void SetCommandIdentifier(string v) 46 | { 47 | CommandIdentifier.Value = new Container(v); 48 | } 49 | public static string GetCommandIdentifier() 50 | { 51 | return CommandIdentifier.Value?.Value ?? ""; 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /WFBot/Utils/EnumerableExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace WFBot.Utils 7 | { 8 | public static class EnumerableExtensions 9 | { 10 | public static IEnumerable Permutate(this IEnumerable source) 11 | { 12 | return permutate(source, Enumerable.Empty()); 13 | IEnumerable permutate(IEnumerable reminder, IEnumerable prefix) => 14 | !reminder.Any() ? new[] { prefix.ToArray() } : 15 | reminder.SelectMany((c, i) => permutate( 16 | reminder.Take(i).Concat(reminder.Skip(i+1)).ToArray(), 17 | prefix.Append(c))); 18 | } 19 | public static IEnumerable> DifferentCombinations(this IEnumerable elements, int k) 20 | { 21 | var enumerable = elements.ToList(); 22 | return k == 0 ? new[] { Array.Empty() } : 23 | enumerable.SelectMany((e, i) => 24 | enumerable.Skip(i + 1).DifferentCombinations(k - 1).Select(c => (new[] {e}).Concat(c))); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /WFBot/Utils/GroupMessageSender.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using WFBot.Features.Utils; 5 | 6 | namespace WFBot.Utils 7 | { 8 | /*public class GroupMessageSender : IGroupMessageSender 9 | { 10 | public GroupID GroupID { get; } 11 | 12 | public GroupMessageSender(GroupID groupID) 13 | { 14 | this.GroupID = groupID; 15 | } 16 | 17 | public void SendMessage(string msg) 18 | { 19 | msg.SendToGroup(GroupID); 20 | } 21 | } 22 | 23 | public interface IGroupMessageSender 24 | { 25 | GroupID GroupID { get; } 26 | void SendMessage(string msg); 27 | }*/ 28 | } 29 | -------------------------------------------------------------------------------- /WFBot/Utils/LZMADecompress.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | 6 | namespace WFBot.Utils 7 | { 8 | public class LZMADecompress 9 | { 10 | public static void DecompressFileLZMA(string inFile, string outFile) 11 | { 12 | SevenZip.Compression.LZMA.Decoder coder = new SevenZip.Compression.LZMA.Decoder(); 13 | FileStream input = new FileStream(inFile, FileMode.Open); 14 | FileStream output = new FileStream(outFile, FileMode.Create); 15 | 16 | // Read the decoder properties 17 | byte[] properties = new byte[5]; 18 | input.Read(properties, 0, 5); 19 | 20 | // Read in the decompress file size. 21 | byte[] fileLengthBytes = new byte[8]; 22 | input.Read(fileLengthBytes, 0, 8); 23 | long fileLength = BitConverter.ToInt64(fileLengthBytes, 0); 24 | 25 | coder.SetDecoderProperties(properties); 26 | coder.Code(input, output, input.Length, fileLength, null); 27 | output.Flush(); 28 | output.Close(); 29 | input.Flush(); 30 | input.Close(); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /WFBot/Utils/Plugins.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO; 4 | using System.Reflection; 5 | using HarmonyLib; 6 | using WFBot.MahuaEvents; 7 | 8 | namespace WFBot.Utils 9 | { 10 | public class Plugins 11 | { 12 | public static void Load() 13 | { 14 | var harmony = new Harmony($"wfbot"); 15 | Directory.CreateDirectory("WFBotPlugins"); 16 | foreach (var file in Directory.GetFiles("WFBotPlugins", "*.dll")) 17 | { 18 | try 19 | { 20 | harmony.PatchAll(Assembly.LoadFile(Path.GetFullPath(file))); 21 | } 22 | catch (Exception e) 23 | { 24 | Trace.WriteLine(e); 25 | } 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /WFBot/Utils/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace WFBot.Utils 7 | { 8 | public static class StringExtensions 9 | { 10 | public static string FirstCharToUpper(this string input) 11 | { 12 | switch (input) 13 | { 14 | case null: throw new ArgumentNullException(nameof(input)); 15 | case "": throw new ArgumentException($"{nameof(input)} cannot be empty", nameof(input)); 16 | default: return input.First().ToString().ToUpper() + input.Substring(1); 17 | } 18 | } 19 | public static bool IsNumber(this string source) 20 | { 21 | return int.TryParse(source, out _); 22 | } 23 | 24 | public static string ToBase64(this string source) 25 | { 26 | var bytes = Encoding.UTF8.GetBytes(source); 27 | return Convert.ToBase64String(bytes); 28 | } 29 | 30 | public static string Format(this string source) 31 | { 32 | return source.Replace(" ", "").ToLower().Trim(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /WFBot/Utils/WFBotResourceLock.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Collections.Generic; 4 | using System.Collections.Immutable; 5 | using System.Linq; 6 | using System.Text; 7 | 8 | namespace WFBot.Utils 9 | { 10 | public class WFBotResourceLock : IDisposable 11 | { 12 | static readonly HashSet Locks = new HashSet(); 13 | public static ImmutableArray AllLocks => Locks.ToImmutableArray(); 14 | public static bool AnyLockAcquired => Locks.Any(); 15 | 16 | public bool Locked { get; private set; } 17 | public string Name { get; } 18 | public ResourceLockTypes LockType { get; } 19 | public WFBotResourceLock(string name, ResourceLockTypes type = ResourceLockTypes.Whatever) 20 | { 21 | if (WFBotCore.IsShuttingDown) 22 | throw new InvalidOperationException( 23 | "You cannot acquire a resource lock while the app is shutting down."); 24 | Name = name; 25 | LockType = type; 26 | 27 | lock (Locks) 28 | { 29 | Locked = true; 30 | Locks.Add(this); 31 | } 32 | } 33 | 34 | public static WFBotResourceLock Create(string name, ResourceLockTypes type = ResourceLockTypes.Whatever) 35 | { 36 | return new WFBotResourceLock(name, type); 37 | } 38 | 39 | public void Dispose() 40 | { 41 | lock (Locks) 42 | { 43 | Locked = false; 44 | if (Locks.Contains(this)) 45 | { 46 | Locks.Remove(this); 47 | } 48 | 49 | if (WFBotCore.IsShuttingDown) 50 | { 51 | Console.WriteLine($"资源 {Name} 已经释放."); 52 | } 53 | } 54 | 55 | } 56 | 57 | public override string ToString() 58 | { 59 | return LockType == ResourceLockTypes.Essential ? $"*{Name}" : Name; 60 | } 61 | } 62 | 63 | public enum ResourceLockTypes 64 | { 65 | Essential, 66 | Whatever 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /WFBot/WFBot.csproj.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | No -------------------------------------------------------------------------------- /WFBot/WebSocketHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using System.Threading.Tasks; 3 | using GammaLibrary.Extensions; 4 | using WebSocketSharp; 5 | using WebSocketSharp.Server; 6 | using WFBot.Features.Utils; 7 | 8 | namespace WFBot 9 | { 10 | public class WebSocketHandler 11 | { 12 | private WebSocketServer webserver = new WebSocketServer(IPAddress.Loopback, 15789); 13 | public WebSocketHandler() 14 | { 15 | Task.Factory.StartNew(() => { 16 | //webserver.AddWebSocketService("/GetGroup"); 17 | webserver.AddWebSocketService("/AddGroup"); 18 | webserver.Start(); 19 | }, TaskCreationOptions.LongRunning); 20 | } 21 | } 22 | // tOdO 我觉得你得重写这一块 23 | // mAybE 以后可能用不到这一块 24 | /* 25 | public class GetGroup : WebSocketBehavior 26 | { 27 | protected override async Task OnMessage(MessageEventArgs e) 28 | { 29 | string result; 30 | using (var robotSession = MahuaRobotManager.Instance.CreateSession()) 31 | { 32 | 33 | var mahuaApi = robotSession.MahuaApi; 34 | var members = mahuaApi.GetGroupMemebersWithModel(e.Data.ReadToEnd()).Model.ToList(); 35 | result = string.Join(" ", members.Select(g => g.Qq)); 36 | } 37 | 38 | await Send(result); 39 | } 40 | } 41 | */ 42 | public class AddGroup : WebSocketBehavior 43 | { 44 | protected override void OnMessage(MessageEventArgs e) 45 | { 46 | var group = e.Data; 47 | if (!Config.Instance.WFGroupList.Contains(group)) 48 | { 49 | Config.Instance.WFGroupList.Add(group); 50 | Config.Save(); 51 | Messenger.SendDebugInfo($"{group}启用了通知功能."); 52 | } 53 | 54 | } 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /WFBot/WebUI/App.razor: -------------------------------------------------------------------------------- 1 | @using GammaLibrary.Extensions 2 | @inject IHttpContextAccessor context 3 | @inject NavigationManager _navigationManager 4 | 5 | 6 | 7 | @if (!verified) 8 | { 9 |

访问需要验证

10 | 11 | 12 | } 13 | else 14 | { 15 | 16 | 17 | } 18 |
19 | 20 | Not found 21 | 22 |

Sorry, there's nothing at this address.

23 |
24 |
25 |
26 | 27 | @code 28 | { 29 | bool verified => Config.Instance.WebUIPassword.IsNullOrWhiteSpace() || context.HttpContext.Request.Cookies.TryGetValue("auth", out var pwd) && pwd == InternalPassword; 30 | string password; 31 | string InternalPassword => (Config.Instance.WebUIPassword + "5UPER_StR0NG_S1LT").SHA256().ToHexString(); 32 | 33 | 34 | void VerifyPassword() 35 | { 36 | _navigationManager.NavigateTo($"/auth?password={(password + "5UPER_StR0NG_S1LT").SHA256().ToHexString()}", true); 37 | } 38 | 39 | void Callback(KeyboardEventArgs obj) 40 | { 41 | if (obj.Key == "Enter") 42 | { 43 | VerifyPassword(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /WFBot/WebUI/Pages/About.razor: -------------------------------------------------------------------------------- 1 | @page "/about" 2 | 关于 3 |

关于

4 | 5 |

WFBot GitHub

6 |

WFBot 文档

7 | 8 | 9 | @code { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /WFBot/WebUI/Pages/CommandAlias.razor: -------------------------------------------------------------------------------- 1 | @page "/commandalias" 2 | @using WFBot.Features.Other 3 | @using WFBot.TextCommandCore 4 | @using System.Reflection 5 | @using GammaLibrary.Extensions 6 | 7 | @inject IBlazorStrap _blazorStrap 8 | 9 | 命令别名 10 |

命令别名

11 |

配置命令的别名, 按行分割

12 | 保存 13 | @foreach (var info in CustomCommandMatcherHandler._commandInfos.Value) 14 | { 15 | var id = info.Method.Name; 16 |

@id

17 | if (info.Method.IsAttributeDefined()) 18 | { 19 |

默认匹配器: @(info.Method.GetCustomAttribute().Matchers.Connect())

20 | } 21 | if (info.Method.IsAttributeDefined()) 22 | { 23 |

默认匹配器(不区分大小写): @(info.Method.GetCustomAttribute().Matchers.Connect())

24 | } 25 |

自定义匹配器

26 | 29 | } 30 | 31 | 32 | @code { 33 | internal static Dictionary> CustomCommandsRegistry => CustomCommandConfig.Instance.CustomCommands; 34 | async void Save() 35 | { 36 | await Task.Run(() => 37 | { 38 | CustomCommandConfig.Save(); 39 | 40 | }); 41 | _blazorStrap.Toaster.Add("提示", "保存成功"); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /WFBot/WebUI/Pages/CustomCommandContent.razor: -------------------------------------------------------------------------------- 1 | @page "/customcommandcontent" 2 | @using WFBot.Features.CustomCommandContent 3 | @using GammaLibrary.Extensions 4 | @using GammaLibrary.Common 5 | @inject IJSRuntime js 6 | @inject IBlazorStrap _blazorStrap 7 | 8 | 设置 9 | 10 |

自定义消息内容

11 |

12 | 警告: 这是一个极限测试版的功能, 非常不稳定, 使用需要在设置中开启. 如果遇到什么问题, 请刷新这个页面或重启 WFBot. 随着 WFBot 的更新, 里面的内容还会保持旧版, 所以你可能需要定期更新这个文件. 13 |

14 | 15 |

当前状态: @(Config.Instance.EnableCustomCommandContent ? "启用" : "**禁用**")

16 |

17 | 上次保存时的 WFBot 版本: @(CustomCommandContentConfig.Instance.LastSaveVersion.IsNullOrWhiteSpace() ? "从来没有保存过" : CustomCommandContentConfig.Instance.LastSaveVersion)     18 | @if (CustomCommandContentConfig.Instance.LastSaveVersion != WFBotCore.Version) 19 | { 20 | 对比和上次更改的源文件修改内容, 请转到 WFFormatter.cs 21 | } 22 |

23 | 24 |
25 | 26 | 27 | 28 |
29 | 30 |
31 | 32 | @code { 33 | 34 | protected override async Task OnAfterRenderAsync(bool firstRender) 35 | { 36 | if (firstRender) 37 | { 38 | await js.InvokeAsync("load_editor"); 39 | var content = CustomCommandContentConfig.Instance.Content; 40 | await js.InvokeAsync("set_editor_content", content.IsNullOrWhiteSpace() ? GetDefaultContent() : content); 41 | } 42 | } 43 | 44 | string GetDefaultContent() 45 | { 46 | return GammaLibrary.Resource.FromManifestResource("WFBot.Features.Utils.WFFormatter.cs").String.Replace("WFFormatter", "WFFormatterCustom"); 47 | } 48 | 49 | 50 | 51 | 52 | async void ResetToDefault() 53 | { 54 | await js.InvokeAsync("set_editor_content", GetDefaultContent()); 55 | } 56 | 57 | async void ResetToCurrent() 58 | { 59 | var content = CustomCommandContentConfig.Instance.Content; 60 | await js.InvokeAsync("set_editor_content", content); 61 | } 62 | 63 | AsyncLock locker = new AsyncLock(); 64 | 65 | async void Apply() 66 | { 67 | await locker.WaitAsync(); 68 | try 69 | { 70 | var content = await js.InvokeAsync("get_editor_content"); 71 | var s = await Task.Run(() => 72 | { 73 | try 74 | { 75 | CustomCommandContentConfig.Instance.Content = content; 76 | CustomCommandContentConfig.Save(); 77 | CustomCommandContentHandler.Load(true); 78 | return "成功!"; 79 | } 80 | catch (Exception e) 81 | { 82 | return e.ToString(); 83 | } 84 | }); 85 | Console.WriteLine(s); 86 | _blazorStrap.Toaster.Add("提示" ,s); 87 | } 88 | finally 89 | { 90 | locker.Dispose(); 91 | } 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /WFBot/WebUI/Pages/Debug.razor: -------------------------------------------------------------------------------- 1 | @page "/debug" 2 | @using WFBot.Features.Events 3 | @using WFBot.Features.Commands 4 | @using WFBot.Features.ImageRendering 5 | @using WFBot.Orichalt 6 | @using WFBot.TextCommandCore 7 | @using WFBot.Utils 8 | @using GammaLibrary.Extensions 9 | @inject IBlazorStrap _blazorStrap 10 |

Debug

11 | 12 |

通知测试

13 | 执行 14 | 15 |

命令测试

16 | @foreach (var c in commands) 17 | { 18 |

@c

19 | 执行 20 |
@(results.ContainsKey(c) ? results[c] : "")
21 | 22 | } 23 | 24 | 25 | @code { 26 | Dictionary results = new(); 27 | Dictionary resultsImage = new(); 28 | 29 | string[] commands = new[] 30 | { 31 | "金星赏金", 32 | "金星赏金 5", 33 | "地球赏金", 34 | "地球赏金 5", 35 | "火卫赏金", 36 | "火卫赏金 7", 37 | "裂隙", 38 | "裂隙 1", 39 | "遗物 后纪L4", 40 | "翻译 致残突击", 41 | "赤毒", 42 | "警报", 43 | "突击", 44 | "入侵", 45 | "仲裁", 46 | "午夜电波", 47 | "平原", 48 | "活动", 49 | "虚空商人", 50 | "小小黑", 51 | "s船", 52 | "wiki", 53 | "查询 Valkyr Prime 一套", 54 | "紫卡 绝路", 55 | "WFA紫卡 绝路", 56 | "wiki Valkyr", 57 | "status", 58 | "help", 59 | "查询 瓦尔基里", 60 | "查询 电男", 61 | "查询 致残", 62 | "虚空风暴 1", 63 | "钢铁裂缝 1", 64 | }; 65 | 66 | 67 | void TestNotify() 68 | { 69 | WFBotCore.Instance.NotificationHandler.TestNotification(); 70 | _blazorStrap.Toaster.Add("提示", "已经清空了已发送的入侵, 如果其中有稀有奖励, 机器人将会在下次提醒时发送."); 71 | 72 | } 73 | async Task Execute(string s) 74 | { 75 | await Task.Run(async () => 76 | { 77 | 78 | var cancelSource = new CancellationTokenSource(); 79 | AsyncContext.SetCancellationToken(cancelSource.Token); 80 | 81 | AsyncContext.SetUseImageRendering(true); 82 | var orichaltContext = new OrichaltContext(s, MessagePlatform.Unknown, MessageScope.Public); 83 | AsyncContext.SetOrichaltContext(orichaltContext); 84 | var c = new CommandsHandler(orichaltContext, s); 85 | c.RichMessageSender = messages => 86 | { 87 | var image = messages.FirstOrDefault(x => x is ImageMessage); 88 | if (image != null) 89 | { 90 | resultsImage[s] = "data:image/png;base64," + ((ImageMessage) image).Content.ToBase64String(); 91 | } 92 | }; 93 | var input = await c.ProcessCommandInput(); 94 | results[s] = input.result + c.OutputStringBuilder.ToString(); 95 | InvokeAsync(StateHasChanged); 96 | }); 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /WFBot/WebUI/Pages/Error.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model WFBot.WebUI.Pages.ErrorModel 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Error 11 | 12 | 13 | 14 | 15 | 16 |
17 |
18 |

Error.

19 |

An error occurred while processing your request.

20 | 21 | @if (Model.ShowRequestId) 22 | { 23 |

24 | Request ID: @Model.RequestId 25 |

26 | } 27 | 28 |

Development Mode

29 |

30 | Swapping to the Development environment displays detailed information about the error that occurred. 31 |

32 |

33 | The Development environment shouldn't be enabled for deployed applications. 34 | It can result in displaying sensitive information from exceptions to end users. 35 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 36 | and restarting the app. 37 |

38 |
39 |
40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /WFBot/WebUI/Pages/Error.cshtml.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Microsoft.AspNetCore.Mvc.RazorPages; 3 | using System.Diagnostics; 4 | 5 | namespace WFBot.WebUI.Pages 6 | { 7 | [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] 8 | [IgnoreAntiforgeryToken] 9 | public class ErrorModel : PageModel 10 | { 11 | public string RequestId { get; set; } 12 | 13 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); 14 | 15 | private readonly ILogger _logger; 16 | 17 | public ErrorModel(ILogger logger) 18 | { 19 | _logger = logger; 20 | } 21 | 22 | public void OnGet() 23 | { 24 | RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /WFBot/WebUI/Pages/Features.razor: -------------------------------------------------------------------------------- 1 | @page "/feature" 2 | @using WFBot.Orichalt 3 | @using System.Diagnostics 4 | 一些功能 5 |

功能

6 |
7 |

超级广播

8 |

向所有开启了通知功能的群发送一条广播

9 | 10 | 11 |

删除所有缓存

12 |

如果因为缓存原因不能载入机器人, 可以在这里删除

13 | 14 | 15 |
16 | 17 | @if (showModal) 18 | { 19 | 43 | } 44 | 45 | @code { 46 | // 抄代码 https://gist.github.com/conficient/ba98d1662c659e170ec16650acea05c8 47 | string broadcastContent; 48 | bool showModal = false; 49 | 50 | void ModalShow() => showModal = true; 51 | void ModalCancel() => showModal = false; 52 | void ModalOk() 53 | { 54 | MiguelNetwork.Broadcast(broadcastContent); 55 | showModal = false; 56 | } 57 | 58 | void DeleteCache() 59 | { 60 | Task.Run(() => 61 | { 62 | foreach (var file in Directory.GetFiles("WFCaches")) 63 | { 64 | try 65 | { 66 | File.Delete(file); 67 | } 68 | catch (Exception e) 69 | { 70 | Trace.WriteLine($"缓存 {file} 删除失败: {e}"); 71 | } 72 | } 73 | }); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /WFBot/WebUI/Pages/Index.razor: -------------------------------------------------------------------------------- 1 | @page "/" 2 | @using Microsoft.AspNetCore.Components.Server.Circuits 3 | @using System.Diagnostics 4 | @using WFBot.Features.Telemetry 5 | @implements IDisposable 6 | 主页 7 |

WFBot Dashboard

8 |

状态

9 |

客户端 ID @(TelemetryClient.ClientID)

10 |

已经运行了 @((DateTime.Now - WFBotCore.StartTime).ToString("d' 天 'hh\\:mm\\:ss")).

11 |

当前内存占用 @((Environment.WorkingSet / 1024.0 / 1024.0).ToString("F2")) MB.

12 |

当前存储占用 @((new DirectoryInfo(".").EnumerateFiles("*.*", SearchOption.AllDirectories).Select(f => f.Length).Sum() / 1024.0 / 1024.0).ToString("F1") + " MB").

13 | 14 |
15 |

日志

16 | 17 |
18 |
19 |
20 |
21 |             
22 |                 @foreach (var c in WebLogTraceListener.Lines)
23 |                 {
24 |                     @c
25 |                 }
26 |             
27 |         
28 |
29 |
30 |
31 |

执行控制台命令

32 |
33 |
34 | 35 |
36 |
37 | 38 |
39 |
40 | 41 | 42 | 43 | @code 44 | { 45 | string command; 46 | Timer updateTimer; 47 | protected override void OnInitialized() 48 | { 49 | WFBotWebUIServer.DataChanged += HandleDataChanged; 50 | updateTimer = new Timer(Tick, null, 0, 1000); 51 | } 52 | 53 | void Tick(object state) 54 | { 55 | InvokeAsync(StateHasChanged); 56 | } 57 | 58 | public void Dispose() 59 | { 60 | WFBotWebUIServer.DataChanged -= HandleDataChanged; 61 | updateTimer?.Dispose(); 62 | } 63 | 64 | public void HandleDataChanged(object sender, EventArgs args) 65 | { 66 | InvokeAsync(StateHasChanged); 67 | } 68 | 69 | void ExecuteCommand() 70 | { 71 | var c = command; 72 | Task.Run(() => 73 | { 74 | WFBotCore.Instance.OnConsoleCommand(c); 75 | }); 76 | command = ""; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /WFBot/WebUI/Pages/MiraiSettings.razor: -------------------------------------------------------------------------------- 1 | @page "/miraisettings" 2 | @using WFBot.Orichalt 3 | @using WFBot.Orichalt.OrichaltConnectors 4 | @using Microsoft.AspNetCore.Components 5 | 6 | @inject IBlazorStrap _blazorStrap 7 | 8 | 设置 9 | 10 |

设置

11 | 12 | @if (Config.Instance.Miguel_Platform != MessagePlatform.MiraiHTTP) 13 | { 14 | 17 | 18 | } 19 | else 20 | { 21 | 22 |
23 | 24 |
25 | 26 | 27 |
28 |
29 |
30 |
31 | 32 | 33 |
34 | 35 |
36 | 37 |
38 |
39 |
40 | 41 |
42 | 43 |
44 |
45 |
46 | 47 |
48 | 49 |
50 |
51 | 52 |
53 | 54 |
55 | 56 |
57 |
58 |
59 |
60 | 61 | 64 |
65 |
66 |
67 | 68 |
69 | 70 | 71 |
72 |
73 |
74 |
75 | 76 | 79 |
80 |
81 | 82 |
83 | 84 | 85 | 86 | 87 |
88 |
89 |
90 | } 91 | 92 | 93 | 94 | @code 95 | { 96 | MiraiConfig config => MiraiConfig.Instance; 97 | async void Save() 98 | { 99 | await Task.Run(() => 100 | { 101 | MiraiConfig.Save(); 102 | 103 | }); 104 | _blazorStrap.Toaster.Add("提示", "保存成功"); 105 | } 106 | } -------------------------------------------------------------------------------- /WFBot/WebUI/Pages/MiraiSettingsV1.razor: -------------------------------------------------------------------------------- 1 | @page "/miraisettingsv1" 2 | @using WFBot.Orichalt 3 | @using WFBot.Orichalt.OrichaltConnectors 4 | @using Microsoft.AspNetCore.Components 5 | 6 | @inject IBlazorStrap _blazorStrap 7 | 8 | 设置 9 | 10 |

设置

11 | 12 | @if (Config.Instance.Miguel_Platform != MessagePlatform.MiraiHTTPV1) 13 | { 14 | 17 | 18 | } 19 | else 20 | { 21 | 22 |
23 | 24 |
25 | 26 | 27 |
28 |
29 |
30 |
31 | 32 | 33 |
34 | 35 |
36 | 37 |
38 |
39 |
40 | 41 |
42 | 43 |
44 |
45 |
46 | 47 |
48 | 49 |
50 |
51 | 52 |
53 | 54 |
55 | 56 |
57 |
58 |
59 |
60 | 61 | 64 |
65 |
66 |
67 | 68 |
69 | 70 | 71 |
72 |
73 | 74 | 75 | 76 |
77 | 78 | 79 | 80 | 81 |
82 |
83 |
84 | } 85 | 86 | 87 | 88 | @code 89 | { 90 | MiraiV1Config config => MiraiV1Config.Instance; 91 | async void Save() 92 | { 93 | await Task.Run(() => 94 | { 95 | MiraiV1Config.Save(); 96 | 97 | }); 98 | _blazorStrap.Toaster.Add("提示", "保存成功"); 99 | } 100 | } -------------------------------------------------------------------------------- /WFBot/WebUI/Pages/OntbotSettings.razor: -------------------------------------------------------------------------------- 1 | @page "/onebotsettings" 2 | @using WFBot.Orichalt 3 | @using WFBot.Orichalt.OrichaltConnectors 4 | @using Microsoft.AspNetCore.Components 5 | 6 | @inject IBlazorStrap _blazorStrap 7 | 8 | 设置 9 | 10 |

设置

11 | 12 | 13 | @if (Config.Instance.Miguel_Platform != MessagePlatform.OneBot) 14 | { 15 | 18 | 19 | } 20 | else 21 | { 22 |
23 | 24 |
25 | 26 | 27 |
28 |
29 |
30 |
31 | 32 | 33 |
34 | 35 |
36 | 37 |
38 |
39 |
40 | 41 |
42 | 43 |
44 |
45 |
46 | 47 |
48 | 49 |
50 |
51 |
52 |
53 | 54 | 57 |
58 |
59 |
60 | 61 |
62 | 63 | 64 |
65 |
66 | 67 | 68 | 69 |
70 | 71 | 72 | 73 | 74 |
75 |
76 |
77 | } 78 | @code 79 | { 80 | OneBotConfig config => OneBotConfig.Instance; 81 | async void Save() 82 | { 83 | await Task.Run(() => 84 | { 85 | OneBotConfig.Save(); 86 | 87 | }); 88 | _blazorStrap.Toaster.Add("提示", "保存成功"); 89 | } 90 | } -------------------------------------------------------------------------------- /WFBot/WebUI/Pages/_Host.cshtml: -------------------------------------------------------------------------------- 1 | @page "/" 2 | @namespace WFBot.WebUI.Pages 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | @{ 5 | Layout = "_Layout.cshtml"; 6 | } 7 | 8 | 9 | -------------------------------------------------------------------------------- /WFBot/WebUI/Pages/_Layout.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Web 2 | @namespace WFBot.WebUI.Pages 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | @RenderBody() 18 | 19 |
20 | 21 | An error has occurred. This application may no longer respond until reloaded. 22 | 23 | 24 | An unhandled exception has occurred. See browser dev tools for details. 25 | 26 | Reload 27 | 🗙 28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /WFBot/WebUI/Shared/InputRadioForkMicrosoft.razor: -------------------------------------------------------------------------------- 1 | @using System.Globalization 2 | @typeparam TValue 3 | 4 | 6 | 7 | 8 | 9 | @code { 10 | [Parameter] 11 | public string id { get; set; } 12 | [Parameter] 13 | public TValue SelectedValue { get; set; } 14 | [Parameter] 15 | public TValue TrueValue { get; set; } 16 | 17 | private void OnChange(ChangeEventArgs args) 18 | { 19 | 20 | TrueValueChanged.InvokeAsync(SelectedValue); 21 | } 22 | 23 | 24 | [Parameter] 25 | public EventCallback TrueValueChanged { get; set; } 26 | 27 | 28 | } -------------------------------------------------------------------------------- /WFBot/WebUI/Shared/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 | WFBot 4 | 5 |
6 | 9 | 10 |
11 |
12 | GitHub 13 |
14 | 15 |
16 | @Body 17 |
18 |
19 |
20 | 21 | -------------------------------------------------------------------------------- /WFBot/WebUI/Shared/MainLayout.razor.css: -------------------------------------------------------------------------------- 1 | .page { 2 | position: relative; 3 | display: flex; 4 | flex-direction: column; 5 | } 6 | 7 | main { 8 | flex: 1; 9 | } 10 | 11 | .sidebar { 12 | background-image: linear-gradient(180deg, rgba(41,23,147,1) 30%, rgba(102,204,255,1) 100%); 13 | } 14 | 15 | .top-row { 16 | background-color: #f7f7f7; 17 | border-bottom: 1px solid #d6d5d5; 18 | justify-content: flex-end; 19 | height: 3.5rem; 20 | display: flex; 21 | align-items: center; 22 | } 23 | 24 | .top-row /*::deep*/ a, .top-row .btn-link { 25 | white-space: nowrap; 26 | margin-left: 1.5rem; 27 | } 28 | 29 | .top-row a:first-child { 30 | overflow: hidden; 31 | text-overflow: ellipsis; 32 | } 33 | 34 | @media (max-width: 640.98px) { 35 | .top-row:not(.auth) { 36 | display: none; 37 | } 38 | 39 | .top-row.auth { 40 | justify-content: space-between; 41 | } 42 | 43 | .top-row a, .top-row .btn-link { 44 | margin-left: 0; 45 | } 46 | } 47 | 48 | @media (min-width: 641px) { 49 | .page { 50 | flex-direction: row; 51 | } 52 | 53 | .sidebar { 54 | width: 250px; 55 | height: 100vh; 56 | position: sticky; 57 | top: 0; 58 | } 59 | 60 | .top-row { 61 | position: sticky; 62 | top: 0; 63 | z-index: 1; 64 | } 65 | 66 | .top-row, article { 67 | padding-left: 2rem !important; 68 | padding-right: 1.5rem !important; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /WFBot/WebUI/Shared/NavMenu.razor: -------------------------------------------------------------------------------- 1 |  9 | 10 |
11 | 64 |
65 | 66 | @code { 67 | private bool collapseNavMenu = true; 68 | 69 | private string NavMenuCssClass => collapseNavMenu ? "collapse" : null; 70 | 71 | private void ToggleNavMenu() 72 | { 73 | collapseNavMenu = !collapseNavMenu; 74 | 75 | } 76 | 77 | private static string PureVersionString = WFBotCore.Version.Split('+').First(); 78 | 79 | 80 | } -------------------------------------------------------------------------------- /WFBot/WebUI/Shared/NavMenu.razor.css: -------------------------------------------------------------------------------- 1 | .navbar-toggler { 2 | background-color: rgba(255, 255, 255, 0.1); 3 | } 4 | 5 | .top-row { 6 | height: 3.5rem; 7 | background-color: rgba(0,0,0,0.4); 8 | } 9 | 10 | .navbar-brand { 11 | font-size: 1.1rem; 12 | } 13 | 14 | .oi { 15 | width: 2rem; 16 | font-size: 1.1rem; 17 | vertical-align: text-top; 18 | top: -2px; 19 | } 20 | 21 | .nav-item { 22 | font-size: 0.9rem; 23 | padding-bottom: 0.5rem; 24 | } 25 | 26 | .nav-item:first-of-type { 27 | padding-top: 1rem; 28 | } 29 | 30 | .nav-item:last-of-type { 31 | padding-bottom: 1rem; 32 | } 33 | 34 | /* ReSharper disable once CssNotResolved */ 35 | .nav-item ::deep a { 36 | color: #d7d7d7; 37 | border-radius: 4px; 38 | height: 3rem; 39 | display: flex; 40 | align-items: center; 41 | line-height: 3rem; 42 | } 43 | 44 | /* ReSharper disable once CssNotResolved */ 45 | .nav-item ::deep a.active { 46 | background-color: rgba(255,255,255,0.25); 47 | color: white; 48 | } 49 | 50 | /* ReSharper disable once CssNotResolved */ 51 | .nav-item ::deep a:hover { 52 | background-color: rgba(255,255,255,0.1); 53 | color: white; 54 | } 55 | 56 | @media (min-width: 641px) { 57 | .navbar-toggler { 58 | display: none; 59 | } 60 | 61 | .collapse { 62 | /* Never collapse the sidebar for wide screens */ 63 | display: block; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /WFBot/WebUI/WebLogTraceListener.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Concurrent; 2 | using System.Diagnostics; 3 | using System.Text; 4 | 5 | namespace WFBot.WebUI 6 | { 7 | public class WebLogTraceListener : TraceListener 8 | { 9 | public static FixedSizedQueue Lines = new(1000); 10 | StringBuilder tempStringBuilder = new(); 11 | 12 | public override void Write(string message) 13 | { 14 | lock (this) 15 | { 16 | foreach (var c in (message ?? "").ToCharArray()) 17 | { 18 | tempStringBuilder.Append(c); 19 | if (c == '\n') 20 | { 21 | Lines.Enqueue(tempStringBuilder.ToString()); 22 | tempStringBuilder.Clear(); 23 | WFBotWebUIServer.NotifyDataChanged(); 24 | } 25 | } 26 | } 27 | } 28 | 29 | public override void WriteLine(string message) 30 | { 31 | Write($"{message}" + Environment.NewLine); 32 | } 33 | } 34 | 35 | 36 | // https://stackoverflow.com/questions/5852863/fixed-size-queue-which-automatically-dequeues-old-values-upon-new-enques 37 | // 抄代码真爽哦 38 | public class FixedSizedQueue : ConcurrentQueue 39 | { 40 | private readonly object syncObject = new object(); 41 | 42 | public int Size { get; private set; } 43 | 44 | public FixedSizedQueue(int size) 45 | { 46 | Size = size; 47 | } 48 | 49 | public new void Enqueue(T obj) 50 | { 51 | base.Enqueue(obj); 52 | lock (syncObject) 53 | { 54 | while (base.Count > Size) 55 | { 56 | T outObj; 57 | base.TryDequeue(out outObj); 58 | } 59 | } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /WFBot/WebUI/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using Microsoft.AspNetCore.Authorization 3 | @using Microsoft.AspNetCore.Components.Authorization 4 | @using Microsoft.AspNetCore.Components.Forms 5 | @using Microsoft.AspNetCore.Components.Routing 6 | @using Microsoft.AspNetCore.Components.Web 7 | @using Microsoft.AspNetCore.Components.Web.Virtualization 8 | @using Microsoft.JSInterop 9 | @using WFBot.WebUI 10 | @using WFBot.WebUI.Shared 11 | @using BlazorStrap -------------------------------------------------------------------------------- /WFBot/Windows/OriginalSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.Text; 6 | using GammaLibrary.Extensions; 7 | using WFBot.Features.Utils; 8 | 9 | namespace WFBot 10 | { 11 | public static class DictionaryExtensions 12 | { 13 | /*public static Dictionary Reverse(this Dictionary dic) 14 | { 15 | dic.SelectMany(k => k.Value 16 | .Select(v => new { Key = v, Value = k.Key })) 17 | .ToDictionary(t => t.Key, t => t.Value); 18 | }*/ 19 | // 不会写泛型( 20 | } 21 | public static class StringExtensions 22 | { 23 | public static bool IsNumber(this string source) 24 | { 25 | return int.TryParse(source, out _); 26 | } 27 | 28 | public static string ToBase64(this string source) 29 | { 30 | var bytes = Encoding.UTF8.GetBytes(source); 31 | return Convert.ToBase64String(bytes); 32 | } 33 | 34 | public static string Format(this string source) 35 | { 36 | return source.Replace(" ", "").ToLower().Trim(); 37 | } 38 | 39 | public static string FormatFast(this string source) 40 | { 41 | return source.Replace(" ", "").ToLower(); 42 | } 43 | } 44 | 45 | public enum Platform 46 | { 47 | [Symbol("pc")]PC, 48 | [Symbol("xb1")]XBOX, 49 | [Symbol("ps4")]PS4, 50 | [Symbol("swi")]NS 51 | } 52 | [AttributeUsage(AttributeTargets.Field | AttributeTargets.Class)] // 谢啦 嫖代码真的爽 53 | class SymbolAttribute : Attribute 54 | { 55 | public string[] Symbols { get; } 56 | 57 | public SymbolAttribute(params string[] symbols) 58 | { 59 | Symbols = symbols; 60 | } 61 | } 62 | 63 | public static class EnumExtensions 64 | { 65 | public static string[] GetSymbols(this TEnum obj) where TEnum : Enum 66 | { 67 | try 68 | { 69 | return obj.GetType().GetMember(obj.ToString()).First() 70 | .GetCustomAttribute().Symbols; 71 | } 72 | catch (Exception) 73 | { 74 | // 在这里给你自己发信息 告诉你自己代码出错了. 75 | // 非机器人的写法为: 76 | // Debug.Assert(xxx); 如果xxx是false就会提醒你这里有一个代码bug 77 | // assert 为断言 不用看 这只是一种习惯 78 | Messenger.SendDebugInfo("你猜怎么着?你最不想看到的那部分,也就是自定义平台,他报错啦!!!机器人要炸啦!!!你要被用户骂死啦!!!(检查一下你的enum贴没贴symbol)"); 79 | return new string[0]; 80 | } 81 | } 82 | 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /WFBot/wwwroot/css/open-iconic/FONT-LICENSE: -------------------------------------------------------------------------------- 1 | SIL OPEN FONT LICENSE Version 1.1 2 | 3 | Copyright (c) 2014 Waybury 4 | 5 | PREAMBLE 6 | The goals of the Open Font License (OFL) are to stimulate worldwide 7 | development of collaborative font projects, to support the font creation 8 | efforts of academic and linguistic communities, and to provide a free and 9 | open framework in which fonts may be shared and improved in partnership 10 | with others. 11 | 12 | The OFL allows the licensed fonts to be used, studied, modified and 13 | redistributed freely as long as they are not sold by themselves. The 14 | fonts, including any derivative works, can be bundled, embedded, 15 | redistributed and/or sold with any software provided that any reserved 16 | names are not used by derivative works. The fonts and derivatives, 17 | however, cannot be released under any other type of license. The 18 | requirement for fonts to remain under this license does not apply 19 | to any document created using the fonts or their derivatives. 20 | 21 | DEFINITIONS 22 | "Font Software" refers to the set of files released by the Copyright 23 | Holder(s) under this license and clearly marked as such. This may 24 | include source files, build scripts and documentation. 25 | 26 | "Reserved Font Name" refers to any names specified as such after the 27 | copyright statement(s). 28 | 29 | "Original Version" refers to the collection of Font Software components as 30 | distributed by the Copyright Holder(s). 31 | 32 | "Modified Version" refers to any derivative made by adding to, deleting, 33 | or substituting -- in part or in whole -- any of the components of the 34 | Original Version, by changing formats or by porting the Font Software to a 35 | new environment. 36 | 37 | "Author" refers to any designer, engineer, programmer, technical 38 | writer or other person who contributed to the Font Software. 39 | 40 | PERMISSION & CONDITIONS 41 | Permission is hereby granted, free of charge, to any person obtaining 42 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 43 | redistribute, and sell modified and unmodified copies of the Font 44 | Software, subject to the following conditions: 45 | 46 | 1) Neither the Font Software nor any of its individual components, 47 | in Original or Modified Versions, may be sold by itself. 48 | 49 | 2) Original or Modified Versions of the Font Software may be bundled, 50 | redistributed and/or sold with any software, provided that each copy 51 | contains the above copyright notice and this license. These can be 52 | included either as stand-alone text files, human-readable headers or 53 | in the appropriate machine-readable metadata fields within text or 54 | binary files as long as those fields can be easily viewed by the user. 55 | 56 | 3) No Modified Version of the Font Software may use the Reserved Font 57 | Name(s) unless explicit written permission is granted by the corresponding 58 | Copyright Holder. This restriction only applies to the primary font name as 59 | presented to the users. 60 | 61 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 62 | Software shall not be used to promote, endorse or advertise any 63 | Modified Version, except to acknowledge the contribution(s) of the 64 | Copyright Holder(s) and the Author(s) or with their explicit written 65 | permission. 66 | 67 | 5) The Font Software, modified or unmodified, in part or in whole, 68 | must be distributed entirely under this license, and must not be 69 | distributed under any other license. The requirement for fonts to 70 | remain under this license does not apply to any document created 71 | using the Font Software. 72 | 73 | TERMINATION 74 | This license becomes null and void if any of the above conditions are 75 | not met. 76 | 77 | DISCLAIMER 78 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 79 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 80 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 81 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 82 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 83 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 84 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 85 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 86 | OTHER DEALINGS IN THE FONT SOFTWARE. 87 | -------------------------------------------------------------------------------- /WFBot/wwwroot/css/open-iconic/ICON-LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Waybury 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /WFBot/wwwroot/css/open-iconic/README.md: -------------------------------------------------------------------------------- 1 | [Open Iconic v1.1.1](http://useiconic.com/open) 2 | =========== 3 | 4 | ### Open Iconic is the open source sibling of [Iconic](http://useiconic.com). It is a hyper-legible collection of 223 icons with a tiny footprint—ready to use with Bootstrap and Foundation. [View the collection](http://useiconic.com/open#icons) 5 | 6 | 7 | 8 | ## What's in Open Iconic? 9 | 10 | * 223 icons designed to be legible down to 8 pixels 11 | * Super-light SVG files - 61.8 for the entire set 12 | * SVG sprite—the modern replacement for icon fonts 13 | * Webfont (EOT, OTF, SVG, TTF, WOFF), PNG and WebP formats 14 | * Webfont stylesheets (including versions for Bootstrap and Foundation) in CSS, LESS, SCSS and Stylus formats 15 | * PNG and WebP raster images in 8px, 16px, 24px, 32px, 48px and 64px. 16 | 17 | 18 | ## Getting Started 19 | 20 | #### For code samples and everything else you need to get started with Open Iconic, check out our [Icons](http://useiconic.com/open#icons) and [Reference](http://useiconic.com/open#reference) sections. 21 | 22 | ### General Usage 23 | 24 | #### Using Open Iconic's SVGs 25 | 26 | We like SVGs and we think they're the way to display icons on the web. Since Open Iconic are just basic SVGs, we suggest you display them like you would any other image (don't forget the `alt` attribute). 27 | 28 | ``` 29 | icon name 30 | ``` 31 | 32 | #### Using Open Iconic's SVG Sprite 33 | 34 | Open Iconic also comes in a SVG sprite which allows you to display all the icons in the set with a single request. It's like an icon font, without being a hack. 35 | 36 | Adding an icon from an SVG sprite is a little different than what you're used to, but it's still a piece of cake. *Tip: To make your icons easily style able, we suggest adding a general class to the* `` *tag and a unique class name for each different icon in the* `` *tag.* 37 | 38 | ``` 39 | 40 | 41 | 42 | ``` 43 | 44 | Sizing icons only needs basic CSS. All the icons are in a square format, so just set the `` tag with equal width and height dimensions. 45 | 46 | ``` 47 | .icon { 48 | width: 16px; 49 | height: 16px; 50 | } 51 | ``` 52 | 53 | Coloring icons is even easier. All you need to do is set the `fill` rule on the `` tag. 54 | 55 | ``` 56 | .icon-account-login { 57 | fill: #f00; 58 | } 59 | ``` 60 | 61 | To learn more about SVG Sprites, read [Chris Coyier's guide](http://css-tricks.com/svg-sprites-use-better-icon-fonts/). 62 | 63 | #### Using Open Iconic's Icon Font... 64 | 65 | 66 | ##### …with Bootstrap 67 | 68 | You can find our Bootstrap stylesheets in `font/css/open-iconic-bootstrap.{css, less, scss, styl}` 69 | 70 | 71 | ``` 72 | 73 | ``` 74 | 75 | 76 | ``` 77 | 78 | ``` 79 | 80 | ##### …with Foundation 81 | 82 | You can find our Foundation stylesheets in `font/css/open-iconic-foundation.{css, less, scss, styl}` 83 | 84 | ``` 85 | 86 | ``` 87 | 88 | 89 | ``` 90 | 91 | ``` 92 | 93 | ##### …on its own 94 | 95 | You can find our default stylesheets in `font/css/open-iconic.{css, less, scss, styl}` 96 | 97 | ``` 98 | 99 | ``` 100 | 101 | ``` 102 | 103 | ``` 104 | 105 | 106 | ## License 107 | 108 | ### Icons 109 | 110 | All code (including SVG markup) is under the [MIT License](http://opensource.org/licenses/MIT). 111 | 112 | ### Fonts 113 | 114 | All fonts are under the [SIL Licensed](http://scripts.sil.org/cms/scripts/page.php?item_id=OFL_web). 115 | -------------------------------------------------------------------------------- /WFBot/wwwroot/css/open-iconic/font/fonts/open-iconic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/wwwroot/css/open-iconic/font/fonts/open-iconic.eot -------------------------------------------------------------------------------- /WFBot/wwwroot/css/open-iconic/font/fonts/open-iconic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/wwwroot/css/open-iconic/font/fonts/open-iconic.otf -------------------------------------------------------------------------------- /WFBot/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf -------------------------------------------------------------------------------- /WFBot/wwwroot/css/open-iconic/font/fonts/open-iconic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/WFBot/wwwroot/css/open-iconic/font/fonts/open-iconic.woff -------------------------------------------------------------------------------- /WFBot/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 | @import url('open-iconic/font/css/open-iconic-bootstrap.min.css'); 2 | 3 | html, body { 4 | font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; 5 | } 6 | 7 | h1:focus { 8 | outline: none; 9 | } 10 | 11 | a, .btn-link { 12 | color: #0071c1; 13 | } 14 | 15 | .btn-primary { 16 | color: #fff; 17 | background-color: #1b6ec2; 18 | border-color: #1861ac; 19 | } 20 | 21 | .content { 22 | padding-top: 1.1rem; 23 | } 24 | 25 | .valid.modified:not([type=checkbox]) { 26 | outline: 1px solid #26b050; 27 | } 28 | 29 | .invalid { 30 | outline: 1px solid red; 31 | } 32 | 33 | .validation-message { 34 | color: red; 35 | } 36 | 37 | #blazor-error-ui { 38 | background: lightyellow; 39 | bottom: 0; 40 | box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); 41 | display: none; 42 | left: 0; 43 | padding: 0.6rem 1.25rem 0.7rem 1.25rem; 44 | position: fixed; 45 | width: 100%; 46 | z-index: 1000; 47 | } 48 | 49 | #blazor-error-ui .dismiss { 50 | cursor: pointer; 51 | position: absolute; 52 | right: 0.75rem; 53 | top: 0.5rem; 54 | } 55 | 56 | .blazor-error-boundary { 57 | background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121; 58 | padding: 1rem 1rem 1rem 3.7rem; 59 | color: white; 60 | } 61 | 62 | .blazor-error-boundary::after { 63 | content: "An error has occurred." 64 | } 65 | -------------------------------------------------------------------------------- /WFBot/wwwroot/js/editor.js: -------------------------------------------------------------------------------- 1 | // https://blog.expo.io/building-a-code-editor-with-monaco-f84b3a06deaf 2 | 3 | 4 | 5 | // ReSharper disable StringLiteralWrongQuotes 6 | 7 | let editor; 8 | let model; 9 | 10 | function set_editor_content(s) { 11 | require.config({ 12 | paths: { 13 | 'vs': 'https://cdn.jsdelivr.net/npm/monaco-editor@0.20.0/min/vs' 14 | } 15 | }); 16 | require(['vs/editor/editor.main'], function () { 17 | 18 | model = monaco.editor.createModel(s, "csharp"); 19 | editor.setModel(model); 20 | }); 21 | } 22 | 23 | function get_editor_content() { 24 | return model.getValue(); 25 | } 26 | 27 | function load_editor() { 28 | require.config({ 29 | paths: { 30 | 'vs': 'https://cdn.jsdelivr.net/npm/monaco-editor@0.20.0/min/vs' 31 | } 32 | }); 33 | 34 | 35 | let currentFile = '/index.php'; 36 | 37 | 38 | 39 | // localStorage.removeItem('files'); 40 | 41 | 42 | require(['vs/editor/editor.main'], function () { 43 | 44 | monaco.languages.typescript.javascriptDefaults.setEagerModelSync(true); 45 | monaco.languages.typescript.javascriptDefaults.setCompilerOptions({ 46 | allowNonTsExtensions: true 47 | }); 48 | 49 | 50 | editor = monaco.editor.create(document.getElementById('container'), { 51 | automaticLayout: true, 52 | scrollBeyondLastLine: false, 53 | model: null, 54 | readOnly: false, 55 | theme: "vs-dark", 56 | // roundedSelection: false, 57 | }); 58 | 59 | 60 | 61 | }); 62 | } 63 | 64 | -------------------------------------------------------------------------------- /WFBot/wwwroot2/WFBot.styles.css: -------------------------------------------------------------------------------- 1 | @import '_content/BlazorStrap/BlazorStrap.bundle.scp.css'; 2 | 3 | /* _content/WFBot/WebUI/Shared/MainLayout.razor.rz.scp.css */ 4 | .page[b-gip8mkgiy6] { 5 | position: relative; 6 | display: flex; 7 | flex-direction: column; 8 | } 9 | 10 | main[b-gip8mkgiy6] { 11 | flex: 1; 12 | } 13 | 14 | .sidebar[b-gip8mkgiy6] { 15 | background-image: linear-gradient(180deg, rgba(41,23,147,1) 30%, rgba(102,204,255,1) 100%); 16 | } 17 | 18 | .top-row[b-gip8mkgiy6] { 19 | background-color: #f7f7f7; 20 | border-bottom: 1px solid #d6d5d5; 21 | justify-content: flex-end; 22 | height: 3.5rem; 23 | display: flex; 24 | align-items: center; 25 | } 26 | 27 | .top-row /*::deep*/ a[b-gip8mkgiy6], .top-row .btn-link[b-gip8mkgiy6] { 28 | white-space: nowrap; 29 | margin-left: 1.5rem; 30 | } 31 | 32 | .top-row a:first-child[b-gip8mkgiy6] { 33 | overflow: hidden; 34 | text-overflow: ellipsis; 35 | } 36 | 37 | @media (max-width: 640.98px) { 38 | .top-row:not(.auth)[b-gip8mkgiy6] { 39 | display: none; 40 | } 41 | 42 | .top-row.auth[b-gip8mkgiy6] { 43 | justify-content: space-between; 44 | } 45 | 46 | .top-row a[b-gip8mkgiy6], .top-row .btn-link[b-gip8mkgiy6] { 47 | margin-left: 0; 48 | } 49 | } 50 | 51 | @media (min-width: 641px) { 52 | .page[b-gip8mkgiy6] { 53 | flex-direction: row; 54 | } 55 | 56 | .sidebar[b-gip8mkgiy6] { 57 | width: 250px; 58 | height: 100vh; 59 | position: sticky; 60 | top: 0; 61 | } 62 | 63 | .top-row[b-gip8mkgiy6] { 64 | position: sticky; 65 | top: 0; 66 | z-index: 1; 67 | } 68 | 69 | .top-row[b-gip8mkgiy6], article[b-gip8mkgiy6] { 70 | padding-left: 2rem !important; 71 | padding-right: 1.5rem !important; 72 | } 73 | } 74 | /* _content/WFBot/WebUI/Shared/NavMenu.razor.rz.scp.css */ 75 | .navbar-toggler[b-3cchsatipj] { 76 | background-color: rgba(255, 255, 255, 0.1); 77 | } 78 | 79 | .top-row[b-3cchsatipj] { 80 | height: 3.5rem; 81 | background-color: rgba(0,0,0,0.4); 82 | } 83 | 84 | .navbar-brand[b-3cchsatipj] { 85 | font-size: 1.1rem; 86 | } 87 | 88 | .oi[b-3cchsatipj] { 89 | width: 2rem; 90 | font-size: 1.1rem; 91 | vertical-align: text-top; 92 | top: -2px; 93 | } 94 | 95 | .nav-item[b-3cchsatipj] { 96 | font-size: 0.9rem; 97 | padding-bottom: 0.5rem; 98 | } 99 | 100 | .nav-item:first-of-type[b-3cchsatipj] { 101 | padding-top: 1rem; 102 | } 103 | 104 | .nav-item:last-of-type[b-3cchsatipj] { 105 | padding-bottom: 1rem; 106 | } 107 | 108 | /* ReSharper disable once CssNotResolved */ 109 | .nav-item[b-3cchsatipj] a { 110 | color: #d7d7d7; 111 | border-radius: 4px; 112 | height: 3rem; 113 | display: flex; 114 | align-items: center; 115 | line-height: 3rem; 116 | } 117 | 118 | /* ReSharper disable once CssNotResolved */ 119 | .nav-item[b-3cchsatipj] a.active { 120 | background-color: rgba(255,255,255,0.25); 121 | color: white; 122 | } 123 | 124 | /* ReSharper disable once CssNotResolved */ 125 | .nav-item[b-3cchsatipj] a:hover { 126 | background-color: rgba(255,255,255,0.1); 127 | color: white; 128 | } 129 | 130 | @media (min-width: 641px) { 131 | .navbar-toggler[b-3cchsatipj] { 132 | display: none; 133 | } 134 | 135 | .collapse[b-3cchsatipj] { 136 | /* Never collapse the sidebar for wide screens */ 137 | display: block; 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /WFBot/wwwroot2/_content/BlazorStrap/BlazorStrap.bundle.scp.css: -------------------------------------------------------------------------------- 1 | /* _content/BlazorStrap/Components/BootstrapComponents/BSPopover.razor.rz.scp.css */ 2 | .popover:not(.show)[b-kex6n1b759] { 3 | visibility:hidden; 4 | } 5 | /* _content/BlazorStrap/Components/BootstrapComponents/BSTooltip.razor.rz.scp.css */ 6 | .popover:not(.show)[b-1h1bjrpzgl] { 7 | visibility:hidden; 8 | } 9 | /* _content/BlazorStrap/Components/Content/BSDataTableHead.razor.rz.scp.css */ 10 | /*Credit https://codepen.io/imarkrige/pen/kyOjoL */ 11 | th a[b-pym1v3rx28], 12 | td a[b-pym1v3rx28] { 13 | display: block; 14 | width: 100%; 15 | } 16 | th a.sort-by[b-pym1v3rx28] { 17 | padding-right: 18px; 18 | position: relative; 19 | } 20 | a.sort-by[b-pym1v3rx28]:before, 21 | a.sort-by[b-pym1v3rx28]:after { 22 | border: 4px solid transparent; 23 | content: ""; 24 | display: block; 25 | height: 0; 26 | right: 5px; 27 | top: 50%; 28 | position: absolute; 29 | width: 0; 30 | } 31 | a.sort-by[b-pym1v3rx28]:before { 32 | border-bottom-color: #666; 33 | margin-top: -9px; 34 | } 35 | a.sort-by[b-pym1v3rx28]:after { 36 | border-top-color: #666; 37 | margin-top: 1px; 38 | } 39 | 40 | th a.sort[b-pym1v3rx28] { 41 | padding-right: 18px; 42 | position: relative; 43 | } 44 | 45 | a.sort[b-pym1v3rx28]:before, 46 | a.sort[b-pym1v3rx28]:after { 47 | border: 4px solid transparent; 48 | content: ""; 49 | display: block; 50 | height: 0; 51 | right: 5px; 52 | top: 50%; 53 | position: absolute; 54 | width: 0; 55 | } 56 | a.sort[b-pym1v3rx28]:before { 57 | border-bottom-color: #666; 58 | margin-top: -9px; 59 | } 60 | th a.sort-desc[b-pym1v3rx28] { 61 | padding-right: 18px; 62 | position: relative; 63 | } 64 | 65 | a.sort-desc[b-pym1v3rx28]:before, 66 | a.sort-desc[b-pym1v3rx28]:after { 67 | border: 4px solid transparent; 68 | content: ""; 69 | display: block; 70 | height: 0; 71 | right: 5px; 72 | top: 50%; 73 | position: absolute; 74 | width: 0; 75 | } 76 | 77 | a.sort-desc[b-pym1v3rx28]:after { 78 | border-top-color: #666; 79 | margin-top: 1px; 80 | } 81 | /* _content/BlazorStrap/InternalComponents/Error.razor.rz.scp.css */ 82 | .bserror[b-doufk0x9zt] { 83 | padding: .25rem 1rem; 84 | margin-top: 1.25rem; 85 | margin-bottom: 1.25rem; 86 | border: 1px solid #d8d8d8; 87 | border-left-width: .2rem; 88 | border-right-width: .2rem; 89 | border-radius: .25rem; 90 | border-left-color: var(--bs-red); 91 | border-right-color: var(--bs-red); 92 | } 93 | .bserror-header[b-doufk0x9zt] { 94 | font-size: 1.5em; 95 | } 96 | .bserror-header svg[b-doufk0x9zt]{ 97 | vertical-align: middle; 98 | } 99 | -------------------------------------------------------------------------------- /WFBotExamplePlugin/Class1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Harmony; 7 | using TRKS.WF.QQBot; 8 | using TRKS.WF.QQBot.MahuaEvents; 9 | 10 | namespace WFBotExamplePlugin 11 | { 12 | 13 | // 关于改方法的更多信息请查看 Harmony 库的 [这里](https://github.com/pardeike/Harmony/wiki/Patching) 14 | 15 | [HarmonyPatch(typeof(GroupMessageHandler))] // 这里写你想修改的方法所在的类 16 | [HarmonyPatch("FortunaMissions")] // 这里写你想修改方法的名字 17 | [HarmonyPatch(new[] { typeof(int) })] // 这里写这个方法的参数列表 18 | class Patch 19 | { 20 | // Prefix 的名字 不应修改 21 | static bool Prefix(int index = 0) // (非特殊)参数排序及参数名必须与原方法相同 返回值为 bool 的意思是 如果返回 false 就不会再执行原方法 22 | { 23 | Console.WriteLine("金星赏金 is fucked"); 24 | return false; 25 | } 26 | } 27 | 28 | // 这里的演示会让翻译器给出的结果全部为 AWSL 29 | [HarmonyPatch(typeof(Translator))] 30 | [HarmonyPatch("Translate")] 31 | [HarmonyPatch(new[] { typeof(string) })] 32 | class Patch2 33 | { 34 | // __instance 为该方法执行时的 this 35 | // __result 是如果你想修改这个方法的返回值 改这个 36 | // 更多信息请查看 https://github.com/pardeike/Harmony/wiki/Patching 37 | static bool Prefix(Translator __instance, ref string __result, string source) 38 | { 39 | Console.WriteLine("Translator is fucked"); 40 | __result = $"AWSL: {source}"; 41 | return false; 42 | } 43 | } 44 | 45 | [HarmonyPatch(typeof(WFFormatter))] 46 | [HarmonyPatch("Translate")] 47 | [HarmonyPatch(new[] { typeof(string) })] 48 | class Patch3 49 | { 50 | // __instance 为该方法执行时的 this 51 | // __result 是如果你想修改这个方法的返回值 改这个 52 | // 更多信息请查看 https://github.com/pardeike/Harmony/wiki/Patching 53 | static bool Prefix(Translator __instance, ref string __result, string source) 54 | { 55 | Console.WriteLine("Translator is fucked"); 56 | __result = $"AWSL: {source}"; 57 | return false; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /WFBotExamplePlugin/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("WFBotExamplePlugin")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("WFBotExamplePlugin")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("67442f2c-e4d2-4454-b3cd-7f504b96aae5")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /WFBotExamplePlugin/WFBotExamplePlugin.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {67442F2C-E4D2-4454-B3CD-7F504B96AAE5} 8 | Library 9 | Properties 10 | WFBotExamplePlugin 11 | WFBotExamplePlugin 12 | v4.6.2 13 | 512 14 | true 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | ..\packages\Lib.Harmony.1.2.0.1\lib\net45\0Harmony.dll 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | {795fa006-a765-48d7-a488-efd37d7ca474} 57 | TRKS.WF.QQBot 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /WFBotExamplePlugin/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /WFBotExamplePlugin/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /build-wfbot-ci.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | REM dotnet publish WFBot -o out/WFBotLinuxArm64 -r linux-arm64 --self-contained false -c "Linux Release" -p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true 3 | REM dotnet publish WFBot -o out/WFBotLinux -r linux-x64 --self-contained false -c "Linux Release" -p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true 4 | REM dotnet publish WFBot -o out/WFBotWindows -r win-x86 --self-contained false -c "Linux Release" -p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true 5 | 6 | powershell -Command "(gc WFBot/WFBot.csproj) -replace 'net6.0', 'net7.0' | Out-File -encoding ASCII WFBot/WFBot.csproj" 7 | dotnet publish WFBot -o out/WFBotLinuxArm64S -r linux-arm64 --self-contained true -c "Linux Release" -p:PublishSingleFile=true /p:TargetFramework=net7.0 /p:IncludeNativeLibrariesForSelfExtract=true 8 | dotnet publish WFBot -o out/WFBotLinuxX64S -r linux-x64 --self-contained true -c "Linux Release" -p:PublishSingleFile=true /p:TargetFramework=net7.0 /p:IncludeNativeLibrariesForSelfExtract=true 9 | dotnet publish WFBot -o out/WFBotWindowsS -r win-x86 --self-contained true -c "Linux Release" -p:PublishSingleFile=true /p:TargetFramework=net7.0 /p:IncludeNativeLibrariesForSelfExtract=true 10 | -------------------------------------------------------------------------------- /build-wfbot-nogitversion.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | set NoGitVersion=hso 3 | dotnet publish WFBot -o out/WFBotLinux -c "Linux Release" -------------------------------------------------------------------------------- /build-wfbot-test.bat: -------------------------------------------------------------------------------- 1 | docker build -t trksteam/wfbot:test . 2 | docker image push trksteam/wfbot:test -------------------------------------------------------------------------------- /build-wfbot.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | REM dotnet publish WFBot -o out/WFBotLinuxArm64 -r linux-arm64 --self-contained false -c "Linux Release" -p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true 3 | REM dotnet publish WFBot -o out/WFBotLinux -r linux-x64 --self-contained false -c "Linux Release" -p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true 4 | REM dotnet publish WFBot -o out/WFBotWindows -r win-x86 --self-contained false -c "Linux Release" -p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true 5 | 6 | dotnet publish WFBot -o out/WFBotLinuxArm64S -r linux-arm64 --self-contained true -c "Linux Release" -p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true 7 | dotnet publish WFBot -o out/WFBotLinuxX64S -r linux-x64 --self-contained true -c "Linux Release" -p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true 8 | dotnet publish WFBot -o out/WFBotWindowsS -r win-x86 --self-contained true -c "Linux Release" -p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true 9 | -------------------------------------------------------------------------------- /docs/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.9' 2 | 3 | services: 4 | mirai: 5 | restart: unless-stopped 6 | image: trksteam/mirai-docker:latest 7 | volumes: 8 | - ./config:/app/config 9 | - ./data:/app/data 10 | - ./logs:/app/logs 11 | - ./bots:/app/bots 12 | - ./plugin-libraries:/app/plugin-libraries 13 | labels: 14 | com.centurylinklabs.watchtower.enable: true 15 | wfbot: 16 | restart: unless-stopped 17 | image: trksteam/wfbot 18 | ports: 19 | - "9331:9331" 20 | volumes: 21 | - ./WFBotPlugins:/app/WFBotPlugins 22 | - ./WFBotLogs:/app/WFBotLogs 23 | - ./WFOfflineResource:/app/WFOfflineResource 24 | - ./WFBotConfigs:/app/WFBotConfigs 25 | labels: 26 | com.centurylinklabs.watchtower.enable: true 27 | watchtower: 28 | restart: unless-stopped 29 | image: containrrr/watchtower 30 | volumes: 31 | - /var/run/docker.sock:/var/run/docker.sock 32 | environment: 33 | WATCHTOWER_LABEL_ENABLE: 'true' 34 | WATCHTOWER_POLL_INTERVAL: 1800 35 | WATCHTOWER_CLEANUP: 'true' 36 | 37 | -------------------------------------------------------------------------------- /docs/docker.md: -------------------------------------------------------------------------------- 1 | # Docker 部署 2 | 3 | 0. 安装 Docker 可以参阅 4 | 1. 找个文件夹, 比如说创一个叫 mirai 5 | 2. 新建一个叫 `docker-compose.yml` 的文件, 将 的内容复制到里面; 6 | > 直接执行 `wget https://ghproxy.com/https://raw.githubusercontent.com/TRKS-Team/WFBot/universal/docs/docker-compose.yml` 也可 7 | 3. 首先运行 `sudo docker-compose run --rm mirai` 配置mirai的自动登录和滑动 8 | > 也可以顺便将原本的Device.json复制到 `mirai/bots/{机器人qq}/` 下, 避免反复出现滑动验证 9 | > 你可以先下载[MiraiAndroid](https://github.com/mzdluo123/MiraiAndroid), 在手机上完成登录后, 选择导出Device.json, 然后复制到对应的文件夹下 10 | 11 | 输入 `autoLogin add {机器人QQ} {密码}` 12 | 4. 打开`mirai/config/net.mamoe.mirai-api-http` 修改其中的 `setting.yml` 为以下内容 13 | 14 | ```yaml 15 | adapters: 16 | - http 17 | - ws 18 | debug: false 19 | enableVerify: true 20 | verifyKey: '请修改我' ## 修改为一个与下文一样的Token 21 | singleMode: false 22 | cacheSize: 4096 23 | adapterSettings: 24 | ws: 25 | ## websocket server 监听的本地地址 26 | ## 一般为 localhost 即可, 如果多网卡等情况,自定设置 27 | host: 0.0.0.0 28 | 29 | ## websocket server 监听的端口 30 | ## 与 http server 可以重复, 由于协议与路径不同, 不会产生冲突 31 | port: 8080 32 | 33 | reservedSyncId: -1 34 | http: 35 | ## http server 监听的本地地址 36 | ## 一般为 localhost 即可, 如果多网卡等情况,自定设置 37 | host: 0.0.0.0 38 | 39 | ## http server 监听的端口 40 | ## 与 websocket server 可以重复, 由于协议与路径不同, 不会产生冲突 41 | port: 8080 42 | 43 | ## 配置跨域, 默认允许来自所有域名 44 | cors: [*] 45 | ``` 46 | 5. 再次运行 `sudo docker-compose run --rm mirai` 观察到以下绿色输出 47 | ![](images/QQ%E6%88%AA%E5%9B%BE20220627214408.png) 48 | > 请顺便确认机器人也已经自动登录 49 | 7. 运行 `sudo docker-compose up -d mirai` 此时 mirai 已经在docker容器内运行 50 | 8. 运行 `sudo docker-compose run --rm wfbot` 观察到以下输出 51 | ![](images/QQ%E6%88%AA%E5%9B%BE20220627214621.png) 52 | 打开 `mirai/WFBotConfigs/WFConfig.json` 修改此处内容 53 | ![](images/QQ%E6%88%AA%E5%9B%BE20220627214806.png) 54 | 再次运行 `sudo docker-compose run --rm wfbot` 观察到以下输出 55 | ![](images/QQ%E6%88%AA%E5%9B%BE20220627214916.png) 56 | 打开`mirai/WFBotConfigs/MiraiHTTPv2.json` 修改为以下内容 57 | ![](images/QQ%E6%88%AA%E5%9B%BE20220627215234.png) 58 | 最后再次运行 `sudo docker-compose run --rm wfbot` 可以尝试与机器人进行消息互动确保运行正常 59 | 确保正常后摁下 Ctrl+C 退出 wfbot 60 | 9. 运行 `sudo docker-compose up -d wfbot` 此时WFBot也将在docker容器内运行 61 | 62 | ## 如何启动和更新 63 | **本教程顺便部署了一个 [Watchtower](https://github.com/containrrr/watchtower/) 实例, 将会每半个小时自动检查 mirai 和 WFBot的更新, 如果有更新将会自动重启容器完成自动更新.** 64 | 想要再次启动, 就直接输入 `sudo docker-compose up -d` , WFBot 将会在 mirai 启动后自动连接. 65 | 想要手动更新 WFBot, 直接输入 `sudo docker-compose pull wfbot && sudo docker-compose up -d` 66 | -------------------------------------------------------------------------------- /docs/faq.md: -------------------------------------------------------------------------------- 1 | # 常见问题 2 | 3 | ## Q: GitHub Commit 获取异常, 可能是请求次数过多 4 | 5 | 申请 Token 请查看 [这里](token.md) 6 | 我们不会上传你的个人 Token. 但请保管好运行这个机器人的电脑. 7 | -------------------------------------------------------------------------------- /docs/images/2021-01-20-22-31-26.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/2021-01-20-22-31-26.png -------------------------------------------------------------------------------- /docs/images/2021-01-20-22-36-23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/2021-01-20-22-36-23.png -------------------------------------------------------------------------------- /docs/images/2021-01-20-22-41-51.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/2021-01-20-22-41-51.png -------------------------------------------------------------------------------- /docs/images/2021-01-20-22-47-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/2021-01-20-22-47-24.png -------------------------------------------------------------------------------- /docs/images/2021-01-20-22-53-07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/2021-01-20-22-53-07.png -------------------------------------------------------------------------------- /docs/images/2021-01-20-22-56-39.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/2021-01-20-22-56-39.png -------------------------------------------------------------------------------- /docs/images/2021-01-20-23-07-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/2021-01-20-23-07-05.png -------------------------------------------------------------------------------- /docs/images/2021-01-20-23-11-14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/2021-01-20-23-11-14.png -------------------------------------------------------------------------------- /docs/images/2021-01-20-23-14-53.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/2021-01-20-23-14-53.png -------------------------------------------------------------------------------- /docs/images/2021-01-20-23-16-41.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/2021-01-20-23-16-41.png -------------------------------------------------------------------------------- /docs/images/2021-01-20-23-20-21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/2021-01-20-23-20-21.png -------------------------------------------------------------------------------- /docs/images/2021-01-20-23-36-00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/2021-01-20-23-36-00.png -------------------------------------------------------------------------------- /docs/images/MONEY.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/MONEY.png -------------------------------------------------------------------------------- /docs/images/QQ截图20211110000226.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/QQ截图20211110000226.png -------------------------------------------------------------------------------- /docs/images/QQ截图20211110001258.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/QQ截图20211110001258.png -------------------------------------------------------------------------------- /docs/images/QQ截图20211110001446.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/QQ截图20211110001446.png -------------------------------------------------------------------------------- /docs/images/QQ截图20211110001645.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/QQ截图20211110001645.png -------------------------------------------------------------------------------- /docs/images/QQ截图20220619213108.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/QQ截图20220619213108.png -------------------------------------------------------------------------------- /docs/images/QQ截图20220621224220.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/QQ截图20220621224220.png -------------------------------------------------------------------------------- /docs/images/QQ截图20220621224330.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/QQ截图20220621224330.png -------------------------------------------------------------------------------- /docs/images/QQ截图20220621231503.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/QQ截图20220621231503.png -------------------------------------------------------------------------------- /docs/images/QQ截图20220621232534.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/QQ截图20220621232534.png -------------------------------------------------------------------------------- /docs/images/QQ截图20220621234016.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/QQ截图20220621234016.png -------------------------------------------------------------------------------- /docs/images/QQ截图20220621235448.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/QQ截图20220621235448.png -------------------------------------------------------------------------------- /docs/images/QQ截图20220627214408.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/QQ截图20220627214408.png -------------------------------------------------------------------------------- /docs/images/QQ截图20220627214621.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/QQ截图20220627214621.png -------------------------------------------------------------------------------- /docs/images/QQ截图20220627214806.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/QQ截图20220627214806.png -------------------------------------------------------------------------------- /docs/images/QQ截图20220627214916.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/QQ截图20220627214916.png -------------------------------------------------------------------------------- /docs/images/QQ截图20220627215234.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/QQ截图20220627215234.png -------------------------------------------------------------------------------- /docs/images/jetbrains-variant-3-201x231.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/jetbrains-variant-3-201x231.png -------------------------------------------------------------------------------- /docs/images/processon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/processon.png -------------------------------------------------------------------------------- /docs/images/token1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/token1.png -------------------------------------------------------------------------------- /docs/images/token2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/token2.png -------------------------------------------------------------------------------- /docs/images/token3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TRKS-Team/WFBot/c25647a73b887ed2d13ee94fe562510f592fe7a1/docs/images/token3.png -------------------------------------------------------------------------------- /docs/plugin.md: -------------------------------------------------------------------------------- 1 | # 写一个插件 2 | 3 | 项目中的 WFBotExamplePlugin 提供了一个示例插件 对着改就行 4 | 更多信息请查看 Harmony 库的 [这里](https://github.com/pardeike/Harmony/wiki/Patching) 5 | -------------------------------------------------------------------------------- /docs/token.md: -------------------------------------------------------------------------------- 1 | # 如何填写 GitHub Token 2 | 3 | ## 申请一个 GitHub Token 4 | 5 | 打开[这里](https://github.com/settings/tokens/new) 6 | ![](images/token1.png) 7 | ![](images/token2.png) 8 | ![](images/token3.png) 9 | 10 | 下一步在机器人设置中填写即可 11 | --------------------------------------------------------------------------------