├── .deepsource.toml
├── .github
├── dependabot.yml
└── workflows
│ ├── AddCommentOnPR.yml
│ ├── Build&Deploy.yml
│ ├── DeployDev.yml
│ ├── DeployProd.yml
│ ├── Dotnet.yml
│ └── HandleDeployCommand.yml
├── .gitignore
├── .idea
└── .idea.DiscordBot
│ └── .idea
│ ├── .gitignore
│ ├── .name
│ ├── indexLayout.xml
│ ├── riderModule.iml
│ └── vcs.xml
├── .vscode
├── launch.json
├── settings.json
└── tasks.json
├── DiscordBot.sln
├── DiscordBot
├── .gitignore
├── AssemblyDefinition.cs
├── Attributes
│ ├── BotCommandChannelAttribute.cs
│ ├── HideFromHelpAttribute.cs
│ ├── IgnoreBotsAttribute.cs
│ ├── RoleAttributes.cs
│ └── ThreadAttributes.cs
├── Constants.cs
├── Data
│ └── UnityAPI.cs
├── DiscordBot.csproj
├── Domain
│ ├── ProfileData.cs
│ └── RectangleD.cs
├── Extensions
│ ├── ChannelExtensions.cs
│ ├── ContextExtension.cs
│ ├── DBConnectionExtension.cs
│ ├── DateExtensions.cs
│ ├── EmbedBuilderExtension.cs
│ ├── InternetExtensions.cs
│ ├── MessageExtensions.cs
│ ├── ReactMessageExtensions.cs
│ ├── StringExtensions.cs
│ ├── TaskExtensions.cs
│ ├── UserDBRepository.cs
│ ├── UserExtensions.cs
│ └── UserServiceExtensions.cs
├── GlobalSuppressions.cs
├── GlobalUsings.cs
├── Modules
│ ├── AirportModule.cs
│ ├── EmbedModule.cs
│ ├── ModerationModule.cs
│ ├── ReactionRoleModule.cs
│ ├── ReminderModule.cs
│ ├── TicketModule.cs
│ ├── TipModule.cs
│ ├── UnityHelp
│ │ ├── CannedInteractiveModule.cs
│ │ ├── CannedResponseModule.cs
│ │ ├── GeneralHelpModule.cs
│ │ ├── UnityHelpInteractiveModule.cs
│ │ └── UnityHelpModule.cs
│ ├── UserModule.cs
│ ├── UserSlashModule.cs
│ └── Weather
│ │ ├── WeatherContainers.cs
│ │ └── WeatherModule.cs
├── Program.cs
├── Properties
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── SERVER
│ ├── FAQs.json
│ ├── fonts
│ │ ├── Consolas.ttf
│ │ ├── ConsolasBold.ttf
│ │ ├── OpenSans-Regular.ttf
│ │ ├── OpenSansEmoji.ttf
│ │ └── georgia.ttf
│ ├── images
│ │ ├── ExampleExport.png
│ │ ├── Layout.txt
│ │ ├── background.png
│ │ ├── background.psd
│ │ ├── background_old.png
│ │ ├── default.png
│ │ ├── foreground.png
│ │ ├── foreground.psd
│ │ ├── levelupcard.png
│ │ ├── levelupcard.psd
│ │ ├── levelupcardbackground.png
│ │ └── triangle.png
│ └── skins
│ │ ├── background.png
│ │ ├── foreground.png
│ │ ├── skin.default.json
│ │ └── skin.json
├── Services
│ ├── AirportService.cs
│ ├── CommandHandlingService.cs
│ ├── CurrencyService.cs
│ ├── DatabaseService.cs
│ ├── FeedService.cs
│ ├── LoggingService.cs
│ ├── Moderation
│ │ └── IntroductionWatcherService.cs
│ ├── ModerationService.cs
│ ├── PublisherService.cs
│ ├── ReactRoleService.cs
│ ├── Recruitment
│ │ └── RecruitService.cs
│ ├── ReminderService.cs
│ ├── Tips
│ │ ├── Components
│ │ │ └── Tip.cs
│ │ └── TipService.cs
│ ├── UnityHelp
│ │ ├── CannedResponseService.cs
│ │ ├── Components
│ │ │ ├── HelpBotMessage.cs
│ │ │ └── ThreadContainer.cs
│ │ └── UnityHelpService.cs
│ ├── UpdateService.cs
│ ├── UserExtendedService.cs
│ ├── UserService.cs
│ └── WeatherService.cs
├── Settings
│ ├── Deserialized
│ │ ├── ReactionRole.cs
│ │ ├── Rules.cs
│ │ ├── Settings.cs
│ │ └── UserSettings.cs
│ ├── ReactionRoles.json
│ ├── Rules.json
│ ├── Settings.example.json
│ └── UserSettings.json
├── Skin
│ ├── AvatarBorderSkinModule.cs
│ ├── BaseTextSkinModule.cs
│ ├── CustomTextSkinModule.cs
│ ├── ISkinModule.cs
│ ├── KarmaPointsSkinModule.cs
│ ├── KarmaRankSkinModule.cs
│ ├── LevelSkinModule.cs
│ ├── RectangleD.cs
│ ├── RectangleSampleAvatarColorSkinModule.cs
│ ├── SkinData.cs
│ ├── SkinLayer.cs
│ ├── SkinModuleJsonConverter.cs
│ ├── TotalXpSkinModule.cs
│ ├── UsernameSkinModule.cs
│ ├── XpBarInfoSkinModule.cs
│ ├── XpBarSkinModule.cs
│ └── XpRankSkinModule.cs
└── Utils
│ ├── MathUtility.cs
│ ├── SerializeUtil.cs
│ ├── StringUtil.cs
│ ├── Utils.cs
│ └── WebUtil.cs
├── Dockerfile
├── LICENSE
├── NuGet.config
├── README.md
├── UpgradeLog.htm
└── docker-compose.yml
/.deepsource.toml:
--------------------------------------------------------------------------------
1 | version = 1
2 |
3 | [[analyzers]]
4 | name = "csharp"
5 | enabled = true
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for all configuration options:
4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5 |
6 | version: 2
7 | updates:
8 | - package-ecosystem: "nuget" # See documentation for possible values
9 | directory: "/" # Location of package manifests
10 | schedule:
11 | interval: "daily"
12 |
--------------------------------------------------------------------------------
/.github/workflows/AddCommentOnPR.yml:
--------------------------------------------------------------------------------
1 | name: Add Deployment Comment to PR
2 | "on":
3 | pull_request_target:
4 | types: [opened]
5 |
6 | jobs:
7 | add_deploy_comment:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - name: Add deployment comment
11 | uses: thollander/actions-comment-pull-request@v3
12 | with:
13 | message: |
14 | ### 🚀 Deploy this PR to an environment
15 |
16 | You can deploy this PR to either development or staging environment:
17 |
18 | - Comment `/deploy_dev` to deploy to the **development** environment
19 |
20 | Alternatively, you can:
21 | 1. Go to Actions tab
22 | 2. Click on "Manual Deploy to Firebase" workflow
23 | 3. Click the "Run workflow" button
24 | 4. Select branch: `${{ github.event.pull_request.head.ref }}`
25 | 5. Choose environment: DEV
26 | 6. Enter a deployment message
27 | 7. Click "Run workflow"
28 |
--------------------------------------------------------------------------------
/.github/workflows/Build&Deploy.yml:
--------------------------------------------------------------------------------
1 | name: Build & Deploy
2 |
3 | on:
4 | push:
5 | branches: [dev]
6 | workflow_call:
7 | inputs:
8 | env:
9 | required: true
10 | type: string
11 | workflow_dispatch:
12 | inputs:
13 | env:
14 | description: "Environment to deploy to"
15 | required: true
16 | default: "dev"
17 | type: choice
18 | options:
19 | - dev
20 |
21 | jobs:
22 | push_to_registry:
23 | name: Push Docker image to GitHub Packages
24 | runs-on: ubuntu-latest
25 |
26 | steps:
27 | - name: Login to GitHub Container Registry
28 | uses: docker/login-action@v1
29 | with:
30 | registry: ghcr.io
31 | username: ${{ github.repository_owner }}
32 | password: ${{ secrets.GITHUB_TOKEN }}
33 |
34 | - name: Build and push
35 | uses: docker/build-push-action@v2
36 | with:
37 | push: true
38 | tags: ghcr.io/unity-developer-community/udc-bot-dev:latest
39 |
40 | restart:
41 | name: Restart Bot
42 | needs: push_to_registry
43 | runs-on: ubuntu-latest
44 |
45 | environment:
46 | name: ${{ inputs.env }}
47 |
48 | steps:
49 | - name: Run commands in SSH
50 | uses: appleboy/ssh-action@master
51 | with:
52 | script: |
53 | cd ${{ secrets.SERVER_BUILD_DIR }}
54 | docker-compose pull
55 | docker-compose up -d
56 | host: ${{ secrets.SERVER_IP }}
57 | port: ${{ secrets.SERVER_PORT }}
58 | username: ${{ secrets.SERVER_USER }}
59 | password: ${{ secrets.SERVER_PASSWORD }}
60 |
61 | - name: Discord notification
62 | env:
63 | DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
64 | uses: Ilshidur/action-discord@master
65 | with:
66 | args: Bot has been deployment to Test Server successfully.
67 |
--------------------------------------------------------------------------------
/.github/workflows/DeployDev.yml:
--------------------------------------------------------------------------------
1 | name: Deploy to Test Server
2 |
3 | on:
4 | push:
5 | branches: [dev]
6 | workflow_dispatch:
7 |
8 | jobs:
9 | push_to_registry:
10 | name: Push Docker image to GitHub Packages
11 | runs-on: ubuntu-latest
12 |
13 | steps:
14 | - name: Login to GitHub Container Registry
15 | uses: docker/login-action@v1
16 | with:
17 | registry: ghcr.io
18 | username: ${{ github.repository_owner }}
19 | password: ${{ secrets.GITHUB_TOKEN }}
20 |
21 | - name: Build and push
22 | uses: docker/build-push-action@v2
23 | with:
24 | push: true
25 | tags: ghcr.io/unity-developer-community/udc-bot-dev:latest
26 |
27 | restart:
28 | name: Restart Bot
29 | needs: push_to_registry
30 | runs-on: ubuntu-latest
31 |
32 | environment:
33 | name: dev
34 |
35 | steps:
36 | - name: Run commands in SSH
37 | uses: appleboy/ssh-action@master
38 | with:
39 | script: |
40 | cd ${{ secrets.SERVER_BUILD_DIR }}
41 | docker-compose pull
42 | docker-compose up -d
43 | host: ${{ secrets.SERVER_IP }}
44 | port: ${{ secrets.SERVER_PORT }}
45 | username: ${{ secrets.SERVER_USER }}
46 | password: ${{ secrets.SERVER_PASSWORD }}
47 |
48 | - name: Discord notification
49 | env:
50 | DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
51 | uses: Ilshidur/action-discord@master
52 | with:
53 | args: Bot has been deployment to Test Server successfully.
54 |
--------------------------------------------------------------------------------
/.github/workflows/DeployProd.yml:
--------------------------------------------------------------------------------
1 | name: Deploy to UDC Server
2 |
3 | on:
4 | push:
5 | branches: [master]
6 | workflow_dispatch:
7 |
8 | jobs:
9 | push_to_registry:
10 | name: Push Docker image to GitHub Packages
11 | runs-on: ubuntu-latest
12 |
13 | steps:
14 | - name: Login to GitHub Container Registry
15 | uses: docker/login-action@v1
16 | with:
17 | registry: ghcr.io
18 | username: ${{ github.repository_owner }}
19 | password: ${{ secrets.GITHUB_TOKEN }}
20 |
21 | - name: Build and push
22 | uses: docker/build-push-action@v2
23 | with:
24 | push: true
25 | tags: ghcr.io/unity-developer-community/udc-bot:latest
26 |
27 | restart:
28 | name: Restart Bot
29 | needs: push_to_registry
30 | runs-on: ubuntu-latest
31 |
32 | environment:
33 | name: prod
34 |
35 | steps:
36 | - name: Run commands in SSH
37 | uses: appleboy/ssh-action@master
38 | with:
39 | script: |
40 | cd ${{ secrets.SERVER_BUILD_DIR }}
41 | docker-compose pull
42 | docker-compose up -d
43 | host: ${{ secrets.SERVER_IP }}
44 | port: ${{ secrets.SERVER_PORT }}
45 | username: ${{ secrets.SERVER_USER }}
46 | password: ${{ secrets.SERVER_PASSWORD }}
47 |
48 | - name: Discord notification
49 | env:
50 | DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
51 | uses: Ilshidur/action-discord@master
52 | with:
53 | args: Bot has been deployment to UDC Server successfully.
54 |
--------------------------------------------------------------------------------
/.github/workflows/Dotnet.yml:
--------------------------------------------------------------------------------
1 | name: .NET Build
2 |
3 | on:
4 | pull_request:
5 | branches: [master, dev]
6 |
7 | jobs:
8 | build:
9 | name: Build & Test
10 | runs-on: ubuntu-latest
11 |
12 | steps:
13 | - uses: actions/checkout@v2
14 |
15 | - name: Setup .NET Core
16 | uses: actions/setup-dotnet@v1
17 | with:
18 | dotnet-version: 6.0.x
19 |
20 | - name: Install dependencies
21 | run: dotnet restore
22 |
23 | - name: Build
24 | run: dotnet build --configuration Release --no-restore
25 |
--------------------------------------------------------------------------------
/.github/workflows/HandleDeployCommand.yml:
--------------------------------------------------------------------------------
1 | name: Handle Deploy Command
2 | "on":
3 | issue_comment:
4 | types: [created]
5 |
6 | jobs:
7 | process_comment:
8 | if: github.event.issue.pull_request && (github.event.comment.body == '/deploy_dev')
9 | runs-on: ubuntu-latest
10 | steps:
11 | - name: Determine deployment environment
12 | id: deployment_env
13 | run: |
14 | if [[ "${{ github.event.comment.body }}" == "/deploy_dev" ]]; then
15 | echo "env=dev" >> $GITHUB_OUTPUT
16 | echo "env_name=development" >> $GITHUB_OUTPUT
17 | fi
18 |
19 | - name: Get PR information
20 | id: pr_info
21 | uses: actions/github-script@v6
22 | with:
23 | github-token: ${{ secrets.GITHUB_TOKEN }}
24 | script: |
25 | const { owner, repo, number } = context.issue;
26 | const { data: pull } = await github.rest.pulls.get({
27 | owner,
28 | repo,
29 | pull_number: number
30 | });
31 |
32 | console.log("PR head branch:", pull.head.ref);
33 | console.log("PR head SHA:", pull.head.sha);
34 |
35 | core.setOutput("branch", pull.head.ref);
36 | core.setOutput("sha", pull.head.sha);
37 | core.setOutput("repo_name", pull.head.repo.full_name);
38 | return pull.head.ref;
39 |
40 | - name: Add reaction to comment
41 | uses: actions/github-script@v6
42 | with:
43 | github-token: ${{ secrets.GITHUB_TOKEN }}
44 | script: |
45 | github.rest.reactions.createForIssueComment({
46 | owner: context.repo.owner,
47 | repo: context.repo.repo,
48 | comment_id: context.payload.comment.id,
49 | content: 'rocket'
50 | });
51 |
52 | - name: Add deployment comment
53 | uses: actions/github-script@v6
54 | with:
55 | github-token: ${{ secrets.GITHUB_TOKEN }}
56 | script: |
57 | github.rest.issues.createComment({
58 | owner: context.repo.owner,
59 | repo: context.repo.repo,
60 | issue_number: context.issue.number,
61 | body: `🚀 Starting deployment of \`${{ steps.pr_info.outputs.repo_name }}:${{ steps.pr_info.outputs.branch }}\` to ${{ steps.deployment_env.outputs.env_name }}...`
62 | });
63 |
64 | - name: Generate unique branch name
65 | id: branch_name
66 | run: |
67 | TIMESTAMP=$(date +%s)
68 | UNIQUE_BRANCH="deploy-branch-${{ steps.pr_info.outputs.branch }}-$TIMESTAMP"
69 | echo "name=$UNIQUE_BRANCH" >> $GITHUB_OUTPUT
70 |
71 | - name: Checkout PR branch
72 | uses: actions/checkout@v3
73 | with:
74 | ref: ${{ steps.pr_info.outputs.sha }}
75 | repository: ${{ github.event.issue.pull_request.head.repo.full_name }}
76 | fetch-depth: 0
77 |
78 | - name: Create temporary branch
79 | run: |
80 | git checkout -b ${{ steps.branch_name.outputs.name }}
81 | git push origin ${{ steps.branch_name.outputs.name }}
82 |
83 | - name: Trigger deployment workflow
84 | uses: benc-uk/workflow-dispatch@v1
85 | with:
86 | workflow: Build & Deploy
87 | token: ${{ secrets.GITHUB_TOKEN }}
88 | ref: ${{ steps.branch_name.outputs.name }}
89 | inputs: |
90 | {
91 | "env": "${{ steps.deployment_env.outputs.env }}"
92 | }
93 |
94 | - name: Wait for deployment to start
95 | run: sleep 60 # Wait 60 seconds to ensure workflow has started
96 |
97 | - name: Clean up temporary branch
98 | if: always()
99 | run: |
100 | git push origin --delete ${{ steps.branch_name.outputs.name }} || true
101 |
--------------------------------------------------------------------------------
/.idea/.idea.DiscordBot/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Rider ignored files
5 | /contentModel.xml
6 | /modules.xml
7 | /.idea.DiscordBot.iml
8 | /projectSettingsUpdater.xml
9 | # Editor-based HTTP Client requests
10 | /httpRequests/
11 |
--------------------------------------------------------------------------------
/.idea/.idea.DiscordBot/.idea/.name:
--------------------------------------------------------------------------------
1 | DiscordBot
--------------------------------------------------------------------------------
/.idea/.idea.DiscordBot/.idea/indexLayout.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/.idea.DiscordBot/.idea/riderModule.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/.idea.DiscordBot/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to find out which attributes exist for C# debugging
3 | // Use hover for the description of the existing attributes
4 | // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "name": ".NET Core Launch (console)",
9 | "type": "coreclr",
10 | "request": "launch",
11 | "preLaunchTask": "build",
12 | // If you have changed target frameworks, make sure to update the program path.
13 | "program": "${workspaceFolder}/DiscordBot/bin/Debug/netcoreapp2.1/DiscordBot.dll",
14 | "args": [],
15 | "cwd": "${workspaceFolder}/DiscordBot",
16 | // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
17 | "console": "internalConsole",
18 | "stopAtEntry": false
19 | },
20 | {
21 | "name": ".NET Core Attach",
22 | "type": "coreclr",
23 | "request": "attach",
24 | "processId": "${command:pickProcess}"
25 | }
26 | ]
27 | }
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "sonarlint.connectedMode.project": {
3 | "connectionId": "unity-developer-community",
4 | "projectKey": "Unity-Developer-Community_UDC-Bot"
5 | }
6 | }
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "2.0.0",
3 | "tasks": [
4 | {
5 | "label": "build",
6 | "command": "dotnet",
7 | "type": "process",
8 | "args": [
9 | "build",
10 | "${workspaceFolder}/DiscordBot/DiscordBot.csproj",
11 | "/property:GenerateFullPaths=true",
12 | "/consoleloggerparameters:NoSummary"
13 | ],
14 | "problemMatcher": "$msCompile"
15 | },
16 | {
17 | "label": "publish",
18 | "command": "dotnet",
19 | "type": "process",
20 | "args": [
21 | "publish",
22 | "${workspaceFolder}/DiscordBot/DiscordBot.csproj",
23 | "/property:GenerateFullPaths=true",
24 | "/consoleloggerparameters:NoSummary"
25 | ],
26 | "problemMatcher": "$msCompile"
27 | },
28 | {
29 | "label": "watch",
30 | "command": "dotnet",
31 | "type": "process",
32 | "args": [
33 | "watch",
34 | "run",
35 | "${workspaceFolder}/DiscordBot/DiscordBot.csproj",
36 | "/property:GenerateFullPaths=true",
37 | "/consoleloggerparameters:NoSummary"
38 | ],
39 | "problemMatcher": "$msCompile"
40 | }
41 | ]
42 | }
--------------------------------------------------------------------------------
/DiscordBot.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.27421.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DiscordBot", "DiscordBot\DiscordBot.csproj", "{D021BBDF-02DC-4938-B035-75D7EDBDBAC2}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {D021BBDF-02DC-4938-B035-75D7EDBDBAC2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {D021BBDF-02DC-4938-B035-75D7EDBDBAC2}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {D021BBDF-02DC-4938-B035-75D7EDBDBAC2}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {D021BBDF-02DC-4938-B035-75D7EDBDBAC2}.Release|Any CPU.Build.0 = Release|Any CPU
18 | {8C06F0F6-2B30-4931-B93E-AE005F92C676}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19 | {8C06F0F6-2B30-4931-B93E-AE005F92C676}.Debug|Any CPU.Build.0 = Debug|Any CPU
20 | {8C06F0F6-2B30-4931-B93E-AE005F92C676}.Release|Any CPU.ActiveCfg = Release|Any CPU
21 | {8C06F0F6-2B30-4931-B93E-AE005F92C676}.Release|Any CPU.Build.0 = Release|Any CPU
22 | EndGlobalSection
23 | GlobalSection(SolutionProperties) = preSolution
24 | HideSolutionNode = FALSE
25 | EndGlobalSection
26 | GlobalSection(ExtensibilityGlobals) = postSolution
27 | SolutionGuid = {78E5BAD2-164B-46CF-8D4F-DDD5720A6DE0}
28 | EndGlobalSection
29 | EndGlobal
30 |
--------------------------------------------------------------------------------
/DiscordBot/.gitignore:
--------------------------------------------------------------------------------
1 | /Settings/Settings.json
2 | /SERVER/images/profiles/
3 | /SERVER/images/subtitles/
4 | /SERVER/log.txt
5 |
6 | SERVER/logXP.txt
7 | SERVER/scrap.py
8 | SERVER/botdata.json
9 | SERVER/unityapi.json
10 | SERVER/unitymanual.json
11 | SERVER/userdata.json
12 | SERVER/feeds.json
13 |
--------------------------------------------------------------------------------
/DiscordBot/AssemblyDefinition.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.CompilerServices;
2 |
3 | [assembly: InternalsVisibleTo("DiscordBot.Tests")]
--------------------------------------------------------------------------------
/DiscordBot/Attributes/BotCommandChannelAttribute.cs:
--------------------------------------------------------------------------------
1 | using Discord.Commands;
2 | using DiscordBot.Settings;
3 | using Microsoft.Extensions.DependencyInjection;
4 |
5 | namespace DiscordBot.Attributes;
6 |
7 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
8 | public class BotCommandChannelAttribute : PreconditionAttribute
9 | {
10 | public override async Task CheckPermissionsAsync(ICommandContext context, CommandInfo command, IServiceProvider services)
11 | {
12 | var settings = services.GetRequiredService();
13 |
14 | if (context.Channel.Id == settings.BotCommandsChannel.Id)
15 | {
16 | return await Task.FromResult(PreconditionResult.FromSuccess());
17 | }
18 |
19 | Task task = context.Message.DeleteAfterSeconds(seconds: 10);
20 | return await Task.FromResult(PreconditionResult.FromError($"This command can only be used in <#{settings.BotCommandsChannel.Id.ToString()}>."));
21 | }
22 | }
--------------------------------------------------------------------------------
/DiscordBot/Attributes/HideFromHelpAttribute.cs:
--------------------------------------------------------------------------------
1 | namespace DiscordBot.Attributes;
2 |
3 | public class HideFromHelpAttribute : Attribute
4 | {
5 | }
--------------------------------------------------------------------------------
/DiscordBot/Attributes/IgnoreBotsAttribute.cs:
--------------------------------------------------------------------------------
1 | using Discord.Commands;
2 |
3 | namespace DiscordBot.Attributes;
4 |
5 | ///
6 | /// Simple attribute, if the command is used by a bot, it escapes early and doesn't run the command.
7 | ///
8 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
9 | public class IgnoreBotsAttribute : PreconditionAttribute
10 | {
11 | public override Task CheckPermissionsAsync(ICommandContext context, CommandInfo command, IServiceProvider services)
12 | {
13 | if (context.Message.Author.IsBot)
14 | {
15 | return Task.FromResult(PreconditionResult.FromError(string.Empty));
16 | }
17 |
18 | return Task.FromResult(PreconditionResult.FromSuccess());
19 | }
20 | }
21 |
22 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
23 | public class IgnoreBotsAndWebhooksAttribute : PreconditionAttribute
24 | {
25 | public override Task CheckPermissionsAsync(ICommandContext context, CommandInfo command, IServiceProvider services)
26 | {
27 | if (context.Message.Author.IsBot || context.Message.Author.IsWebhook)
28 | {
29 | return Task.FromResult(PreconditionResult.FromError(string.Empty));
30 | }
31 |
32 | return Task.FromResult(PreconditionResult.FromSuccess());
33 | }
34 | }
35 |
36 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
37 | public class IgnoreWebhooksAttribute : PreconditionAttribute
38 | {
39 | public override Task CheckPermissionsAsync(ICommandContext context, CommandInfo command, IServiceProvider services)
40 | {
41 | if (context.Message.Author.IsWebhook)
42 | {
43 | return Task.FromResult(PreconditionResult.FromError(string.Empty));
44 | }
45 |
46 | return Task.FromResult(PreconditionResult.FromSuccess());
47 | }
48 | }
--------------------------------------------------------------------------------
/DiscordBot/Attributes/RoleAttributes.cs:
--------------------------------------------------------------------------------
1 | using Discord.Commands;
2 | using Discord.WebSocket;
3 | using DiscordBot.Settings;
4 | using Microsoft.Extensions.DependencyInjection;
5 |
6 | namespace DiscordBot.Attributes;
7 |
8 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
9 | public class RequireAdminAttribute : PreconditionAttribute
10 | {
11 | public override Task CheckPermissionsAsync(ICommandContext context, CommandInfo command, IServiceProvider services)
12 | {
13 | var user = (SocketGuildUser)context.Message.Author;
14 |
15 | if (user.Roles.Any(x => x.Permissions.Administrator)) return Task.FromResult(PreconditionResult.FromSuccess());
16 | return Task.FromResult(PreconditionResult.FromError(user + " attempted to use admin only command!"));
17 | }
18 | }
19 |
20 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
21 | public class RequireModeratorAttribute : PreconditionAttribute
22 | {
23 | public override Task CheckPermissionsAsync(ICommandContext context, CommandInfo command, IServiceProvider services)
24 | {
25 | var user = (SocketGuildUser)context.Message.Author;
26 | var settings = services.GetRequiredService();
27 |
28 | if (user.Roles.Any(x => x.Id == settings.ModeratorRoleId)) return Task.FromResult(PreconditionResult.FromSuccess());
29 | return Task.FromResult(PreconditionResult.FromError(user + " attempted to use a moderator command!"));
30 | }
31 | }
--------------------------------------------------------------------------------
/DiscordBot/Attributes/ThreadAttributes.cs:
--------------------------------------------------------------------------------
1 | using Discord.Commands;
2 | using Discord.WebSocket;
3 | using DiscordBot.Settings;
4 | using Microsoft.Extensions.DependencyInjection;
5 |
6 | namespace DiscordBot.Attributes;
7 |
8 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
9 | public class RequireThreadAttribute : PreconditionAttribute
10 | {
11 | protected SocketThreadChannel _currentThread;
12 |
13 | public override async Task CheckPermissionsAsync(ICommandContext context, CommandInfo command, IServiceProvider services)
14 | {
15 | this._currentThread = context.Message.Channel as SocketThreadChannel;
16 | if (this._currentThread != null) return await Task.FromResult(PreconditionResult.FromSuccess());
17 |
18 | Task task = context.Message.DeleteAfterSeconds(seconds: 10);
19 | return await Task.FromResult(PreconditionResult.FromError("This command can only be used in a thread."));
20 | }
21 | }
22 |
23 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
24 | public class RequireAutoThreadAttribute : RequireThreadAttribute
25 | {
26 | protected AutoThreadChannel _autoThreadChannel;
27 |
28 | public override async Task CheckPermissionsAsync(ICommandContext context, CommandInfo command, IServiceProvider services)
29 | {
30 | var res = await base.CheckPermissionsAsync(context, command, services);
31 | if (!res.IsSuccess) return res;
32 |
33 | var settings = services.GetRequiredService();
34 | this._autoThreadChannel = settings.AutoThreadChannels.Find(x => this._currentThread.ParentChannel.Id == x.Id);
35 | if (this._autoThreadChannel != null) return await Task.FromResult(PreconditionResult.FromSuccess());
36 |
37 | Task task = context.Message.DeleteAfterSeconds(seconds: 10);
38 | return await Task.FromResult(PreconditionResult.FromError("This command can only be used in a thread created automatically."));
39 |
40 | }
41 | }
42 |
43 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
44 | public class RequireArchivableAutoThreadAttribute : RequireAutoThreadAttribute
45 | {
46 | public override async Task CheckPermissionsAsync(ICommandContext context, CommandInfo command, IServiceProvider services)
47 | {
48 | var res = await base.CheckPermissionsAsync(context, command, services);
49 | if (!res.IsSuccess) return res;
50 |
51 | if (this._autoThreadChannel.CanArchive) return await Task.FromResult(PreconditionResult.FromSuccess());
52 |
53 | Task task = context.Message.DeleteAfterSeconds(seconds: 10);
54 | return await Task.FromResult(PreconditionResult.FromError("This command cannot be used in a this thread."));
55 | }
56 | }
57 |
58 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
59 | public class RequireDeletableAutoThreadAttribute : RequireAutoThreadAttribute
60 | {
61 | public override async Task CheckPermissionsAsync(ICommandContext context, CommandInfo command, IServiceProvider services)
62 | {
63 | var res = await base.CheckPermissionsAsync(context, command, services);
64 | if (!res.IsSuccess) return res;
65 |
66 | if (this._autoThreadChannel.CanDelete) return await Task.FromResult(PreconditionResult.FromSuccess());
67 |
68 | Task task = context.Message.DeleteAfterSeconds(seconds: 10);
69 | return await Task.FromResult(PreconditionResult.FromError("This command cannot be used in a this thread."));
70 | }
71 | }
72 |
73 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
74 | public class RequireAutoThreadAuthorAttribute : RequireAutoThreadAttribute
75 | {
76 | public override async Task CheckPermissionsAsync(ICommandContext context, CommandInfo command, IServiceProvider services)
77 | {
78 | var res = await base.CheckPermissionsAsync(context, command, services);
79 | if (!res.IsSuccess) return res;
80 |
81 | var messages = await this._currentThread.GetPinnedMessagesAsync();
82 | var firstMessage = messages.LastOrDefault();
83 | if (firstMessage != null)
84 | {
85 | var user = (SocketGuildUser)context.Message.Author;
86 | if (firstMessage.MentionedUsers.Any(x => x.Id == context.User.Id))
87 | return await Task.FromResult(PreconditionResult.FromSuccess());
88 | }
89 |
90 | Task task = context.Message.DeleteAfterSeconds(seconds: 10);
91 | return await Task.FromResult(PreconditionResult.FromError("This command can only be used by the thread author."));
92 | }
93 | }
--------------------------------------------------------------------------------
/DiscordBot/Constants.cs:
--------------------------------------------------------------------------------
1 | namespace DiscordBot;
2 |
3 | public static class Constants
4 | {
5 | public const int MaxLengthChannelMessage = 2000;
6 | }
--------------------------------------------------------------------------------
/DiscordBot/Data/UnityAPI.cs:
--------------------------------------------------------------------------------
1 | namespace DiscordBot.Data;
2 |
3 | public class Rating
4 | {
5 | public object Count { get; set; }
6 | public int Average { get; set; }
7 | }
8 |
9 | public class Kategory
10 | {
11 | public string Slug { get; set; }
12 | public string Name { get; set; }
13 | public string Id { get; set; }
14 | }
15 |
16 | public class Category
17 | {
18 | public string TreeId { get; set; }
19 | public string LabelEnglish { get; set; }
20 | public string Label { get; set; }
21 | public string Id { get; set; }
22 | public string Multiple { get; set; }
23 | }
24 |
25 | public class Publisher
26 | {
27 | public string LabelEnglish { get; set; }
28 | public string Url { get; set; }
29 | public string Slug { get; set; }
30 | public string Label { get; set; }
31 | public string Id { get; set; }
32 | public string SupportEmail { get; set; }
33 | public object SupportUrl { get; set; }
34 | }
35 |
36 | public class Link
37 | {
38 | public string Type { get; set; }
39 | public string Id { get; set; }
40 | }
41 |
42 | public class List
43 | {
44 | public string Slug { get; set; }
45 | public string SlugV2 { get; set; }
46 | public string Name { get; set; }
47 | public object Overlay { get; set; }
48 | }
49 |
50 | public class Flags
51 | {
52 | }
53 |
54 | public class Image
55 | {
56 | public string Link { get; set; }
57 | public string Width { get; set; }
58 | public string Name { get; set; }
59 | public string Type { get; set; }
60 | public string Height { get; set; }
61 | public string Thumb { get; set; }
62 | }
63 |
64 | public class Keyimage
65 | {
66 | public string Small { get; set; }
67 | public string Big { get; set; }
68 | public object SmallLegacy { get; set; }
69 | public object Facebook { get; set; }
70 | public object BigLegacy { get; set; }
71 | public string Icon { get; set; }
72 | public string Icon75 { get; set; }
73 | public string Icon25 { get; set; }
74 | }
75 |
76 | public class Daily
77 | {
78 | public string Icon { get; set; }
79 | public Rating Rating { get; set; }
80 | public int Remaining { get; set; }
81 | public Kategory Kategory { get; set; }
82 | public string PackageVersionId { get; set; }
83 | public string Slug { get; set; }
84 | public Category Category { get; set; }
85 | public string Hotness { get; set; }
86 | public string Id { get; set; }
87 | public Publisher Publisher { get; set; }
88 | public List