├── .gitattributes
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ ├── new-feature---task.md
│ └── question.md
└── workflows
│ └── cicd.yml
├── .gitignore
├── .vscode
├── launch.json
├── settings.json
└── tasks.json
├── LICENSE
├── PRIVACY_POLICY.md
├── azure-pipelines.yml
├── docs
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── PULL_REQUEST_TEMPLATE.md
├── README.md
└── img
│ ├── apps.png
│ ├── github-download.png
│ ├── vsdeps-asp.png
│ ├── vsdeps-base.png
│ └── vsdeps-win.png
└── src
├── .ruleset
├── Directory.Build.props
├── Miunie.Core
├── Attributes
│ └── ServiceAttribute.cs
├── Commands
│ ├── CommandPipelineStep.cs
│ ├── CommandProcessor.cs
│ ├── CommandProcessorInput.cs
│ ├── ICommandPipelineStep.cs
│ ├── ICommandProcessor.cs
│ ├── IMiunieServiceCollection.cs
│ ├── MiunieCommandContext.cs
│ ├── MiunieServiceCommand.cs
│ └── PipelineSteps
│ │ ├── PreconditionCheckStep.cs
│ │ └── ServiceLocationStep.cs
├── Configuration
│ ├── BotConfiguration.cs
│ └── IBotConfiguration.cs
├── Discord
│ ├── IDiscordConnection.cs
│ ├── IDiscordGuilds.cs
│ ├── IDiscordImpersonation.cs
│ └── IDiscordMessages.cs
├── Entities
│ ├── ConnectionState.cs
│ ├── Discord
│ │ ├── MiunieChannel.cs
│ │ ├── MiunieGuild.cs
│ │ ├── MiunieRole.cs
│ │ └── MiunieUser.cs
│ ├── PhraseKey.cs
│ ├── Reputation.cs
│ ├── ReputationEntry.cs
│ ├── ReputationType.cs
│ ├── ServiceType.cs
│ └── Views
│ │ ├── GuildView.cs
│ │ ├── MessageView.cs
│ │ └── TextChannelView.cs
├── Events
│ └── MessageReceivedEventArgs.cs
├── Infrastructure
│ ├── IDateTime.cs
│ └── IFileSystem.cs
├── Json
│ └── IJsonConverter.cs
├── Logging
│ ├── ILogReader.cs
│ └── ILogWriter.cs
├── Miunie.Core.csproj
├── MiunieBot.cs
├── Providers
│ ├── ILanguageProvider.cs
│ ├── IMiunieUserProvider.cs
│ ├── ITimeManipulationProvider.cs
│ ├── IUserReputationProvider.cs
│ ├── LanguageProvider.cs
│ ├── MiunieUserProvider.cs
│ ├── TimeManipulationProvider.cs
│ └── UserReputationProvider.cs
├── Services
│ ├── MiscService.cs
│ ├── PrivacyService.cs
│ ├── ProfileService.cs
│ ├── RemoteRepositoryService.cs
│ └── TimeService.cs
├── Storage
│ └── IPersistentStorage.cs
├── Strings.Designer.cs
└── Strings.resx
├── Miunie.Discord
├── Adapters
│ ├── DiscordGuildsAdapter.cs
│ └── DiscordMessagesAdapter.cs
├── CommandHandler.cs
├── CommandModules
│ ├── MiscCommands.cs
│ ├── PrivacyCommand.cs
│ ├── ProfileCommand.cs
│ ├── RemoteRepositoryCommand.cs
│ └── TimeCommand.cs
├── Convertors
│ ├── EntityConvertor.cs
│ ├── MiunieChannelConvertor.cs
│ ├── MiunieGuildConvertor.cs
│ ├── MiunieRoleConvertor.cs
│ └── MiunieUserConverter.cs
├── Embeds
│ ├── EmbedConstructor.cs
│ └── Paginator.cs
├── IDiscord.cs
├── Impersonation.cs
├── Logging
│ └── DiscordLogger.cs
├── Miunie.Discord.csproj
├── MiunieDiscord.cs
├── MiunieDiscordClient.cs
└── TypeReaders
│ └── MiunieUserTypeReader.cs
├── Miunie.Infrastructure
├── Json
│ └── JsonConverter.cs
├── LiteDbStorage
│ └── PersistentStorage.cs
├── Logging
│ ├── ConsoleLogger.cs
│ └── InMemoryLogger.cs
├── Miunie.Infrastructure.csproj
└── OS
│ ├── SystemDateTime.cs
│ └── SystemFileSystem.cs
├── Miunie.InversionOfControl
├── Container.cs
└── Miunie.InversionOfControl.csproj
├── Miunie.Tests
├── Commands
│ ├── MessagePreconditonTests.cs
│ └── ServiceLocatorTests.cs
├── Data
│ └── DummyMiunieUsers.cs
├── Miunie.Tests.csproj
├── MiunieDiscordClientTests.cs
├── MiunieDiscordTests.cs
├── Providers
│ ├── MiunieUserProviderTests.cs
│ ├── TimeManipulationProviderTests.cs
│ └── UserReputationProviderTests.cs
└── Services
│ ├── ProfileServiceReputationTests.cs
│ ├── ProfileServiceTests.cs
│ ├── TimeServiceTests.cs
│ └── YesNoServiceTests.cs
├── Miunie.sln
└── stylecop.json
/.gitattributes:
--------------------------------------------------------------------------------
1 | **/wwwroot/lib/* linguist-vendored
2 | lib/* linguist-vendored
3 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/new-feature---task.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: New Feature / Task
3 | about: For new issues regarding a new feature or a task
4 | title: "\U0001F49C - Feature Name"
5 | labels: up-for-grabs
6 | assignees: ''
7 |
8 | ---
9 |
10 | > 🟥🟩 **WINDOWS 10** - Version 1903+ is required for the UWP UI.
11 | > 🟦🟨 [How to setup UWP](https://docs.microsoft.com/en-us/windows/uwp/get-started/get-set-up)
12 |
13 | # Remove the above notice if the issue is not about UWP
14 |
15 | > 🌻 This issue is perfect for developers who are new to Miunie!
16 |
17 | ## Summary
18 |
19 | ## How to implement
20 |
21 | ## Interested? 😊
22 |
23 | If you'd like to help us by solving this issue, just say so in the comments. ❤️
24 | And don't shy away from asking any kind of question you might have.
25 |
26 | Should you have any questions at all, feel free to contact either me (@petrspelos) or @DraxCodes on our Discord server:
27 |
28 | [](https://discord.gg/cGhEZuk)
29 |
30 | _And of course, thank you so much for contributing! 🎉 It's because of amazing people like yourself that Miunie exists._
31 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/question.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Question
3 | about: Have a question? Feel free to ask.
4 | title: ''
5 | labels: question
6 | assignees: ''
7 |
8 | ---
9 |
10 | ## Summary
11 |
12 | _Describe what your question is about._ 😊
13 |
--------------------------------------------------------------------------------
/.github/workflows/cicd.yml:
--------------------------------------------------------------------------------
1 | name: Build and Test
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | pull_request:
8 | branches:
9 | - master
10 |
11 | jobs:
12 | multiplatform_build:
13 | runs-on: ${{ matrix.os }}
14 | strategy:
15 | matrix:
16 | os: [ubuntu-latest, windows-latest, macOS-latest]
17 | steps:
18 | - uses: actions/checkout@v2
19 | - name: Setup .NET Core
20 | uses: actions/setup-dotnet@v1
21 | with:
22 | dotnet-version: 3.1.101
23 | - name: Build with dotnet
24 | run: dotnet build src/Miunie.sln --configuration Release
25 | - name: Run tests
26 | run: dotnet test src/Miunie.Tests
27 |
--------------------------------------------------------------------------------
/.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}/src/Miunie.Avalonia/bin/Debug/netcoreapp3.0/Miunie.Avalonia.dll",
14 | "args": [],
15 | "cwd": "${workspaceFolder}/src/Miunie.Avalonia",
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 | "workbench.colorCustomizations": {
3 | "titleBar.activeBackground": "#b92a82",
4 | "titleBar.inactiveBackground": "#81275f",
5 | "titleBar.activeForeground": "#ffffff"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/.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}/src/Miunie.Avalonia/Miunie.Avalonia.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}/src/Miunie.Avalonia/Miunie.Avalonia.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}/src/Miunie.Avalonia/Miunie.Avalonia.csproj",
36 | "/property:GenerateFullPaths=true",
37 | "/consoleloggerparameters:NoSummary"
38 | ],
39 | "problemMatcher": "$msCompile"
40 | }
41 | ]
42 | }
--------------------------------------------------------------------------------
/PRIVACY_POLICY.md:
--------------------------------------------------------------------------------
1 | # Privacy Policy
2 |
3 | Your privacy is important to us. It is Control.NET policy to respect your privacy regarding any information we may collect from you through our app, Miunie.
4 |
5 | We only ask for personal information when we truly need it to provide a service to you. We collect it on your local machine by fair and lawful means, with your knowledge and consent. We also let you know why we’re collecting it and how it will be used. Your data will only be sent to Discord and will never be collected by us.
6 |
7 | We only retain collected information on your machine for as long as necessary to provide you with your requested service. What data we store, we’ll protect within commercially acceptable means to prevent loss and theft, as well as unauthorised access, disclosure, copying, use or modification.
8 |
9 | We cannot share any personally identifying information publicly or with third-parties, since all of your data is on your machine and is only accessed for ease of use purposes by the locally running application.
10 |
11 | Our app may link to external sites that are not operated by us. Please be aware that we have no control over the content and practices of these sites, and cannot accept responsibility or liability for their respective privacy policies.
12 |
13 | You are free to refuse our request for your personal information, with the understanding that we may be unable to provide you with some of your desired services.
14 |
15 | Your continued use of our application will be regarded as acceptance of our practices around privacy and personal information. If you have any questions about how we handle user data and personal information, feel free to contact us.
16 |
17 | This policy is effective as of 3 March 2020.
18 |
--------------------------------------------------------------------------------
/azure-pipelines.yml:
--------------------------------------------------------------------------------
1 | # ASP.NET Core / .NET Core app
2 | # Build and test .NET Core projects.
3 | # Add steps that run tests, create a NuGet package, deploy, and more:
4 | # https://docs.microsoft.com/azure/devops/pipelines/languages/dotnet-core
5 |
6 | trigger:
7 | - master
8 |
9 | pool:
10 | vmImage: 'windows-2019'
11 |
12 | variables:
13 | buildConfiguration: 'Release'
14 |
15 | steps:
16 | - script: dotnet build src/ --configuration $(buildConfiguration)
17 | displayName: 'dotnet build $(buildConfiguration)'
18 | - task: DotNetCoreCLI@2
19 | inputs:
20 | command: test
21 | projects: '**/*Tests/*.csproj'
22 | arguments: '--configuration $(buildConfiguration)'
--------------------------------------------------------------------------------
/docs/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at our discord server [here](https://discord.gg/cGhEZuk) . All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/docs/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
2 | ## Related Issue
3 |
4 | _What issue does this pull request relate to? If none, please create the issue first._ :+1:
5 |
6 | Fixes # (issue number)
7 |
8 | ## Changes
9 | _Please describe your changes._
10 |
11 | ## Expected Feedback
12 | _Please describe what feedback you're looking for. This is a good place to mention your code is perhaps a Work In Progress or a Draft and might change._
13 |
14 | ## Co-Authors
15 | _Please add any co-authors that may have helped with your PR._
16 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | **🧡 Miunie is built by these wonderful people:**
18 |
19 | [](https://sourcerer.io/fame/petrspelos/discord-bot-tutorial/Miunie/links/0)[](https://sourcerer.io/fame/petrspelos/discord-bot-tutorial/Miunie/links/1)[](https://sourcerer.io/fame/petrspelos/discord-bot-tutorial/Miunie/links/2)[](https://sourcerer.io/fame/petrspelos/discord-bot-tutorial/Miunie/links/3)[](https://sourcerer.io/fame/petrspelos/discord-bot-tutorial/Miunie/links/4)[](https://sourcerer.io/fame/petrspelos/discord-bot-tutorial/Miunie/links/5)[](https://sourcerer.io/fame/petrspelos/discord-bot-tutorial/Miunie/links/6)[](https://sourcerer.io/fame/petrspelos/discord-bot-tutorial/Miunie/links/7)
20 |
21 | **💚 Special thanks to:**
22 |
23 | - 🎨 **[wayanfa](https://www.instagram.com/haelequin_55/)** for drawing Miunie.
24 |
25 | **Miunie Core** is a Discord bot framework targetting [.NET Standard](https://docs.microsoft.com/en-us/dotnet/standard/net-standard) 2.0.
26 |
27 | We use Miunie Core in the following front-end projects:
28 |
29 | [](https://github.com/control-net/miunie-uwp)
30 | [](https://github.com/control-net/miunie-console)
31 | [](https://github.com/control-net/miunie-avalonia)
32 |
33 | 
34 |
35 | ## [🔗 Learn more about Miunie...](https://github.com/control-net/Miunie/wiki/About-Miunie)
36 |
37 | ## Useful links
38 |
39 | ## [🔗 How to help the project](https://github.com/control-net/Miunie/wiki/How-to-help)
40 |
41 | ## [🔗 How to build Miunie from source](https://github.com/control-net/Miunie/wiki/Getting-started-with-Miunie)
42 |
43 | ## [🔗 How to deploy Miunie](https://github.com/control-net/Miunie/wiki/Deploying-Miunie)
44 |
45 | ## Built With
46 |
47 | - .NET Standard 2.0
48 | - [.Net Core 3.1](https://dotnet.microsoft.com/download/dotnet-core)
49 | - [Discord.NET](https://github.com/discord-net/Discord.Net) - Discord API wrapper library
50 | - 💙 Collaborative spirit
51 | - ❤️ Passion
52 |
53 | ## Authors
54 |
55 | - Petr Sedláček - Initial work - [petrspelos](https://github.com/petrspelos)
56 |
57 | See also the list of [contributors](https://github.com/control-net/Miunie/graphs/contributors) who participated in this project.
58 |
59 | ## License
60 |
61 | This project is licensed under the GPL-3.0 License - see the [LICENSE](https://github.com/control-net/Miunie/blob/master/LICENSE) file for details
62 |
--------------------------------------------------------------------------------
/docs/img/apps.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/control-net/Miunie/1cc652436fb42dca7659497600e350f3981461a8/docs/img/apps.png
--------------------------------------------------------------------------------
/docs/img/github-download.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/control-net/Miunie/1cc652436fb42dca7659497600e350f3981461a8/docs/img/github-download.png
--------------------------------------------------------------------------------
/docs/img/vsdeps-asp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/control-net/Miunie/1cc652436fb42dca7659497600e350f3981461a8/docs/img/vsdeps-asp.png
--------------------------------------------------------------------------------
/docs/img/vsdeps-base.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/control-net/Miunie/1cc652436fb42dca7659497600e350f3981461a8/docs/img/vsdeps-base.png
--------------------------------------------------------------------------------
/docs/img/vsdeps-win.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/control-net/Miunie/1cc652436fb42dca7659497600e350f3981461a8/docs/img/vsdeps-win.png
--------------------------------------------------------------------------------
/src/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | 8.0
4 | ../.ruleset
5 |
6 |
7 |
8 | runtime; build; native; contentfiles; analyzers; buildtransitive
9 | all
10 |
11 |
12 | stylecop.json
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Attributes/ServiceAttribute.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Entities;
17 | using System;
18 |
19 | namespace Miunie.Core.Attributes
20 | {
21 | public sealed class ServiceAttribute : Attribute
22 | {
23 | public ServiceAttribute(ServiceType serviceType = ServiceType.SINGLETON)
24 | {
25 | ServiceType = serviceType;
26 | }
27 |
28 | public ServiceType ServiceType { get; private set; }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Commands/CommandPipelineStep.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using System.Threading.Tasks;
17 |
18 | namespace Miunie.Core.Commands
19 | {
20 | public abstract class CommandPipelineStep : ICommandPipelineStep
21 | {
22 | public CommandPipelineStep(ICommandPipelineStep nextStep)
23 | {
24 | NextStep = nextStep;
25 | }
26 |
27 | protected ICommandPipelineStep NextStep { get; }
28 |
29 | public abstract Task ProcessAsync(CommandProcessorInput input);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Commands/CommandProcessor.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using System.Threading.Tasks;
17 |
18 | namespace Miunie.Core.Commands
19 | {
20 | public class CommandProcessor : ICommandProcessor
21 | {
22 | public Task ProcessAsync(CommandProcessorInput input)
23 | {
24 | return Task.CompletedTask;
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Commands/CommandProcessorInput.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using System.Collections.Generic;
17 |
18 | namespace Miunie.Core.Commands
19 | {
20 | public class CommandProcessorInput
21 | {
22 | public string Message { get; set; }
23 |
24 | ///
25 | /// Gets or sets the position in the Message where the prefix ends.
26 | ///
27 | public uint PrefixOffset { get; set; }
28 |
29 | public ulong MessageId { get; set; }
30 |
31 | public ulong UserId { get; set; }
32 |
33 | public ulong ChannelId { get; set; }
34 |
35 | public ulong? GuildId { get; set; }
36 |
37 | public IEnumerable TargetedCommands { get; set; }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Commands/ICommandPipelineStep.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using System.Threading.Tasks;
17 |
18 | namespace Miunie.Core.Commands
19 | {
20 | public interface ICommandPipelineStep
21 | {
22 | Task ProcessAsync(CommandProcessorInput input);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Commands/ICommandProcessor.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using System.Threading.Tasks;
17 |
18 | namespace Miunie.Core.Commands
19 | {
20 | public interface ICommandProcessor
21 | {
22 | Task ProcessAsync(CommandProcessorInput input);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Commands/IMiunieServiceCollection.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using System.Collections.Generic;
17 |
18 | namespace Miunie.Core.Commands
19 | {
20 | public interface IMiunieServiceCollection
21 | {
22 | IEnumerable GetAvailableCommands();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Commands/MiunieCommandContext.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | namespace Miunie.Core.Commands
17 | {
18 | public class MiunieCommandContext
19 | {
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Commands/MiunieServiceCommand.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | namespace Miunie.Core.Commands
17 | {
18 | public class MiunieServiceCommand
19 | {
20 | public string Prompt { get; set; }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Commands/PipelineSteps/PreconditionCheckStep.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Configuration;
17 | using System.Threading.Tasks;
18 |
19 | namespace Miunie.Core.Commands.PipelineSteps
20 | {
21 | public class PreconditionCheckStep : CommandPipelineStep
22 | {
23 | private readonly IBotConfiguration _config;
24 |
25 | public PreconditionCheckStep(ICommandPipelineStep step, IBotConfiguration config)
26 | : base(step)
27 | {
28 | _config = config;
29 | }
30 |
31 | public override Task ProcessAsync(CommandProcessorInput input)
32 | {
33 | if (!_config.PrefixIsSet)
34 | {
35 | return NextStep.ProcessAsync(input);
36 | }
37 |
38 | if (input.Message.StartsWith(_config.CommandPrefix))
39 | {
40 | input.PrefixOffset = (uint)_config.CommandPrefix.Length;
41 | return NextStep.ProcessAsync(input);
42 | }
43 |
44 | return Task.CompletedTask;
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Commands/PipelineSteps/ServiceLocationStep.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Logging;
17 | using System.Linq;
18 | using System.Threading.Tasks;
19 |
20 | namespace Miunie.Core.Commands.PipelineSteps
21 | {
22 | public class ServiceLocationStep : CommandPipelineStep
23 | {
24 | private readonly IMiunieServiceCollection _serviceCollection;
25 | private readonly ILogWriter _logWriter;
26 |
27 | public ServiceLocationStep(ICommandPipelineStep step, IMiunieServiceCollection serviceCollection, ILogWriter logWriter)
28 | : base(step)
29 | {
30 | _serviceCollection = serviceCollection;
31 | _logWriter = logWriter;
32 | }
33 |
34 | public override Task ProcessAsync(CommandProcessorInput input)
35 | {
36 | var commands = _serviceCollection.GetAvailableCommands();
37 |
38 | if (commands is null || !commands.Any())
39 | {
40 | _logWriter.Log("Service Location did not get any available commands.");
41 | return Task.CompletedTask;
42 | }
43 |
44 | var prompt = input.Message.Substring((int)input.PrefixOffset).Trim();
45 |
46 | input.TargetedCommands = commands.Where(c => prompt.StartsWith(c.Prompt));
47 | return NextStep.ProcessAsync(input);
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Configuration/BotConfiguration.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | namespace Miunie.Core.Configuration
17 | {
18 | public class BotConfiguration : IBotConfiguration
19 | {
20 | public string DiscordToken { get; set; }
21 |
22 | public bool CommandsEnabled { get; set; } = true;
23 |
24 | public string CommandPrefix { get; set; }
25 |
26 | public bool PrefixIsSet => !string.IsNullOrWhiteSpace(CommandPrefix);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Configuration/IBotConfiguration.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | namespace Miunie.Core.Configuration
17 | {
18 | public interface IBotConfiguration
19 | {
20 | bool CommandsEnabled { get; set; }
21 |
22 | string DiscordToken { get; set; }
23 |
24 | string CommandPrefix { get; set; }
25 |
26 | bool PrefixIsSet { get; }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Discord/IDiscordConnection.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Entities;
17 | using Miunie.Core.Entities.Discord;
18 | using System;
19 | using System.Threading;
20 | using System.Threading.Tasks;
21 |
22 | namespace Miunie.Core.Discord
23 | {
24 | public interface IDiscordConnection
25 | {
26 | event EventHandler ConnectionChanged;
27 |
28 | ConnectionState ConnectionState { get; }
29 |
30 | bool UserIsMiunie(MiunieUser user);
31 |
32 | Task RunAsync(CancellationToken cancellationToken);
33 |
34 | string GetBotAvatarUrl();
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Discord/IDiscordGuilds.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Entities.Discord;
17 | using System.Threading.Tasks;
18 |
19 | namespace Miunie.Core.Discord
20 | {
21 | public interface IDiscordGuilds
22 | {
23 | Task FromAsync(MiunieUser user);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Discord/IDiscordImpersonation.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Entities.Views;
17 | using Miunie.Core.Events;
18 | using System;
19 | using System.Collections.Generic;
20 | using System.Threading.Tasks;
21 |
22 | namespace Miunie.Core.Discord
23 | {
24 | public interface IDiscordImpersonation
25 | {
26 | event EventHandler MessageReceived;
27 |
28 | void SubscribeForMessages();
29 |
30 | void UnsubscribeForMessages();
31 |
32 | IEnumerable GetAvailableGuilds();
33 |
34 | Task> GetAvailableTextChannelsAsync(ulong guildId);
35 |
36 | Task> GetMessagesFromTextChannelAsync(ulong guildId, ulong channelId);
37 |
38 | Task SendTextToChannelAsync(string text, ulong id);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Discord/IDiscordMessages.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Entities;
17 | using Miunie.Core.Entities.Discord;
18 | using System.Collections.Generic;
19 | using System.Threading.Tasks;
20 |
21 | namespace Miunie.Core.Discord
22 | {
23 | public interface IDiscordMessages
24 | {
25 | Task SendMessageAsync(MiunieChannel targetChannel, PhraseKey phraseKey, params object[] parameters);
26 |
27 | Task SendMessageAsync(MiunieChannel targetChannel, MiunieUser user);
28 |
29 | Task SendMessageAsync(MiunieChannel targetChannel, MiunieGuild guild);
30 |
31 | Task SendMessageAsync(MiunieChannel mc, IEnumerable repEntries, int index);
32 |
33 | Task SendDirectFileMessageAsync(MiunieUser mu, string userAsJson);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Entities/ConnectionState.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | namespace Miunie.Core.Entities
17 | {
18 | public enum ConnectionState
19 | {
20 | CONNECTED,
21 | CONNECTING,
22 | DISCONNECTED
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Entities/Discord/MiunieChannel.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | namespace Miunie.Core.Entities.Discord
17 | {
18 | public class MiunieChannel
19 | {
20 | public ulong ChannelId { get; set; }
21 |
22 | public ulong GuildId { get; set; }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Entities/Discord/MiunieGuild.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using System;
17 | using System.Collections.Generic;
18 |
19 | namespace Miunie.Core.Entities.Discord
20 | {
21 | public class MiunieGuild
22 | {
23 | public ulong Id { get; set; }
24 |
25 | public string Name { get; set; }
26 |
27 | public IEnumerable Roles { get; set; }
28 |
29 | public IEnumerable ChannelNames { get; set; }
30 |
31 | public DateTime CreationDate { get; set; }
32 |
33 | public int TextChannelCount { get; set; }
34 |
35 | public int VoiceChannelCount { get; set; }
36 |
37 | public int MemberCount { get; set; }
38 |
39 | public string IconUrl { get; set; }
40 |
41 | public string GetStats()
42 | => $"{MemberCount} members chatting in \n" +
43 | $":pencil: {TextChannelCount} Text Channel/s & \n" +
44 | $":loudspeaker: {VoiceChannelCount} Voice Channel/s.";
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Entities/Discord/MiunieRole.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | namespace Miunie.Core.Entities.Discord
17 | {
18 | public class MiunieRole
19 | {
20 | public ulong Id { get; set; }
21 |
22 | public string Name { get; set; }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Entities/Discord/MiunieUser.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using System;
17 | using System.Collections.Generic;
18 | using System.Linq;
19 |
20 | namespace Miunie.Core.Entities.Discord
21 | {
22 | public class MiunieUser
23 | {
24 | public Guid Id => GenerateSeededGuid();
25 |
26 | public string Name { get; set; }
27 |
28 | public ulong GuildId { get; set; }
29 |
30 | public ulong UserId { get; set; }
31 |
32 | public Reputation Reputation { get; set; }
33 |
34 | public DateTime JoinedAt { get; set; }
35 |
36 | public DateTime CreatedAt { get; set; }
37 |
38 | public bool IsBot { get; set; }
39 |
40 | public IEnumerable Roles { get; set; }
41 |
42 | public string AvatarUrl { get; set; }
43 |
44 | public TimeSpan? UtcTimeOffset { get; set; }
45 |
46 | private Guid GenerateSeededGuid()
47 | {
48 | var left = BitConverter.GetBytes(GuildId);
49 | var right = BitConverter.GetBytes(UserId);
50 | var bytes = left.Concat(right).ToArray();
51 | return new Guid(bytes);
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Entities/PhraseKey.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | namespace Miunie.Core.Entities
17 | {
18 | public enum PhraseKey
19 | {
20 | REPUTATION_GIVEN,
21 | REPUTATION_TAKEN,
22 | CANNOT_SELF_REP,
23 | SHOW_REMOTE_REPO,
24 | USER_EMBED_TITLE,
25 | USER_EMBED_NAME_TITLE,
26 | USER_EMBED_IS_BOT,
27 | USER_EMBED_IS_HUMAN,
28 | USER_EMBED_REALNESS_TITLE,
29 | USER_EMBED_REP_TITLE,
30 | USER_EMBED_REP_LOG_TITLE,
31 | USER_EMBED_REP_LOG_EMPTY,
32 | USER_EMBED_ROLES_TITLE,
33 | USER_EMBED_JOINED_AT_TITLE,
34 | USER_EMBED_CREATED_AT_TITLE,
35 | GUILD_EMBED_TITLE,
36 | GUILD_EMBED_NAME_TITLE,
37 | GUILD_EMBED_STATS_TITLE,
38 | GUILD_EMBED_ROLES_TITLE,
39 | GUILD_EMBED_CREATED_AT_TITLE,
40 | TIME_NO_TIMEZONE_INFO,
41 | TIME_TIMEZONE_INFO,
42 | TIME_NEW_OFFSET_SET,
43 | TIME_NEW_OFFSET_SET_ADMIN,
44 | USER_EMBED_TIME_TITLE,
45 | USER_EMBED_TIME_NOSET,
46 | USER_EMBED_TIME,
47 | YES_NO_MAYBE,
48 | TIME_USERTIME_FROM_LOCAL,
49 | TIME_USERTIME_IN_FUTURE,
50 | TIME_USERTIME_IN_FUTURE_UNPARSABLE,
51 | TIME_NO_MESSAGE,
52 | TIME_MESSAGE_INFO_EDIT,
53 | TIME_MESSAGE_INFO_NO_EDIT,
54 | INCORRECT_VERB,
55 | REPUTATION_TAKEN_BOT,
56 | REPUTATION_GIVEN_BOT,
57 | USER_PRIVACY_FILE_MESSAGE,
58 | USER_PRIVACY_DATA_REMOVED,
59 | GPL3_NOTICE
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Entities/Reputation.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using System;
17 | using System.Collections.Concurrent;
18 |
19 | namespace Miunie.Core.Entities
20 | {
21 | public class Reputation
22 | {
23 | public Reputation()
24 | {
25 | PlusRepLog = new ConcurrentDictionary();
26 | MinusRepLog = new ConcurrentDictionary();
27 | }
28 |
29 | public int Value { get; set; }
30 |
31 | public ConcurrentDictionary PlusRepLog { get; set; }
32 |
33 | public ConcurrentDictionary MinusRepLog { get; set; }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Entities/ReputationEntry.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using System;
17 |
18 | namespace Miunie.Core.Entities
19 | {
20 | public class ReputationEntry
21 | {
22 | public ReputationEntry(ulong targetId, string targetName, DateTime givenAt, ReputationType type, bool isfromInvoker = false)
23 | {
24 | TargetId = targetId;
25 | TargetName = targetName;
26 | GivenAt = givenAt;
27 | Type = type;
28 | IsFromInvoker = isfromInvoker;
29 | }
30 |
31 | public ulong TargetId { get; set; }
32 |
33 | public string TargetName { get; set; }
34 |
35 | public DateTime GivenAt { get; set; }
36 |
37 | public ReputationType Type { get; set; }
38 |
39 | public bool IsFromInvoker { get; set; }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Entities/ReputationType.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | namespace Miunie.Core.Entities
17 | {
18 | public enum ReputationType
19 | {
20 | Plus = 1,
21 | Minus = 2
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Entities/ServiceType.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | namespace Miunie.Core.Entities
17 | {
18 | public enum ServiceType
19 | {
20 | SCOPED,
21 | SINGLETON,
22 | TRANSIENT
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Entities/Views/GuildView.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | namespace Miunie.Core.Entities.Views
17 | {
18 | public class GuildView
19 | {
20 | public ulong Id { get; set; }
21 |
22 | public string Name { get; set; }
23 |
24 | public string IconUrl { get; set; }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Entities/Views/MessageView.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using System;
17 |
18 | namespace Miunie.Core.Entities.Views
19 | {
20 | public class MessageView
21 | {
22 | public ulong ChannelId { get; set; }
23 |
24 | public string AuthorName { get; set; }
25 |
26 | public string AuthorAvatarUrl { get; set; }
27 |
28 | public string Content { get; set; }
29 |
30 | public DateTimeOffset TimeStamp { get; set; }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Entities/Views/TextChannelView.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using System.Collections.Generic;
17 |
18 | namespace Miunie.Core.Entities.Views
19 | {
20 | public class TextChannelView
21 | {
22 | public ulong Id { get; set; }
23 |
24 | public string Name { get; set; }
25 |
26 | public IEnumerable Messages { get; set; }
27 |
28 | public bool CanSendMessages { get; set; }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Events/MessageReceivedEventArgs.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Entities.Views;
17 | using System;
18 |
19 | namespace Miunie.Core.Events
20 | {
21 | public class MessageReceivedEventArgs : EventArgs
22 | {
23 | public MessageReceivedEventArgs(MessageView message)
24 | {
25 | Message = message;
26 | }
27 |
28 | public MessageView Message { get; }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Infrastructure/IDateTime.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using System;
17 |
18 | namespace Miunie.Core.Infrastructure
19 | {
20 | public interface IDateTime
21 | {
22 | DateTime UtcNow { get; }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Infrastructure/IFileSystem.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | namespace Miunie.Core.Infrastructure
17 | {
18 | public interface IFileSystem
19 | {
20 | string DataStoragePath { get; }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Json/IJsonConverter.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | namespace Miunie.Core.Json
17 | {
18 | public interface IJsonConverter
19 | {
20 | string Serialize(T obj);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Logging/ILogReader.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using System;
17 | using System.Collections.Generic;
18 |
19 | namespace Miunie.Core.Logging
20 | {
21 | public interface ILogReader
22 | {
23 | event EventHandler LogRecieved;
24 |
25 | IEnumerable RetrieveLogs(int ammount = 5);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Logging/ILogWriter.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | namespace Miunie.Core.Logging
17 | {
18 | public interface ILogWriter
19 | {
20 | void Log(string message);
21 |
22 | void LogError(string message);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Miunie.Core.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 | GPL-3.0
6 | LICENSE
7 | https://github.com/control-net/Miunie
8 | https://github.com/control-net/Miunie
9 | git
10 |
11 |
12 |
13 |
14 | True
15 | True
16 | Strings.resx
17 |
18 |
19 |
20 |
21 |
22 | PublicResXFileCodeGenerator
23 | Strings.Designer.cs
24 |
25 |
26 |
27 |
28 |
29 | True
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/src/Miunie.Core/MiunieBot.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Configuration;
17 | using Miunie.Core.Discord;
18 | using System.Threading;
19 | using System.Threading.Tasks;
20 |
21 | namespace Miunie.Core
22 | {
23 | public class MiunieBot
24 | {
25 | private CancellationTokenSource _tokenSource;
26 |
27 | public MiunieBot(IDiscordConnection miunieDiscord, IBotConfiguration botConfig, IDiscordImpersonation impersonation)
28 | {
29 | MiunieDiscord = miunieDiscord;
30 | BotConfiguration = botConfig;
31 | Impersonation = impersonation;
32 | }
33 |
34 | public IBotConfiguration BotConfiguration { get; }
35 |
36 | public IDiscordConnection MiunieDiscord { get; }
37 |
38 | public IDiscordImpersonation Impersonation { get; }
39 |
40 | public async Task StartAsync()
41 | {
42 | _tokenSource = new CancellationTokenSource();
43 | await MiunieDiscord.RunAsync(_tokenSource.Token);
44 | }
45 |
46 | public void Stop()
47 | {
48 | if (_tokenSource is null) { return; }
49 | _tokenSource.Cancel();
50 | _tokenSource.Dispose();
51 | _tokenSource = null;
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Providers/ILanguageProvider.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | namespace Miunie.Core.Providers
17 | {
18 | public interface ILanguageProvider
19 | {
20 | string GetPhrase(string key, params object[] objs);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Providers/IMiunieUserProvider.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Entities.Discord;
17 | using System.Collections.Generic;
18 |
19 | namespace Miunie.Core.Providers
20 | {
21 | public interface IMiunieUserProvider
22 | {
23 | MiunieUser GetById(ulong userId, ulong guildId);
24 |
25 | void StoreUser(MiunieUser u);
26 |
27 | void RemoveUser(MiunieUser u);
28 |
29 | IEnumerable GetAllUsers();
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Providers/ITimeManipulationProvider.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Entities.Discord;
17 | using System;
18 |
19 | namespace Miunie.Core.Providers
20 | {
21 | public interface ITimeManipulationProvider
22 | {
23 | TimeSpan? GetTimeSpanFromString(string timeframe, int units);
24 |
25 | DateTime? GetDateTimeLocalToUser(DateTime? utcDateTime, MiunieUser user);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Providers/IUserReputationProvider.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Entities;
17 | using Miunie.Core.Entities.Discord;
18 | using System.Collections.Generic;
19 |
20 | namespace Miunie.Core.Providers
21 | {
22 | public interface IUserReputationProvider
23 | {
24 | int TimeoutInSeconds { get; }
25 |
26 | void AddReputation(MiunieUser invoker, MiunieUser target);
27 |
28 | void RemoveReputation(MiunieUser invoker, MiunieUser target);
29 |
30 | bool CanAddReputation(MiunieUser invoker, MiunieUser target);
31 |
32 | bool CanRemoveReputation(MiunieUser invoker, MiunieUser target);
33 |
34 | IEnumerable GetReputation(MiunieUser user);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Providers/LanguageProvider.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Logging;
17 | using System;
18 |
19 | namespace Miunie.Core.Providers
20 | {
21 | public class LanguageProvider : ILanguageProvider
22 | {
23 | private static readonly string[] ResourceSeparators = { "{{OR}}" };
24 |
25 | private readonly ILogWriter _logger;
26 | private readonly Random _random;
27 |
28 | public LanguageProvider(ILogWriter logger, Random random)
29 | {
30 | _logger = logger;
31 | _random = random;
32 | }
33 |
34 | public string GetPhrase(string key, params object[] objs)
35 | {
36 | var resource = Strings.ResourceManager.GetString(key);
37 | if (resource is null)
38 | {
39 | _logger.LogError($"Unable to find Language Resource with the following key: {key}");
40 | return string.Empty;
41 | }
42 |
43 | var pool = resource.Split(ResourceSeparators, StringSplitOptions.RemoveEmptyEntries);
44 | return string.Format(pool[_random.Next(0, pool.Length)], objs);
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Providers/MiunieUserProvider.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Entities;
17 | using Miunie.Core.Entities.Discord;
18 | using Miunie.Core.Storage;
19 | using System.Collections.Generic;
20 |
21 | namespace Miunie.Core.Providers
22 | {
23 | public class MiunieUserProvider : IMiunieUserProvider
24 | {
25 | private readonly IPersistentStorage _persistentStorage;
26 |
27 | public MiunieUserProvider(IPersistentStorage persistentStorage)
28 | {
29 | _persistentStorage = persistentStorage;
30 | }
31 |
32 | public MiunieUser GetById(ulong userId, ulong guildId)
33 | {
34 | var user = _persistentStorage.RestoreSingle(u => u.UserId == userId && u.GuildId == guildId);
35 | return EnsureExists(user, userId, guildId);
36 | }
37 |
38 | public void StoreUser(MiunieUser user)
39 | {
40 | if (_persistentStorage.Exists(u => u.UserId == user.UserId && u.GuildId == user.GuildId))
41 | {
42 | _persistentStorage.Update(user);
43 | }
44 | else
45 | {
46 | _persistentStorage.Store(user);
47 | }
48 | }
49 |
50 | public void RemoveUser(MiunieUser user)
51 | {
52 | if (_persistentStorage.Exists(u => u.UserId == user.UserId && u.GuildId == user.GuildId))
53 | {
54 | _persistentStorage.Remove(u => u.UserId == user.UserId && u.GuildId == user.GuildId);
55 | }
56 | }
57 |
58 | public IEnumerable GetAllUsers()
59 | => _persistentStorage.RestoreAll();
60 |
61 | private MiunieUser EnsureExists(
62 | MiunieUser user,
63 | ulong userId,
64 | ulong guildId)
65 | {
66 | if (user is null)
67 | {
68 | user = new MiunieUser
69 | {
70 | GuildId = guildId,
71 | UserId = userId,
72 | Reputation = new Reputation()
73 | };
74 | StoreUser(user);
75 | }
76 |
77 | return user;
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Providers/TimeManipulationProvider.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Entities.Discord;
17 | using System;
18 |
19 | namespace Miunie.Core.Providers
20 | {
21 | public class TimeManipulationProvider : ITimeManipulationProvider
22 | {
23 | public TimeSpan? GetTimeSpanFromString(string timeframe, int units)
24 | {
25 | if (string.IsNullOrWhiteSpace(timeframe) || units <= 0)
26 | {
27 | return null;
28 | }
29 |
30 | timeframe = timeframe.Trim().ToLower();
31 |
32 | return timeframe switch {
33 | var tframe when
34 | tframe == "hours" || tframe == "hour" || tframe == "hrs" || tframe == "hr"
35 | => new TimeSpan(units, 0, 0),
36 | var tframe when
37 | tframe == "minutes" || tframe == "minute" || tframe == "mins" || tframe == "min"
38 | => new TimeSpan(0, units, 0),
39 | var tframe when
40 | tframe == "seconds" || tframe == "second" || tframe == "secs" || tframe == "sec"
41 | => new TimeSpan(0, 0, units),
42 | _ => null,
43 | };
44 | }
45 |
46 | public DateTime? GetDateTimeLocalToUser(DateTime? utcDateTime, MiunieUser user)
47 | {
48 | if (!utcDateTime.HasValue)
49 | {
50 | return utcDateTime;
51 | }
52 |
53 | if (user.UtcTimeOffset.HasValue)
54 | {
55 | return utcDateTime.Value.Add(user.UtcTimeOffset.Value);
56 | }
57 |
58 | return utcDateTime;
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Providers/UserReputationProvider.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Entities;
17 | using Miunie.Core.Entities.Discord;
18 | using Miunie.Core.Infrastructure;
19 | using System;
20 | using System.Collections.Concurrent;
21 | using System.Collections.Generic;
22 | using System.Linq;
23 |
24 | namespace Miunie.Core.Providers
25 | {
26 | public class UserReputationProvider : IUserReputationProvider
27 | {
28 | private readonly IMiunieUserProvider _userProvider;
29 | private readonly IDateTime _dateTime;
30 |
31 | public UserReputationProvider(IMiunieUserProvider userProvider, IDateTime dateTime)
32 | {
33 | _userProvider = userProvider;
34 | _dateTime = dateTime;
35 | }
36 |
37 | public int TimeoutInSeconds { get; } = 1800;
38 |
39 | public IEnumerable GetReputation(MiunieUser invoker)
40 | {
41 | var rep = new List();
42 |
43 | if (invoker is null || invoker.Reputation is null) { return rep; }
44 |
45 | foreach (MiunieUser user in _userProvider.GetAllUsers().Where(x => x.Id != invoker.Id))
46 | {
47 | if (user.Reputation.PlusRepLog.ContainsKey(invoker.UserId))
48 | {
49 | rep.Add(new ReputationEntry(user.UserId, user.Name, user.Reputation.PlusRepLog[invoker.UserId], ReputationType.Plus, true));
50 | }
51 |
52 | if (user.Reputation.MinusRepLog.ContainsKey(invoker.UserId))
53 | {
54 | rep.Add(new ReputationEntry(user.UserId, user.Name, user.Reputation.PlusRepLog[invoker.UserId], ReputationType.Minus, true));
55 | }
56 | }
57 |
58 | foreach (KeyValuePair entry in invoker.Reputation.PlusRepLog)
59 | {
60 | var user = _userProvider.GetById(entry.Key, invoker.GuildId);
61 | rep.Add(new ReputationEntry(user.UserId, user.Name, entry.Value, ReputationType.Plus));
62 | }
63 |
64 | foreach (KeyValuePair entry in invoker.Reputation.MinusRepLog)
65 | {
66 | var user = _userProvider.GetById(entry.Key, invoker.GuildId);
67 | rep.Add(new ReputationEntry(user.UserId, user.Name, entry.Value, ReputationType.Minus));
68 | }
69 |
70 | return rep.OrderByDescending(x => x.GivenAt);
71 | }
72 |
73 | public void AddReputation(MiunieUser invoker, MiunieUser target)
74 | {
75 | target.Reputation.Value++;
76 | _ = target.Reputation.PlusRepLog.TryAdd(invoker.UserId, _dateTime.UtcNow);
77 | _userProvider.StoreUser(target);
78 | }
79 |
80 | public void RemoveReputation(MiunieUser invoker, MiunieUser target)
81 | {
82 | target.Reputation.Value--;
83 | _ = target.Reputation.MinusRepLog.TryAdd(invoker.UserId, _dateTime.UtcNow);
84 | _userProvider.StoreUser(target);
85 | }
86 |
87 | public bool CanAddReputation(MiunieUser invoker, MiunieUser target)
88 | => HasTimeout(target.Reputation.PlusRepLog, invoker);
89 |
90 | public bool CanRemoveReputation(MiunieUser invoker, MiunieUser target)
91 | => HasTimeout(target.Reputation.MinusRepLog, invoker);
92 |
93 | private bool HasTimeout(ConcurrentDictionary log, MiunieUser invoker)
94 | {
95 | _ = log.TryGetValue(invoker.UserId, out var lastRepDateTime);
96 |
97 | if ((_dateTime.UtcNow - lastRepDateTime).TotalSeconds <= TimeoutInSeconds) { return true; }
98 |
99 | _ = log.TryRemove(invoker.UserId, out _);
100 | _userProvider.StoreUser(invoker);
101 | return false;
102 | }
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Services/MiscService.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Attributes;
17 | using Miunie.Core.Discord;
18 | using Miunie.Core.Entities;
19 | using Miunie.Core.Entities.Discord;
20 | using System.Threading.Tasks;
21 |
22 | namespace Miunie.Core
23 | {
24 | [Service]
25 | public class MiscService
26 | {
27 | private readonly IDiscordMessages _messages;
28 |
29 | public MiscService(IDiscordMessages messages)
30 | {
31 | _messages = messages;
32 | }
33 |
34 | public async Task SendRandomYesNoAnswerAsync(MiunieChannel channel)
35 | {
36 | await _messages.SendMessageAsync(channel, PhraseKey.YES_NO_MAYBE);
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Services/PrivacyService.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Attributes;
17 | using Miunie.Core.Discord;
18 | using Miunie.Core.Entities;
19 | using Miunie.Core.Entities.Discord;
20 | using Miunie.Core.Json;
21 | using Miunie.Core.Providers;
22 | using System.Threading.Tasks;
23 |
24 | namespace Miunie.Core
25 | {
26 | [Service]
27 | public class PrivacyService
28 | {
29 | private readonly IDiscordMessages _messages;
30 | private readonly IMiunieUserProvider _users;
31 | private readonly IJsonConverter _jsonParser;
32 |
33 | public PrivacyService(IDiscordMessages messages, IMiunieUserProvider users, IJsonConverter jsonParser)
34 | {
35 | _messages = messages;
36 | _users = users;
37 | _jsonParser = jsonParser;
38 | }
39 |
40 | public async Task OutputUserJsonDataAsync(MiunieUser user)
41 | {
42 | var userJson = _jsonParser.Serialize(user);
43 | await _messages.SendDirectFileMessageAsync(user, userJson);
44 | }
45 |
46 | public async Task RemoveUserData(MiunieUser user, MiunieChannel channel)
47 | {
48 | _users.RemoveUser(user);
49 | await _messages.SendMessageAsync(channel, PhraseKey.USER_PRIVACY_DATA_REMOVED, user.Name);
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Services/ProfileService.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Attributes;
17 | using Miunie.Core.Discord;
18 | using Miunie.Core.Entities;
19 | using Miunie.Core.Entities.Discord;
20 | using Miunie.Core.Logging;
21 | using Miunie.Core.Providers;
22 | using System.Threading.Tasks;
23 |
24 | namespace Miunie.Core
25 | {
26 | [Service]
27 | public class ProfileService
28 | {
29 | private readonly IDiscordMessages _discordMessages;
30 | private readonly IUserReputationProvider _reputationProvider;
31 | private readonly ILogWriter _logger;
32 | private readonly IDiscordConnection _miunieDiscord;
33 |
34 | public ProfileService(IDiscordMessages discordMessages, IUserReputationProvider reputationProvider, ILogWriter logger, IDiscordConnection miunieDiscord)
35 | {
36 | _discordMessages = discordMessages;
37 | _reputationProvider = reputationProvider;
38 | _logger = logger;
39 | _miunieDiscord = miunieDiscord;
40 | }
41 |
42 | public async Task ShowProfileAsync(MiunieUser user, MiunieChannel c)
43 | => await _discordMessages.SendMessageAsync(c, user);
44 |
45 | public async Task ShowReputationLogAsync(MiunieUser user, int page, MiunieChannel c)
46 | {
47 | page -= 1;
48 | var repGiven = _reputationProvider.GetReputation(user);
49 |
50 | await _discordMessages.SendMessageAsync(c, repGiven, page);
51 | }
52 |
53 | public async Task GiveReputationAsync(MiunieUser invoker, MiunieUser target, MiunieChannel c)
54 | {
55 | if (invoker.UserId == target.UserId)
56 | {
57 | await _discordMessages.SendMessageAsync(c, PhraseKey.CANNOT_SELF_REP, invoker.Name);
58 | return;
59 | }
60 |
61 | if (_reputationProvider.CanAddReputation(invoker, target))
62 | {
63 | _logger.Log($"User '{invoker.Name}' has a reputation timeout for User '{target.Name}', ignoring...");
64 | return;
65 | }
66 |
67 | _reputationProvider.AddReputation(invoker, target);
68 |
69 | if (_miunieDiscord.UserIsMiunie(target))
70 | {
71 | await _discordMessages.SendMessageAsync(c, PhraseKey.REPUTATION_GIVEN_BOT, invoker.Name);
72 | return;
73 | }
74 |
75 | await _discordMessages.SendMessageAsync(c, PhraseKey.REPUTATION_GIVEN, target.Name, invoker.Name);
76 | }
77 |
78 | public async Task RemoveReputationAsync(MiunieUser invoker, MiunieUser target, MiunieChannel c)
79 | {
80 | if (invoker.UserId == target.UserId)
81 | {
82 | await _discordMessages.SendMessageAsync(c, PhraseKey.CANNOT_SELF_REP, invoker.Name);
83 | return;
84 | }
85 |
86 | if (_reputationProvider.CanRemoveReputation(invoker, target)) { return; }
87 |
88 | _reputationProvider.RemoveReputation(invoker, target);
89 |
90 | if (_miunieDiscord.UserIsMiunie(target))
91 | {
92 | await _discordMessages.SendMessageAsync(c, PhraseKey.REPUTATION_TAKEN_BOT, invoker.Name);
93 | return;
94 | }
95 |
96 | await _discordMessages.SendMessageAsync(c, PhraseKey.REPUTATION_TAKEN, invoker.Name, target.Name);
97 | }
98 |
99 | public async Task ShowGuildProfileAsync(MiunieGuild guild, MiunieChannel c)
100 | => await _discordMessages.SendMessageAsync(c, guild);
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Services/RemoteRepositoryService.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Attributes;
17 | using Miunie.Core.Discord;
18 | using Miunie.Core.Entities;
19 | using Miunie.Core.Entities.Discord;
20 | using System.Threading.Tasks;
21 |
22 | namespace Miunie.Core
23 | {
24 | [Service]
25 | public class RemoteRepositoryService
26 | {
27 | private readonly IDiscordMessages _discordMessages;
28 |
29 | public RemoteRepositoryService(IDiscordMessages discordMessages)
30 | {
31 | _discordMessages = discordMessages;
32 | }
33 |
34 | public async Task ShowRepositoryAsync(MiunieChannel c)
35 | => await _discordMessages.SendMessageAsync(c, PhraseKey.SHOW_REMOTE_REPO);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Services/TimeService.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Attributes;
17 | using Miunie.Core.Discord;
18 | using Miunie.Core.Entities;
19 | using Miunie.Core.Entities.Discord;
20 | using Miunie.Core.Infrastructure;
21 | using Miunie.Core.Providers;
22 | using System;
23 | using System.Threading.Tasks;
24 |
25 | namespace Miunie.Core
26 | {
27 | [Service]
28 | public class TimeService
29 | {
30 | private readonly IDiscordMessages _messages;
31 | private readonly IDateTime _dateTime;
32 | private readonly IMiunieUserProvider _users;
33 | private readonly ITimeManipulationProvider _timeManipulator;
34 |
35 | public TimeService(IDiscordMessages messages, IDateTime dateTime, IMiunieUserProvider users, ITimeManipulationProvider timeManipulator)
36 | {
37 | _messages = messages;
38 | _dateTime = dateTime;
39 | _users = users;
40 | _timeManipulator = timeManipulator;
41 | }
42 |
43 | public async Task OutputCurrentTimeForUserAsync(MiunieUser user, MiunieChannel channel)
44 | {
45 | if (!user.UtcTimeOffset.HasValue)
46 | {
47 | await _messages.SendMessageAsync(channel, PhraseKey.TIME_NO_TIMEZONE_INFO, user.Name);
48 | return;
49 | }
50 |
51 | var targetDateTime = _dateTime.UtcNow + user.UtcTimeOffset.Value;
52 | await _messages.SendMessageAsync(channel, PhraseKey.TIME_TIMEZONE_INFO, user.Name, targetDateTime);
53 | }
54 |
55 | public async Task OutputCurrentTimeComparedToInputForUserAsync(MiunieUser requestUser, DateTime requestTime, string verb, MiunieUser user, MiunieChannel channel)
56 | {
57 | if (verb.Trim().ToLower() != "for")
58 | {
59 | await _messages.SendMessageAsync(channel, PhraseKey.INCORRECT_VERB, verb);
60 | return;
61 | }
62 |
63 | var requesterOffset = requestUser.UtcTimeOffset ?? default;
64 | var otherUserOffSet = user.UtcTimeOffset ?? default;
65 |
66 | var requestUtcTime = requestTime - requesterOffset;
67 | var otherUserTime = requestUtcTime + otherUserOffSet;
68 |
69 | await _messages.SendMessageAsync(channel, PhraseKey.TIME_USERTIME_FROM_LOCAL, requestTime, user.Name, otherUserTime);
70 | }
71 |
72 | public async Task OutputFutureTimeForUserAsync(MiunieUser user, string verb, int units, string timeframe, MiunieChannel channel)
73 | {
74 | if (verb.Trim().ToLower() != "in")
75 | {
76 | await _messages.SendMessageAsync(channel, PhraseKey.INCORRECT_VERB, verb);
77 | return;
78 | }
79 |
80 | var timeFromLocal = _timeManipulator.GetTimeSpanFromString(timeframe, units);
81 |
82 | if (timeFromLocal is null)
83 | {
84 | await _messages.SendMessageAsync(channel, PhraseKey.TIME_USERTIME_IN_FUTURE_UNPARSABLE, units.ToString(), timeframe);
85 | return;
86 | }
87 |
88 | var usersOffset = user.UtcTimeOffset ?? default;
89 | var usersLocalTime = _dateTime.UtcNow + usersOffset;
90 | var usersFutureTime = usersLocalTime + timeFromLocal;
91 |
92 | await _messages.SendMessageAsync(channel, PhraseKey.TIME_USERTIME_IN_FUTURE, user.Name, usersFutureTime, units.ToString(), timeframe);
93 | }
94 |
95 | public async Task OutputMessageTimeAsLocalAsync(ulong messageId, DateTimeOffset? createdTimeOffset, DateTimeOffset? editTimeOffset, MiunieUser user, MiunieChannel channel)
96 | {
97 | if (createdTimeOffset is null)
98 | {
99 | await _messages.SendMessageAsync(channel, PhraseKey.TIME_NO_MESSAGE, messageId.ToString());
100 | return;
101 | }
102 |
103 | var messageCreated = _timeManipulator.GetDateTimeLocalToUser(createdTimeOffset?.UtcDateTime, user);
104 | var messageEdited = _timeManipulator.GetDateTimeLocalToUser(editTimeOffset?.UtcDateTime, user);
105 |
106 | if (messageEdited.HasValue)
107 | {
108 | await _messages.SendMessageAsync(channel, PhraseKey.TIME_MESSAGE_INFO_EDIT, messageId.ToString(), messageCreated, messageEdited);
109 | return;
110 | }
111 |
112 | await _messages.SendMessageAsync(channel, PhraseKey.TIME_MESSAGE_INFO_NO_EDIT, messageId.ToString(), messageCreated);
113 | }
114 |
115 | public async Task SetUtcOffsetForUserAsync(DateTime userTime, MiunieUser user, MiunieChannel channel)
116 | {
117 | var offset = TimeSpan.FromHours(userTime.Hour - _dateTime.UtcNow.Hour);
118 | user.UtcTimeOffset = offset;
119 | _users.StoreUser(user);
120 | await _messages.SendMessageAsync(channel, PhraseKey.TIME_NEW_OFFSET_SET);
121 | }
122 |
123 | public async Task SetUtcOffsetForUserByAdminAsync(DateTime userTime, MiunieUser user, MiunieChannel channel)
124 | {
125 | var offset = TimeSpan.FromHours(userTime.Hour - _dateTime.UtcNow.Hour);
126 | user.UtcTimeOffset = offset;
127 | _users.StoreUser(user);
128 | await _messages.SendMessageAsync(channel, PhraseKey.TIME_NEW_OFFSET_SET_ADMIN, user.Name);
129 | }
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/src/Miunie.Core/Storage/IPersistentStorage.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using System;
17 | using System.Collections.Generic;
18 | using System.Linq.Expressions;
19 |
20 | namespace Miunie.Core.Storage
21 | {
22 | public interface IPersistentStorage
23 | {
24 | void Store(T item);
25 |
26 | void Update(T item);
27 |
28 | void Remove(Expression> predicate);
29 |
30 | IEnumerable RestoreMany(Expression> predicate);
31 |
32 | IEnumerable RestoreAll();
33 |
34 | T RestoreSingle(Expression> predicate);
35 |
36 | bool Exists(Expression> predicate);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/Miunie.Discord/Adapters/DiscordGuildsAdapter.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Discord;
17 | using Miunie.Core.Entities.Discord;
18 | using Miunie.Discord.Convertors;
19 | using System.Threading.Tasks;
20 |
21 | namespace Miunie.Discord.Adapters
22 | {
23 | public class DiscordGuildsAdapter : IDiscordGuilds
24 | {
25 | private readonly IDiscord _discord;
26 | private readonly EntityConvertor _entityConvertor;
27 |
28 | public DiscordGuildsAdapter(IDiscord discord, EntityConvertor entityConvertor)
29 | {
30 | _discord = discord;
31 | _entityConvertor = entityConvertor;
32 | }
33 |
34 | public Task FromAsync(MiunieUser user)
35 | {
36 | var guild = _discord.Client.GetGuild(user.GuildId);
37 |
38 | return Task.FromResult(_entityConvertor.ConvertGuild(guild));
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/Miunie.Discord/Adapters/DiscordMessagesAdapter.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Discord.WebSocket;
17 | using Miunie.Core.Discord;
18 | using Miunie.Core.Entities;
19 | using Miunie.Core.Entities.Discord;
20 | using Miunie.Core.Logging;
21 | using Miunie.Core.Providers;
22 | using Miunie.Discord.Embeds;
23 | using System.Collections.Generic;
24 | using System.IO;
25 | using System.Threading.Tasks;
26 |
27 | namespace Miunie.Discord.Adapters
28 | {
29 | public class DiscordMessagesAdapter : IDiscordMessages
30 | {
31 | private readonly IDiscord _discord;
32 | private readonly ILanguageProvider _lang;
33 | private readonly ILogWriter _log;
34 |
35 | public DiscordMessagesAdapter(IDiscord discord, ILanguageProvider lang, ILogWriter log)
36 | {
37 | _discord = discord;
38 | _lang = lang;
39 | _log = log;
40 | }
41 |
42 | public async Task SendMessageAsync(MiunieChannel mc, IEnumerable repEntries, int index)
43 | {
44 | var channel = _discord.Client.GetChannel(mc.ChannelId) as SocketTextChannel;
45 | var embed = EmbedConstructor.CreateReputationLog(repEntries, index, _lang);
46 |
47 | _ = await channel.SendMessageAsync(embed: embed);
48 | }
49 |
50 | public async Task SendMessageAsync(MiunieChannel mc, PhraseKey phraseKey, params object[] parameters)
51 | {
52 | var channel = _discord.Client.GetChannel(mc.ChannelId) as SocketTextChannel;
53 | var msg = _lang.GetPhrase(phraseKey.ToString(), parameters);
54 | _ = await channel.SendMessageAsync(msg);
55 | }
56 |
57 | public async Task SendMessageAsync(MiunieChannel mc, MiunieUser mu)
58 | {
59 | if (!(_discord.Client.GetChannel(mc.ChannelId) is SocketTextChannel channel))
60 | {
61 | LogSocketTextChannelCastFailed();
62 | return;
63 | }
64 |
65 | _ = await channel.SendMessageAsync(embed: mu.ToEmbed(_lang));
66 | }
67 |
68 | public async Task SendMessageAsync(MiunieChannel mc, MiunieGuild mg)
69 | {
70 | if (!(_discord.Client.GetChannel(mc.ChannelId) is SocketTextChannel channel))
71 | {
72 | LogSocketTextChannelCastFailed();
73 | return;
74 | }
75 |
76 | _ = await channel.SendMessageAsync(embed: mg.ToEmbed(_lang));
77 | }
78 |
79 | public async Task SendDirectFileMessageAsync(MiunieUser mu, string userAsJson)
80 | {
81 | var dmChannel = await _discord.Client.GetUser(mu.UserId).GetOrCreateDMChannelAsync();
82 | var msg = _lang.GetPhrase(PhraseKey.USER_PRIVACY_FILE_MESSAGE.ToString(), mu.Name);
83 |
84 | using var fileStream = GenerateStreamFromString(userAsJson);
85 | _ = await dmChannel.SendFileAsync(fileStream, $"{mu.Name}.json", msg);
86 | }
87 |
88 | private static Stream GenerateStreamFromString(string s)
89 | {
90 | var stream = new MemoryStream();
91 | var writer = new StreamWriter(stream);
92 | writer.Write(s);
93 | writer.Flush();
94 | stream.Position = 0;
95 | return stream;
96 | }
97 |
98 | private void LogSocketTextChannelCastFailed()
99 | {
100 | _log.LogError("Invalid cast to SocketTextChannel.");
101 | }
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/src/Miunie.Discord/CommandHandler.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Discord.Commands;
17 | using Discord.WebSocket;
18 | using Miunie.Core.Commands;
19 | using Miunie.Core.Configuration;
20 | using Miunie.Core.Entities.Discord;
21 | using Miunie.Core.Logging;
22 | using Miunie.Discord.Convertors;
23 | using Miunie.Discord.TypeReaders;
24 | using System;
25 | using System.Reflection;
26 | using System.Threading.Tasks;
27 |
28 | namespace Miunie.Discord
29 | {
30 | public class CommandHandler
31 | {
32 | private readonly CommandService _commandService;
33 | private readonly IDiscord _discord;
34 | private readonly IServiceProvider _services;
35 | private readonly ILogWriter _logger;
36 | private readonly EntityConvertor _convertor;
37 | private readonly IBotConfiguration _botConfig;
38 | private readonly ICommandProcessor _commandProcessor;
39 |
40 | public CommandHandler(IDiscord discord, IServiceProvider services, ILogWriter logger, EntityConvertor convertor, IBotConfiguration botConfig, ICommandProcessor commandProcessor)
41 | {
42 | _discord = discord;
43 | _commandService = new CommandService();
44 | _services = services;
45 | _logger = logger;
46 | _convertor = convertor;
47 | _botConfig = botConfig;
48 | _commandProcessor = commandProcessor;
49 | }
50 |
51 | public async Task InitializeAsync()
52 | {
53 | _commandService.AddTypeReader(typeof(MiunieUser), new MiunieUserTypeReader(_convertor));
54 |
55 | _discord.Client.MessageReceived += HandleCommandAsync;
56 | _discord.Client.MessageReceived += ProcessMessageAsync;
57 | _ = await _commandService.AddModulesAsync(Assembly.GetExecutingAssembly(), _services);
58 | }
59 |
60 | private Task ProcessMessageAsync(SocketMessage s)
61 | {
62 | if (s is SocketUserMessage msg)
63 | {
64 | var input = new CommandProcessorInput
65 | {
66 | Message = msg.Content,
67 | MessageId = msg.Id,
68 | ChannelId = msg.Channel.Id,
69 | GuildId = (msg.Author as SocketGuildUser)?.Guild.Id
70 | };
71 |
72 | return _commandProcessor.ProcessAsync(input);
73 | }
74 |
75 | return Task.CompletedTask;
76 | }
77 |
78 | private async Task HandleCommandAsync(SocketMessage s)
79 | {
80 | if (_botConfig.CommandsEnabled == false)
81 | {
82 | return;
83 | }
84 |
85 | if (!(s is SocketUserMessage msg))
86 | {
87 | return;
88 | }
89 |
90 | var argPos = 0;
91 | if (msg.HasMentionPrefix(_discord.Client.CurrentUser, ref argPos))
92 | {
93 | var context = new SocketCommandContext(_discord.Client, msg);
94 | await TryRunAsBotCommand(context, argPos).ConfigureAwait(false);
95 | }
96 | }
97 |
98 | private async Task TryRunAsBotCommand(SocketCommandContext context, int argPos)
99 | {
100 | var result = await _commandService.ExecuteAsync(context, argPos, _services);
101 |
102 | if (!result.IsSuccess)
103 | {
104 | _logger.Log($"Command execution failed. Reason: {result.ErrorReason}.");
105 | }
106 | }
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/Miunie.Discord/CommandModules/MiscCommands.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Discord.Commands;
17 | using Discord.WebSocket;
18 | using Miunie.Core;
19 | using Miunie.Discord.Convertors;
20 | using System.Threading.Tasks;
21 |
22 | namespace Miunie.Discord.CommandModules
23 | {
24 | public class MiscCommands : ModuleBase
25 | {
26 | private readonly MiscService _service;
27 | private readonly EntityConvertor _entityConvertor;
28 |
29 | public MiscCommands(MiscService service, EntityConvertor entityConvertor)
30 | {
31 | _service = service;
32 | _entityConvertor = entityConvertor;
33 | }
34 |
35 | [Command("what do you think?")]
36 | public async Task SendRandomYesNoMaybeAnswer()
37 | {
38 | var c = _entityConvertor.ConvertChannel(Context.Channel as SocketGuildChannel);
39 | await _service.SendRandomYesNoAnswerAsync(c);
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/Miunie.Discord/CommandModules/PrivacyCommand.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Discord.Commands;
17 | using Discord.WebSocket;
18 | using Miunie.Core;
19 | using Miunie.Discord.Convertors;
20 | using System.Threading.Tasks;
21 |
22 | namespace Miunie.Discord.CommandModules
23 | {
24 | public class PrivacyCommand : ModuleBase
25 | {
26 | private readonly EntityConvertor _entityConvertor;
27 | private readonly PrivacyService _service;
28 |
29 | public PrivacyCommand(PrivacyService service, EntityConvertor entityConvertor)
30 | {
31 | _entityConvertor = entityConvertor;
32 | _service = service;
33 | }
34 |
35 | [Command("personal data")]
36 | public async Task GetMyPersonalData()
37 | {
38 | var u = _entityConvertor.ConvertUser(Context.User as SocketGuildUser);
39 | await _service.OutputUserJsonDataAsync(u);
40 | }
41 |
42 | [Command("personal data remove")]
43 | public async Task RemoveMyPersonalData()
44 | {
45 | var u = _entityConvertor.ConvertUser(Context.User as SocketGuildUser);
46 | var c = _entityConvertor.ConvertChannel(Context.Channel as SocketGuildChannel);
47 | await _service.RemoveUserData(u, c);
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/Miunie.Discord/CommandModules/ProfileCommand.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Discord.Commands;
17 | using Discord.WebSocket;
18 | using Miunie.Core;
19 | using Miunie.Core.Entities.Discord;
20 | using Miunie.Discord.Convertors;
21 | using System.Threading.Tasks;
22 |
23 | namespace Miunie.Discord.CommandModules
24 | {
25 | public class ProfileCommand : ModuleBase
26 | {
27 | private readonly EntityConvertor _entityConvertor;
28 | private readonly ProfileService _profileService;
29 |
30 | public ProfileCommand(EntityConvertor entityConvertor, ProfileService profileService)
31 | {
32 | _entityConvertor = entityConvertor;
33 | _profileService = profileService;
34 | }
35 |
36 | [Command("profile")]
37 | public async Task ShowProfileAsync(MiunieUser user = null)
38 | {
39 | if (user is null)
40 | {
41 | user = _entityConvertor.ConvertUser(Context.User as SocketGuildUser);
42 | }
43 |
44 | var channel = _entityConvertor.ConvertChannel(Context.Channel as SocketGuildChannel);
45 | await _profileService.ShowProfileAsync(user, channel);
46 | }
47 |
48 | [Command("rep log")]
49 | public async Task ShowReputationLogAsync(int page = 1)
50 | {
51 | var source = _entityConvertor.ConvertUser(Context.User as SocketGuildUser);
52 | var channel = _entityConvertor.ConvertChannel(Context.Channel as SocketGuildChannel);
53 | await _profileService.ShowReputationLogAsync(source, page, channel);
54 | }
55 |
56 | [Command("rep log for")]
57 | public async Task ShowReputationLogAsync(MiunieUser user, int page = 1)
58 | {
59 | var channel = _entityConvertor.ConvertChannel(Context.Channel as SocketGuildChannel);
60 | await _profileService.ShowReputationLogAsync(user, page, channel);
61 | }
62 |
63 | [Command("+rep")]
64 | public async Task AddReputationAsync(MiunieUser user)
65 | {
66 | var source = _entityConvertor.ConvertUser(Context.User as SocketGuildUser);
67 | var channel = _entityConvertor.ConvertChannel(Context.Channel as SocketGuildChannel);
68 | await _profileService.GiveReputationAsync(source, user, channel);
69 | }
70 |
71 | [Command("-rep")]
72 | public async Task RemoveReputationAsync(MiunieUser user)
73 | {
74 | var source = _entityConvertor.ConvertUser(Context.User as SocketGuildUser);
75 | var channel = _entityConvertor.ConvertChannel(Context.Channel as SocketGuildChannel);
76 | await _profileService.RemoveReputationAsync(source, user, channel);
77 | }
78 |
79 | [Command("guild")]
80 | public async Task ShowGuildInfoAsync()
81 | {
82 | var guild = _entityConvertor.ConvertGuild(Context.Guild);
83 | var channel = _entityConvertor.ConvertChannel(Context.Channel as SocketGuildChannel);
84 | await _profileService.ShowGuildProfileAsync(guild, channel);
85 | }
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/Miunie.Discord/CommandModules/RemoteRepositoryCommand.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Discord.Commands;
17 | using Discord.WebSocket;
18 | using Miunie.Core;
19 | using Miunie.Discord.Convertors;
20 | using System.Threading.Tasks;
21 |
22 | namespace Miunie.Discord.CommandModules
23 | {
24 | public class RemoteRepositoryCommand : ModuleBase
25 | {
26 | private readonly RemoteRepositoryService _remoteRepoService;
27 | private readonly EntityConvertor _entityConvertor;
28 |
29 | public RemoteRepositoryCommand(RemoteRepositoryService remoteRepoService, EntityConvertor entityConvertor)
30 | {
31 | _remoteRepoService = remoteRepoService;
32 | _entityConvertor = entityConvertor;
33 | }
34 |
35 | [Command("repo")]
36 | [Summary("Shows the official remote repository hosting the code of this bot")]
37 | public async Task ShowRepository()
38 | {
39 | var channel = _entityConvertor.ConvertChannel(Context.Channel as SocketGuildChannel);
40 | await _remoteRepoService.ShowRepositoryAsync(channel);
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/Miunie.Discord/CommandModules/TimeCommand.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Discord;
17 | using Discord.Commands;
18 | using Discord.WebSocket;
19 | using Miunie.Core;
20 | using Miunie.Core.Entities.Discord;
21 | using Miunie.Discord.Convertors;
22 | using System;
23 | using System.Threading.Tasks;
24 |
25 | namespace Miunie.Discord.CommandModules
26 | {
27 | public class TimeCommand : ModuleBase
28 | {
29 | private readonly TimeService _service;
30 | private readonly EntityConvertor _entityConvertor;
31 |
32 | public TimeCommand(TimeService service, EntityConvertor entityConvertor)
33 | {
34 | _service = service;
35 | _entityConvertor = entityConvertor;
36 | }
37 |
38 | [Command("time for")]
39 | public async Task ShowTimeForUser(MiunieUser user)
40 | {
41 | var c = _entityConvertor.ConvertChannel(Context.Channel as SocketGuildChannel);
42 | await _service.OutputCurrentTimeForUserAsync(user, c);
43 | }
44 |
45 | [Command("time for")]
46 | public async Task ShowTimeForUserWithOffset(MiunieUser user, string verb, int units, string timeframe)
47 | {
48 | var c = _entityConvertor.ConvertChannel(Context.Channel as SocketGuildChannel);
49 | await _service.OutputFutureTimeForUserAsync(user, verb, units, timeframe, c);
50 | }
51 |
52 | [Command("time get")]
53 | public async Task ShowTimeForUserComparedToCurrentUser(DateTime requestTime, string verb, MiunieUser user)
54 | {
55 | var u = _entityConvertor.ConvertUser(Context.User as SocketGuildUser);
56 | var c = _entityConvertor.ConvertChannel(Context.Channel as SocketGuildChannel);
57 | await _service.OutputCurrentTimeComparedToInputForUserAsync(u, requestTime, verb, user, c);
58 | }
59 |
60 | [Command("time of")]
61 | public async Task ShowTimeForMessage(ulong messageId)
62 | {
63 | var m = await Context.Channel.GetMessageAsync(messageId);
64 | var ct = m?.CreatedAt;
65 | var et = m?.EditedTimestamp;
66 | var u = _entityConvertor.ConvertUser(Context.User as SocketGuildUser);
67 | var c = _entityConvertor.ConvertChannel(Context.Channel as SocketGuildChannel);
68 | await _service.OutputMessageTimeAsLocalAsync(messageId, ct, et, u, c);
69 | }
70 |
71 | [Command("time set")]
72 | public async Task SetMyTimeOffset(DateTime currentTime)
73 | {
74 | var u = _entityConvertor.ConvertUser(Context.User as SocketGuildUser);
75 | var c = _entityConvertor.ConvertChannel(Context.Channel as SocketGuildChannel);
76 | await _service.SetUtcOffsetForUserAsync(currentTime, u, c);
77 | }
78 |
79 | [RequireUserPermission(GuildPermission.Administrator)]
80 | [Command("time set for")]
81 | public async Task SetMyTimeOffset(MiunieUser user, DateTime currentTime)
82 | {
83 | var c = _entityConvertor.ConvertChannel(Context.Channel as SocketGuildChannel);
84 | await _service.SetUtcOffsetForUserByAdminAsync(currentTime, user, c);
85 | }
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/Miunie.Discord/Convertors/EntityConvertor.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Discord.WebSocket;
17 | using Miunie.Core.Entities.Discord;
18 | using Miunie.Core.Providers;
19 |
20 | namespace Miunie.Discord.Convertors
21 | {
22 | public class EntityConvertor
23 | {
24 | public EntityConvertor(IMiunieUserProvider miunieUserProvider)
25 | {
26 | ChannelConvertor = new MiunieChannelConvertor();
27 | UserConvertor = new MiunieUserConverter(miunieUserProvider);
28 | GuildConvertor = new MiunieGuildConvertor();
29 | }
30 |
31 | public MiunieChannelConvertor ChannelConvertor { get; }
32 |
33 | public MiunieUserConverter UserConvertor { get; }
34 |
35 | public MiunieGuildConvertor GuildConvertor { get; }
36 |
37 | public MiunieUser ConvertUser(SocketGuildUser m)
38 | => UserConvertor.DiscordMemberToMiunieUser(m);
39 |
40 | public MiunieChannel ConvertChannel(SocketGuildChannel c)
41 | => MiunieChannelConvertor.FromDiscordChannel(c);
42 |
43 | internal MiunieGuild ConvertGuild(SocketGuild g)
44 | => GuildConvertor.DiscordGuildToMiunieGuild(g);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/Miunie.Discord/Convertors/MiunieChannelConvertor.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Discord.WebSocket;
17 | using Miunie.Core.Entities.Discord;
18 | using System;
19 |
20 | namespace Miunie.Discord.Convertors
21 | {
22 | public class MiunieChannelConvertor
23 | {
24 | public static MiunieChannel FromDiscordChannel(SocketGuildChannel channel)
25 | {
26 | if (channel is null)
27 | {
28 | throw new ArgumentNullException(nameof(channel));
29 | }
30 |
31 | MiunieChannel miunieChannel;
32 | if (channel is default(SocketGuildChannel))
33 | {
34 | miunieChannel = default;
35 | }
36 | else
37 | {
38 | miunieChannel = new MiunieChannel()
39 | {
40 | ChannelId = channel.Id,
41 | GuildId = channel.Guild.Id
42 | };
43 | }
44 |
45 | return miunieChannel;
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/Miunie.Discord/Convertors/MiunieGuildConvertor.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Discord.WebSocket;
17 | using Miunie.Core.Entities.Discord;
18 | using System;
19 | using System.Linq;
20 |
21 | namespace Miunie.Discord.Convertors
22 | {
23 | public class MiunieGuildConvertor
24 | {
25 | public MiunieGuild DiscordGuildToMiunieGuild(SocketGuild g)
26 | => g != null ? new MiunieGuild
27 | {
28 | Id = g.Id,
29 | Name = g.Name,
30 | MemberCount = g.MemberCount,
31 | ChannelNames = g.Channels.Select(x => x.Name),
32 | TextChannelCount = g.Channels.Count(x => x is SocketTextChannel),
33 | VoiceChannelCount = g.Channels.Count(x => x is SocketVoiceChannel),
34 | CreationDate = g.CreatedAt.UtcDateTime,
35 | Roles = g.Roles.Select(r => r.DiscordRoleToMiunieRole()),
36 | IconUrl = g.IconUrl
37 | }
38 | : throw new ArgumentNullException(nameof(g));
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/Miunie.Discord/Convertors/MiunieRoleConvertor.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Discord.WebSocket;
17 | using Miunie.Core.Entities.Discord;
18 |
19 | namespace Miunie.Discord.Convertors
20 | {
21 | public static class MiunieRoleConvertor
22 | {
23 | public static MiunieRole DiscordRoleToMiunieRole(this SocketRole role)
24 | => new MiunieRole
25 | {
26 | Id = role.Id,
27 | Name = role.Name
28 | };
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/Miunie.Discord/Convertors/MiunieUserConverter.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Discord.WebSocket;
17 | using Miunie.Core.Entities.Discord;
18 | using Miunie.Core.Providers;
19 | using System;
20 | using System.Linq;
21 |
22 | namespace Miunie.Discord.Convertors
23 | {
24 | public class MiunieUserConverter
25 | {
26 | private readonly IMiunieUserProvider _userProvider;
27 |
28 | public MiunieUserConverter(IMiunieUserProvider userProvider)
29 | {
30 | _userProvider = userProvider;
31 | }
32 |
33 | public MiunieUser DiscordMemberToMiunieUser(SocketGuildUser user)
34 | {
35 | if (user is null)
36 | {
37 | throw new ArgumentNullException(nameof(user));
38 | }
39 |
40 | var mUser = _userProvider.GetById(user.Id, user.Guild.Id);
41 | mUser.Name = user.Nickname ?? user.Username;
42 | mUser.AvatarUrl = user.GetAvatarUrl();
43 | mUser.JoinedAt = user.JoinedAt?.UtcDateTime ?? default;
44 | mUser.CreatedAt = user.CreatedAt.UtcDateTime;
45 | mUser.IsBot = user.IsBot;
46 | mUser.Roles = user.Roles.Select(r => r.DiscordRoleToMiunieRole());
47 | _userProvider.StoreUser(mUser);
48 | return mUser;
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/Miunie.Discord/Embeds/EmbedConstructor.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Discord;
17 | using Miunie.Core.Entities;
18 | using Miunie.Core.Entities.Discord;
19 | using Miunie.Core.Providers;
20 | using System;
21 | using System.Collections.Generic;
22 | using System.Linq;
23 |
24 | namespace Miunie.Discord.Embeds
25 | {
26 | internal static class EmbedConstructor
27 | {
28 | private static readonly int RepLogPageSize = 10;
29 |
30 | public static Embed CreateReputationLog(IEnumerable entries, int index, ILanguageProvider lang)
31 | {
32 | var embed = Paginator.PaginateEmbed(
33 | entries,
34 | new EmbedBuilder()
35 | .WithColor(new Color(236, 64, 122))
36 | .WithTitle(lang.GetPhrase(PhraseKey.USER_EMBED_REP_LOG_TITLE.ToString())),
37 | index,
38 | RepLogPageSize,
39 | x => $"{(x.IsFromInvoker ? "**To:**" : "**From:**")} {x.TargetName} (**{FormatReputationType(x.Type)}**) {x.GivenAt:d} at {x.GivenAt:t} UTC");
40 |
41 | if (string.IsNullOrWhiteSpace(embed.Description))
42 | {
43 | _ = embed.WithDescription(lang.GetPhrase(PhraseKey.USER_EMBED_REP_LOG_EMPTY.ToString()));
44 | }
45 |
46 | return embed.Build();
47 | }
48 |
49 | public static Embed ToEmbed(this MiunieUser mUser, ILanguageProvider lang)
50 | {
51 | var realnessPhrase = lang.GetPhrase((mUser.IsBot ? PhraseKey.USER_EMBED_IS_BOT : PhraseKey.USER_EMBED_IS_HUMAN).ToString());
52 |
53 | return new EmbedBuilder()
54 | .WithColor(new Color(236, 64, 122))
55 | .WithTitle(lang.GetPhrase(PhraseKey.USER_EMBED_TITLE.ToString(), mUser.Name.ToUpper().ToPossessiveForm()))
56 | .WithThumbnailUrl(mUser.AvatarUrl)
57 | .AddField(lang.GetPhrase(PhraseKey.USER_EMBED_NAME_TITLE.ToString()), mUser.Name)
58 | .AddField(lang.GetPhrase(PhraseKey.USER_EMBED_REALNESS_TITLE.ToString()), realnessPhrase, true)
59 | .AddField(lang.GetPhrase(PhraseKey.USER_EMBED_REP_TITLE.ToString()), mUser.Reputation.Value.ToString(), true)
60 | .AddField(lang.GetPhrase(PhraseKey.USER_EMBED_ROLES_TITLE.ToString()), string.Join("\n", mUser.Roles.Select(r => r.Name)), true)
61 | .AddField(lang.GetPhrase(PhraseKey.USER_EMBED_JOINED_AT_TITLE.ToString()), $"{mUser.JoinedAt:d} at {mUser.JoinedAt:t} UTC")
62 | .AddField(lang.GetPhrase(PhraseKey.USER_EMBED_CREATED_AT_TITLE.ToString()), $"{mUser.CreatedAt:d} at {mUser.CreatedAt:t} UTC", true)
63 | .AddField(lang.GetPhrase(PhraseKey.USER_EMBED_TIME_TITLE.ToString()), mUser.UtcTimeOffset.HasValue ? lang.GetPhrase(PhraseKey.USER_EMBED_TIME.ToString(), DateTime.UtcNow + mUser.UtcTimeOffset) : lang.GetPhrase(PhraseKey.USER_EMBED_TIME_NOSET.ToString()), true)
64 | .Build();
65 | }
66 |
67 | public static Embed ToEmbed(this MiunieGuild mGuild, ILanguageProvider lang)
68 | => new EmbedBuilder()
69 | .WithColor(new Color(236, 64, 122))
70 | .WithThumbnailUrl(mGuild.IconUrl)
71 | .WithTitle(lang.GetPhrase(PhraseKey.GUILD_EMBED_TITLE.ToString()))
72 | .AddField(lang.GetPhrase(PhraseKey.GUILD_EMBED_NAME_TITLE.ToString()), mGuild.Name)
73 | .AddField(lang.GetPhrase(PhraseKey.GUILD_EMBED_STATS_TITLE.ToString()), mGuild.GetStats(), true)
74 | .AddField(lang.GetPhrase(PhraseKey.GUILD_EMBED_ROLES_TITLE.ToString()), string.Join(", ", mGuild.Roles.Select(r => r.Name.Replace("@", string.Empty))), true)
75 | .AddField(lang.GetPhrase(PhraseKey.GUILD_EMBED_CREATED_AT_TITLE.ToString()), $"{mGuild.CreationDate:d} at {mGuild.CreationDate:t} UTC")
76 | .Build();
77 |
78 | private static string ToPossessiveForm(this string s)
79 | => s.Last() == 'S'
80 | ? s + "'"
81 | : s + "'S";
82 |
83 | private static string FormatReputationType(ReputationType type)
84 | {
85 | switch (type)
86 | {
87 | case ReputationType.Plus:
88 | return "+1";
89 | case ReputationType.Minus:
90 | return "-1";
91 | default:
92 | throw new ArgumentException("Unknown ReputationType.");
93 | }
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/Miunie.Discord/Embeds/Paginator.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Discord;
17 | using System;
18 | using System.Collections.Generic;
19 | using System.Linq;
20 | using System.Text;
21 |
22 | namespace Miunie.Discord.Embeds
23 | {
24 | internal static class Paginator
25 | {
26 | public static IEnumerable GroupAt(IEnumerable set, int index, int pageSize, bool defaultOnOverflow = false)
27 | {
28 | int maxPages = GetPageCount(set.Count(), pageSize);
29 | if (index < 0 || index >= maxPages)
30 | {
31 | return set;
32 | }
33 |
34 | var remainder = set.Skip(pageSize * (index - 1));
35 |
36 | List group = new List();
37 | for (int i = 0; i < pageSize; i++)
38 | {
39 | if (defaultOnOverflow)
40 | {
41 | group.Add(remainder.ElementAtOrDefault(i));
42 | }
43 | else
44 | {
45 | if (remainder.Count() - 1 < i)
46 | {
47 | continue;
48 | }
49 | else
50 | {
51 | group.Add(remainder.ElementAt(i));
52 | }
53 | }
54 | }
55 |
56 | return group;
57 | }
58 |
59 | public static EmbedBuilder PaginateEmbed(IEnumerable set, EmbedBuilder embed, int index, int pageSize)
60 | {
61 | return embed.WithDescription(Paginate(set, index, pageSize))
62 | .WithFooter($"{(string.IsNullOrWhiteSpace(embed.Footer?.Text) ? string.Empty : $"{embed.Footer?.Text} | ")}{GetPageFooter(index, set.Count(), pageSize)}");
63 | }
64 |
65 | public static EmbedBuilder PaginateEmbed(IEnumerable set, EmbedBuilder embed, int index, int pageSize, Func writer)
66 | {
67 | return embed.WithDescription(Paginate(set, index, pageSize, writer))
68 | .WithFooter($"{(string.IsNullOrWhiteSpace(embed.Footer?.Text) ? string.Empty : $"{embed.Footer?.Text} | ")}{GetPageFooter(index, set.Count(), pageSize)}");
69 | }
70 |
71 | public static string Paginate(IEnumerable set, int index, int pageSize)
72 | {
73 | var group = GroupAt(set, index, pageSize);
74 | StringBuilder page = new StringBuilder();
75 |
76 | foreach (T item in group)
77 | {
78 | _ = page.AppendLine(item.ToString());
79 | }
80 |
81 | return page.ToString();
82 | }
83 |
84 | public static string Paginate(IEnumerable set, int index, int pageSize, Func writer)
85 | {
86 | var group = GroupAt(set, index, pageSize);
87 | StringBuilder page = new StringBuilder();
88 |
89 | foreach (T item in group)
90 | {
91 | _ = page.AppendLine(writer.Invoke(item));
92 | }
93 |
94 | return page.ToString();
95 | }
96 |
97 | private static string GetPageFooter(int index, int collectionSize, int pageSize)
98 | {
99 | return $"Page {index + 1} of {GetPageCount(collectionSize, pageSize)}";
100 | }
101 |
102 | private static int GetPageCount(int collectionSize, int pageSize)
103 | {
104 | return (int)Math.Ceiling((double)collectionSize / pageSize);
105 | }
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/Miunie.Discord/IDiscord.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Discord.WebSocket;
17 | using System.Threading.Tasks;
18 |
19 | namespace Miunie.Discord
20 | {
21 | public interface IDiscord
22 | {
23 | DiscordSocketClient Client { get; }
24 |
25 | Task InitializeAsync();
26 |
27 | void DisposeOfClient();
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/Miunie.Discord/Impersonation.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Discord;
17 | using Discord.WebSocket;
18 | using Miunie.Core.Discord;
19 | using Miunie.Core.Entities.Views;
20 | using Miunie.Core.Events;
21 | using Miunie.Core.Logging;
22 | using System;
23 | using System.Collections.Generic;
24 | using System.Linq;
25 | using System.Threading.Tasks;
26 |
27 | namespace Miunie.Discord
28 | {
29 | public class Impersonation : IDiscordImpersonation
30 | {
31 | private readonly IDiscord _discord;
32 | private readonly ILogWriter _logger;
33 |
34 | public Impersonation(IDiscord discord, ILogWriter logger)
35 | {
36 | _discord = discord;
37 | _logger = logger;
38 | }
39 |
40 | public event EventHandler MessageReceived;
41 |
42 | public IEnumerable GetAvailableGuilds()
43 | => _discord.Client?.Guilds.Select(g => new GuildView
44 | {
45 | Id = g.Id,
46 | IconUrl = g.IconUrl,
47 | Name = g.Name
48 | });
49 |
50 | public Task> GetAvailableTextChannelsAsync(ulong guildId)
51 | {
52 | if (guildId == 0) { return CompletedTextChannelViewTask(new TextChannelView[0]); }
53 |
54 | var guild = _discord.Client.GetGuild(guildId);
55 | var textChannels = guild.Channels
56 | .Where(IsViewableTextChannel)
57 | .Cast()
58 | .Select(ToTextChannelView);
59 |
60 | return CompletedTextChannelViewTask(textChannels);
61 | }
62 |
63 | public async Task> GetMessagesFromTextChannelAsync(ulong guildId, ulong channelId)
64 | {
65 | if (guildId == 0) { return new MessageView[0]; }
66 |
67 | var guild = _discord.Client.GetGuild(guildId);
68 | var textChannel = guild.Channels
69 | .Where(c => c.Id == channelId && IsViewableTextChannel(c))
70 | .Cast()
71 | .FirstOrDefault();
72 |
73 | if (textChannel == null) { return new MessageView[0]; }
74 |
75 | var result = new List();
76 |
77 | try
78 | {
79 | result.AddRange(await GetMessagesFrom(textChannel));
80 | }
81 | catch (Exception ex)
82 | {
83 | _logger.Log($"Miunie cannot read from the '{textChannel.Name}' channel. {ex.Message}");
84 | }
85 |
86 | return result;
87 | }
88 |
89 | public async Task SendTextToChannelAsync(string text, ulong id)
90 | {
91 | if (string.IsNullOrWhiteSpace(text)) { return; }
92 | var textChannel = _discord.Client.GetChannel(id) as SocketTextChannel;
93 | if (textChannel is null) { return; }
94 |
95 | _ = await textChannel.SendMessageAsync(text);
96 | }
97 |
98 | public void SubscribeForMessages()
99 | {
100 | _discord.Client.MessageReceived += Client_MessageReceivedHandler;
101 | }
102 |
103 | public void UnsubscribeForMessages()
104 | {
105 | _discord.Client.MessageReceived -= Client_MessageReceivedHandler;
106 | }
107 |
108 | private Task> CompletedTextChannelViewTask(IEnumerable channels)
109 | => Task.FromResult(channels);
110 |
111 | private TextChannelView ToTextChannelView(SocketTextChannel channel)
112 | => new TextChannelView
113 | {
114 | Id = channel.Id,
115 | Name = $"# {channel.Name}",
116 | Messages = new MessageView[0],
117 | CanSendMessages = CanSendMessagesTo(channel)
118 | };
119 |
120 | private bool CanSendMessagesTo(SocketTextChannel channel)
121 | => channel.GetUser(_discord.Client.CurrentUser.Id)?.GetPermissions(channel).SendMessages ?? false;
122 |
123 | private bool IsViewableTextChannel(SocketGuildChannel c)
124 | {
125 | if (!(c is SocketTextChannel)) { return false; }
126 |
127 | return c.GetUser(_discord.Client.CurrentUser.Id) != null;
128 | }
129 |
130 | private Task Client_MessageReceivedHandler(SocketMessage m)
131 | {
132 | MessageReceived?.Invoke(this, new MessageReceivedEventArgs(ToMessageView(m)));
133 |
134 | return Task.CompletedTask;
135 | }
136 |
137 | private async Task> GetMessagesFrom(SocketTextChannel channel)
138 | {
139 | var socketMessages = await channel.GetMessagesAsync(10).FlattenAsync();
140 |
141 | return socketMessages.Select(ToMessageView);
142 | }
143 |
144 | private MessageView ToMessageView(IMessage message) => new MessageView
145 | {
146 | ChannelId = message.Channel.Id,
147 | AuthorAvatarUrl = message.Author.GetAvatarUrl(),
148 | AuthorName = message.Author.Username,
149 | Content = message.Content,
150 | TimeStamp = message.CreatedAt.ToLocalTime()
151 | };
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/src/Miunie.Discord/Logging/DiscordLogger.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Discord;
17 | using Miunie.Core.Logging;
18 | using System.Threading.Tasks;
19 |
20 | namespace Miunie.Discord.Logging
21 | {
22 | public class DiscordLogger
23 | {
24 | private readonly ILogWriter _logger;
25 |
26 | public DiscordLogger(ILogWriter logger)
27 | {
28 | _logger = logger;
29 | }
30 |
31 | internal Task Log(LogMessage evt)
32 | {
33 | if (evt.Severity == LogSeverity.Critical)
34 | {
35 | _logger.LogError(evt.Message);
36 | }
37 | else
38 | {
39 | _logger.Log(evt.Message);
40 | }
41 |
42 | return Task.CompletedTask;
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/Miunie.Discord/Miunie.Discord.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 | GPL-3.0
6 | LICENSE
7 | https://github.com/control-net/Miunie
8 | https://github.com/control-net/Miunie
9 | git
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | True
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/Miunie.Discord/MiunieDiscord.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Discord;
17 | using Miunie.Core.Discord;
18 | using Miunie.Core.Entities.Discord;
19 | using Miunie.Core.Logging;
20 | using Miunie.Discord.Logging;
21 | using System;
22 | using System.Threading;
23 | using System.Threading.Tasks;
24 |
25 | namespace Miunie.Discord
26 | {
27 | public class MiunieDiscord : IDiscordConnection
28 | {
29 | private readonly IDiscord _discord;
30 | private readonly DiscordLogger _discordLogger;
31 | private readonly ILogWriter _logger;
32 | private readonly CommandHandler _commandHandler;
33 | private Core.Entities.ConnectionState _connectionState;
34 |
35 | public MiunieDiscord(IDiscord discord, DiscordLogger discordLogger, ILogWriter logger, CommandHandler commandHandler)
36 | {
37 | _discord = discord;
38 | _discordLogger = discordLogger;
39 | _logger = logger;
40 | _commandHandler = commandHandler;
41 |
42 | _connectionState = Core.Entities.ConnectionState.DISCONNECTED;
43 | }
44 |
45 | public event EventHandler ConnectionChanged;
46 |
47 | public Core.Entities.ConnectionState ConnectionState
48 | {
49 | get => _connectionState;
50 | private set
51 | {
52 | _connectionState = value;
53 | ConnectionChanged?.Invoke(this, EventArgs.Empty);
54 | }
55 | }
56 |
57 | public bool UserIsMiunie(MiunieUser user)
58 | => user.UserId == _discord.Client?.CurrentUser?.Id;
59 |
60 | public string GetBotAvatarUrl()
61 | => _discord.Client?.CurrentUser?.GetAvatarUrl();
62 |
63 | public async Task RunAsync(CancellationToken cancellationToken)
64 | {
65 | ConnectionState = Core.Entities.ConnectionState.CONNECTING;
66 |
67 | try
68 | {
69 | await _discord.InitializeAsync();
70 | _discord.Client.Log += _discordLogger.Log;
71 | _discord.Client.Ready += ClientOnReady;
72 | await _commandHandler.InitializeAsync();
73 | await _discord.Client.StartAsync();
74 | await Task.Delay(-1, cancellationToken);
75 | }
76 | catch (Exception ex)
77 | {
78 | if (_discord.Client != null)
79 | {
80 | await _discord.Client.LogoutAsync();
81 | _discord.DisposeOfClient();
82 | }
83 |
84 | _logger.LogError(ex.Message);
85 | }
86 | finally
87 | {
88 | ConnectionState = Core.Entities.ConnectionState.DISCONNECTED;
89 | }
90 | }
91 |
92 | private Task ClientOnReady()
93 | {
94 | _logger.Log("Client Ready");
95 | #if DEBUG
96 | _discord.Client.SetGameAsync("Herself being created.", type: ActivityType.Watching);
97 | #endif
98 | ConnectionState = Core.Entities.ConnectionState.CONNECTED;
99 | return Task.CompletedTask;
100 | }
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/Miunie.Discord/MiunieDiscordClient.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Discord;
17 | using Discord.WebSocket;
18 | using Miunie.Core.Configuration;
19 | using System;
20 | using System.Threading.Tasks;
21 |
22 | namespace Miunie.Discord
23 | {
24 | public class MiunieDiscordClient : IDiscord
25 | {
26 | private readonly IBotConfiguration _botConfig;
27 |
28 | public MiunieDiscordClient(IBotConfiguration botConfig)
29 | {
30 | _botConfig = botConfig;
31 | }
32 |
33 | public DiscordSocketClient Client { get; private set; }
34 |
35 | public async Task InitializeAsync()
36 | {
37 | if (string.IsNullOrWhiteSpace(_botConfig.DiscordToken))
38 | {
39 | throw new ArgumentNullException(nameof(_botConfig.DiscordToken));
40 | }
41 |
42 | Client = new DiscordSocketClient(new DiscordSocketConfig
43 | {
44 | LogLevel = LogSeverity.Info,
45 | });
46 |
47 | await Client.LoginAsync(TokenType.Bot, _botConfig.DiscordToken);
48 | }
49 |
50 | public void DisposeOfClient() => Client = null;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/Miunie.Discord/TypeReaders/MiunieUserTypeReader.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Discord;
17 | using Discord.Commands;
18 | using Discord.WebSocket;
19 | using Miunie.Discord.Convertors;
20 | using System;
21 | using System.Threading.Tasks;
22 |
23 | namespace Miunie.Discord.TypeReaders
24 | {
25 | public class MiunieUserTypeReader : TypeReader
26 | {
27 | private readonly EntityConvertor _convertor;
28 |
29 | public MiunieUserTypeReader(EntityConvertor convertor)
30 | {
31 | _convertor = convertor;
32 | }
33 |
34 | public override async Task ReadAsync(ICommandContext context, string input, IServiceProvider services)
35 | {
36 | var discordUserId = MentionUtils.TryParseUser(input, out var userId);
37 |
38 | if (await context.Guild.GetUserAsync(userId) is SocketGuildUser discordUser)
39 | {
40 | var miunieUserResult = _convertor.UserConvertor.DiscordMemberToMiunieUser(discordUser);
41 | return TypeReaderResult.FromSuccess(miunieUserResult);
42 | }
43 |
44 | return TypeReaderResult.FromError(CommandError.ParseFailed, "Input could not be parsed as a MiunieUser.");
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/Miunie.Infrastructure/Json/JsonConverter.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Json;
17 | using Newtonsoft.Json;
18 |
19 | namespace Miunie.Infrastructure.Json
20 | {
21 | public class JsonConverter : IJsonConverter
22 | {
23 | public string Serialize(T obj)
24 | {
25 | return JsonConvert.SerializeObject(obj);
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/Miunie.Infrastructure/LiteDbStorage/PersistentStorage.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using LiteDB;
17 | using Miunie.Core.Infrastructure;
18 | using Miunie.Core.Storage;
19 | using System;
20 | using System.Collections.Generic;
21 | using System.IO;
22 | using System.Linq;
23 | using System.Linq.Expressions;
24 |
25 | namespace Miunie.Infrastructure.LiteDbStorage
26 | {
27 | public class PersistentStorage : IPersistentStorage
28 | {
29 | private readonly string _dbFileName;
30 |
31 | public PersistentStorage(IFileSystem fileSystem)
32 | {
33 | _dbFileName = Path.Combine(fileSystem.DataStoragePath, "Miunie.db");
34 | }
35 |
36 | public IEnumerable RestoreMany(Expression> predicate)
37 | {
38 | using var db = new LiteDatabase(_dbFileName);
39 | var collection = db.GetCollection();
40 | return collection.Find(predicate);
41 | }
42 |
43 | public IEnumerable RestoreAll()
44 | {
45 | using var db = new LiteDatabase(_dbFileName);
46 | var collection = db.GetCollection();
47 | return collection.FindAll();
48 | }
49 |
50 | public T RestoreSingle(Expression> predicate)
51 | => RestoreMany(predicate).FirstOrDefault();
52 |
53 | public bool Exists(Expression> predicate)
54 | {
55 | using var db = new LiteDatabase(_dbFileName);
56 | var collection = db.GetCollection();
57 | return collection.Exists(predicate);
58 | }
59 |
60 | public void Store(T item)
61 | {
62 | using var db = new LiteDatabase(_dbFileName);
63 | var collection = db.GetCollection();
64 | _ = collection.Insert(item);
65 | }
66 |
67 | public void Update(T item)
68 | {
69 | using var db = new LiteDatabase(_dbFileName);
70 | var collection = db.GetCollection();
71 | _ = collection.Update(item);
72 | }
73 |
74 | public void Remove(Expression> predicate)
75 | {
76 | using var db = new LiteDatabase(_dbFileName);
77 | var collection = db.GetCollection();
78 | _ = collection.Delete(predicate);
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/Miunie.Infrastructure/Logging/ConsoleLogger.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Logging;
17 | using System;
18 |
19 | namespace Miunie.Infrastructure.Logging
20 | {
21 | public class ConsoleLogger : ILogWriter
22 | {
23 | public void Log(string message)
24 | {
25 | Console.WriteLine($"{DateTime.Now:G} - {message}");
26 | }
27 |
28 | public void LogError(string message)
29 | {
30 | Console.ForegroundColor = ConsoleColor.Red;
31 | Console.WriteLine($"{DateTime.Now:G} - {message}");
32 | Console.ResetColor();
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/Miunie.Infrastructure/Logging/InMemoryLogger.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Logging;
17 | using System;
18 | using System.Collections.Generic;
19 |
20 | namespace Miunie.Infrastructure.Logging
21 | {
22 | public class InMemoryLogger : ILogWriter, ILogReader
23 | {
24 | public event EventHandler LogRecieved;
25 |
26 | public List Logs { get; private set; } = new List();
27 |
28 | public void Log(string message)
29 | {
30 | Logs.Add(message);
31 | LogRecieved?.Invoke(this, EventArgs.Empty);
32 | }
33 |
34 | public void LogError(string message) => Log($"ERROR: {message}");
35 |
36 | public IEnumerable RetrieveLogs(int ammount = 5)
37 | {
38 | if (Logs.Count < ammount)
39 | {
40 | return Logs;
41 | }
42 |
43 | return Logs.GetRange(Logs.Count - ammount, ammount);
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/Miunie.Infrastructure/Miunie.Infrastructure.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | netstandard2.0
9 | GPL-3.0
10 | LICENSE
11 | https://github.com/control-net/Miunie
12 | https://github.com/control-net/Miunie
13 | git
14 |
15 |
16 |
17 |
18 | True
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/Miunie.Infrastructure/OS/SystemDateTime.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Infrastructure;
17 | using System;
18 |
19 | namespace Miunie.Infrastructure.OS
20 | {
21 | public class SystemDateTime : IDateTime
22 | {
23 | public DateTime UtcNow => DateTime.UtcNow;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/Miunie.Infrastructure/OS/SystemFileSystem.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Infrastructure;
17 | using System.IO;
18 | using System.Reflection;
19 |
20 | namespace Miunie.Infrastructure.OS
21 | {
22 | public class SystemFileSystem : IFileSystem
23 | {
24 | public SystemFileSystem()
25 | {
26 | DataStoragePath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
27 | }
28 |
29 | public string DataStoragePath { get; }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/Miunie.InversionOfControl/Container.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Microsoft.Extensions.DependencyInjection;
17 | using Miunie.Core.Attributes;
18 | using Miunie.Core.Commands;
19 | using Miunie.Core.Configuration;
20 | using Miunie.Core.Discord;
21 | using Miunie.Core.Entities;
22 | using Miunie.Core.Json;
23 | using Miunie.Core.Providers;
24 | using Miunie.Core.Storage;
25 | using Miunie.Discord;
26 | using Miunie.Discord.Adapters;
27 | using Miunie.Discord.Convertors;
28 | using Miunie.Discord.Logging;
29 | using Miunie.Infrastructure.Json;
30 | using Miunie.Infrastructure.LiteDbStorage;
31 | using System;
32 | using System.Linq;
33 | using System.Reflection;
34 |
35 | namespace Miunie.InversionOfControl
36 | {
37 | public static class Container
38 | {
39 | public static IServiceCollection AddMiunieTypes(this IServiceCollection collection)
40 | => collection.AddSingleton()
41 | .AddScoped()
42 | .AddSingleton()
43 | .AddSingleton()
44 | .AddScoped()
45 | .AddScoped()
46 | .AddSingleton()
47 | .AddSingleton()
48 | .AddSingleton()
49 | .AddSingleton()
50 | .AddSingleton()
51 | .AddSingleton()
52 | .AddSingleton()
53 | .AddScoped()
54 | .AddSingleton()
55 | .AddSingleton()
56 | .AddSingleton()
57 | .AddSingleton()
58 | .AddMiunieServices();
59 |
60 | private static IServiceCollection AddMiunieServices(this IServiceCollection collection)
61 | {
62 | var serviceAttributeType = typeof(ServiceAttribute);
63 | var serviceTypes = Assembly.GetAssembly(serviceAttributeType)
64 | .GetTypes()
65 | .Where(x => x.GetCustomAttributes(serviceAttributeType, true).Length > 0).ToList();
66 |
67 | serviceTypes.ForEach((x) =>
68 | {
69 | var attribute = x.GetCustomAttribute(serviceAttributeType) as ServiceAttribute;
70 | switch (attribute.ServiceType)
71 | {
72 | case ServiceType.SCOPED:
73 | _ = collection.AddScoped(x);
74 | break;
75 | case ServiceType.SINGLETON:
76 | _ = collection.AddSingleton(x);
77 | break;
78 | case ServiceType.TRANSIENT:
79 | _ = collection.AddTransient(x);
80 | break;
81 | default:
82 | break;
83 | }
84 | });
85 |
86 | return collection;
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/Miunie.InversionOfControl/Miunie.InversionOfControl.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 | GPL-3.0
6 | LICENSE
7 | https://github.com/control-net/Miunie
8 | https://github.com/control-net/Miunie
9 | git
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | True
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/Miunie.Tests/Commands/MessagePreconditonTests.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Commands;
17 | using Miunie.Core.Commands.PipelineSteps;
18 | using Miunie.Core.Configuration;
19 | using Moq;
20 | using System.Threading.Tasks;
21 | using Xunit;
22 |
23 | namespace Miunie.Tests.Commands
24 | {
25 | public class MessagePreconditonTests
26 | {
27 | [Fact]
28 | public async Task MessageWithNoPrefixIsIgnored()
29 | {
30 | var botConfig = CreateBotConfigWithPrefix("MyPrefix");
31 | var input = CreateInputWithMessage("Message without a prefix");
32 | var nextStep = new Mock();
33 | var step = new PreconditionCheckStep(nextStep.Object, botConfig);
34 |
35 | await step.ProcessAsync(input);
36 |
37 | AssertNextStepIsNotCalled(nextStep);
38 | }
39 |
40 | [Fact]
41 | public async Task MessageWithPrefixCallsNextStep()
42 | {
43 | const uint ExpectedPrefixOffset = 8;
44 | var botConfig = CreateBotConfigWithPrefix("MyPrefix");
45 | var input = CreateInputWithMessage("MyPrefix Message with a prefix");
46 | var nextStep = new Mock();
47 | var step = new PreconditionCheckStep(nextStep.Object, botConfig);
48 |
49 | await step.ProcessAsync(input);
50 |
51 | AssertNextStepIsCalled(nextStep);
52 | Assert.Equal(ExpectedPrefixOffset, input.PrefixOffset);
53 | }
54 |
55 | [Fact]
56 | public async Task NoPrefixSetIgnoreAllMessages()
57 | {
58 | const uint ExpectedPrefixOffset = 0;
59 | var botConfig = CreateBotConfigWithNoPrefix();
60 | var input = CreateInputWithMessage("Any Message");
61 | var nextStep = new Mock();
62 | var step = new PreconditionCheckStep(nextStep.Object, botConfig);
63 |
64 | await step.ProcessAsync(input);
65 |
66 | AssertNextStepIsCalled(nextStep);
67 | Assert.Equal(ExpectedPrefixOffset, input.PrefixOffset);
68 | }
69 |
70 | private void AssertNextStepIsNotCalled(Mock step)
71 | => step.Verify(s => s.ProcessAsync(It.IsAny()), Times.Never());
72 |
73 | private void AssertNextStepIsCalled(Mock step)
74 | => step.Verify(s => s.ProcessAsync(It.IsAny()), Times.Once());
75 |
76 | private IBotConfiguration CreateBotConfigWithPrefix(string prefix)
77 | => new BotConfiguration
78 | {
79 | CommandPrefix = prefix
80 | };
81 |
82 | private IBotConfiguration CreateBotConfigWithNoPrefix()
83 | => new BotConfiguration
84 | {
85 | CommandPrefix = string.Empty
86 | };
87 |
88 | private CommandProcessorInput CreateInputWithMessage(string message)
89 | => new CommandProcessorInput
90 | {
91 | Message = message
92 | };
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/src/Miunie.Tests/Data/DummyMiunieUsers.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Entities;
17 | using Miunie.Core.Entities.Discord;
18 | using System;
19 |
20 | namespace Miunie.Core.XUnit.Tests.Data
21 | {
22 | public class DummyMiunieUsers
23 | {
24 | public static readonly ulong DummyGuildId = 420;
25 |
26 | public MiunieUser Senne { get; private set; } = new MiunieUser
27 | {
28 | UserId = 69420911,
29 | GuildId = DummyGuildId,
30 | Name = "Senne",
31 | Reputation = new Reputation
32 | {
33 | Value = 55
34 | }
35 | };
36 |
37 | public MiunieUser Peter { get; private set; } = new MiunieUser
38 | {
39 | UserId = 182941761801420802,
40 | GuildId = DummyGuildId,
41 | Name = "Peter",
42 | Reputation = new Reputation
43 | {
44 | Value = 100
45 | }
46 | };
47 |
48 | public MiunieUser Drax { get; private set; } = new MiunieUser
49 | {
50 | UserId = 123456789,
51 | GuildId = DummyGuildId,
52 | Name = "Drax",
53 | Reputation = new Reputation
54 | {
55 | Value = -1
56 | }
57 | };
58 |
59 | public MiunieUser DraxWithUtcTimeOffSet { get; private set; } = new MiunieUser
60 | {
61 | UserId = 123456789,
62 | GuildId = DummyGuildId,
63 | Name = "Drax",
64 | UtcTimeOffset = new TimeSpan(0, 0, 0)
65 | };
66 |
67 | public MiunieUser PeterWithNoTimeSet { get; private set; } = new MiunieUser
68 | {
69 | UserId = 182941761801420802,
70 | GuildId = DummyGuildId,
71 | Name = "Peter"
72 | };
73 |
74 | public MiunieUser PeterWithUtcPlusOneHourTimeSet { get; private set; } = new MiunieUser
75 | {
76 | UserId = 123456789,
77 | GuildId = DummyGuildId,
78 | Name = "Drax",
79 | UtcTimeOffset = new TimeSpan(1, 0, 0)
80 | };
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/Miunie.Tests/Miunie.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 | false
6 | GPL-3.0
7 | LICENSE
8 | https://github.com/control-net/Miunie
9 | https://github.com/control-net/Miunie
10 | git
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | True
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/src/Miunie.Tests/MiunieDiscordClientTests.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Configuration;
17 | using Miunie.Discord;
18 | using System;
19 | using Xunit;
20 |
21 | namespace Miunie.Core.XUnit.Tests
22 | {
23 | public class MiunieDiscordClientTests
24 | {
25 | [Theory]
26 | [InlineData(null)]
27 | [InlineData("")]
28 | [InlineData(" ")]
29 | public void Initialize_ShouldThrowArgumentNullException_IfInvalidToken(string token)
30 | {
31 | IBotConfiguration config = new BotConfiguration
32 | {
33 | DiscordToken = token,
34 | CommandsEnabled = true
35 | };
36 | var client = new MiunieDiscordClient(config);
37 |
38 | _ = Assert.ThrowsAsync(client.InitializeAsync);
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/Miunie.Tests/MiunieDiscordTests.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Configuration;
17 | using Miunie.Discord;
18 | using Moq;
19 | using System.Threading;
20 | using System.Threading.Tasks;
21 | using Xunit;
22 |
23 | namespace Miunie.Core.XUnit.Tests
24 | {
25 | public class MiunieDiscordTests
26 | {
27 | [Fact]
28 | public async Task RunAsync_ShouldThrowException_IfInvalidToken()
29 | {
30 | var config = Mock.Of(c => c.DiscordToken == "ObviouslyFakeToken");
31 | var discord = new Mock(config);
32 |
33 | var miunie = new MiunieDiscord(discord.Object, null, null, null);
34 |
35 | var ex = await Record.ExceptionAsync(async () => await miunie.RunAsync(CancellationToken.None));
36 |
37 | Assert.NotNull(ex);
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/Miunie.Tests/Providers/MiunieUserProviderTests.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Entities;
17 | using Miunie.Core.Entities.Discord;
18 | using Miunie.Core.Providers;
19 | using Miunie.Core.Storage;
20 | using Miunie.Core.XUnit.Tests.Data;
21 | using Moq;
22 | using System;
23 | using System.Linq.Expressions;
24 | using Xunit;
25 |
26 | namespace Miunie.Core.XUnit.Tests.Providers
27 | {
28 | public class MiunieUserProviderTests
29 | {
30 | private readonly Mock _storageMock;
31 | private readonly MiunieUserProvider _userProvider;
32 | private readonly DummyMiunieUsers _users;
33 | private readonly Expression> _hasDraxIdAndGuildId;
34 |
35 | public MiunieUserProviderTests()
36 | {
37 | _storageMock = new Mock();
38 | _userProvider = new MiunieUserProvider(_storageMock.Object);
39 | _users = new DummyMiunieUsers();
40 | _hasDraxIdAndGuildId = u => u.UserId == _users.Drax.UserId && u.GuildId == _users.Drax.GuildId;
41 | }
42 |
43 | [Fact]
44 | public void GetById_ShouldFindAndReturnExpectedUser_IfUserFound()
45 | {
46 | var expected = _users.Drax;
47 | _ = _storageMock.Setup(s => s.RestoreSingle(It.IsAny>>()))
48 | .Returns(expected);
49 | _ = _storageMock.Setup(s => s.Store(It.IsAny()));
50 |
51 | var actual = _userProvider.GetById(expected.UserId, expected.GuildId);
52 |
53 | _storageMock.Verify(s => s.RestoreSingle(It.IsAny>>()), Times.Once);
54 | _storageMock.Verify(s => s.Store(It.Is(_hasDraxIdAndGuildId)), Times.Never);
55 | Assert.True(expected.UserId == actual.UserId && expected.GuildId == actual.GuildId);
56 | }
57 |
58 | [Theory]
59 | [InlineData(0, 0)]
60 | [InlineData(1234, 4321)]
61 | public void GetById_ShouldStoreAndReturnNewUser_IfUserNotFound(ulong userId, ulong guildID)
62 | {
63 | MiunieUser nullUser = null;
64 | _ = _storageMock.Setup(s => s.RestoreSingle(It.IsAny>>()))
65 | .Returns(nullUser);
66 | _ = _storageMock.Setup(s => s.Store(nullUser));
67 |
68 | var newUser = _userProvider.GetById(userId, guildID);
69 |
70 | _storageMock.Verify(s => s.RestoreSingle(It.IsAny>>()), Times.Once);
71 | _storageMock.Verify(s => s.Store(It.Is(u => u.UserId == userId && u.GuildId == guildID)), Times.Once);
72 | Assert.True(newUser.UserId == userId && newUser.GuildId == guildID);
73 | }
74 |
75 | [Fact]
76 | public void StoreUser_ShouldUpdateUser_IfUserExists()
77 | {
78 | _ = _storageMock.Setup(s => s.Store(It.IsAny()));
79 | _ = _storageMock.Setup(s => s.Update(It.IsAny()));
80 | _ = _storageMock.Setup(s => s.Exists(It.IsAny>>()))
81 | .Returns(true);
82 |
83 | _userProvider.StoreUser(_users.Drax);
84 |
85 | _storageMock.Verify(s => s.Exists(It.IsAny>>()), Times.Once);
86 | _storageMock.Verify(s => s.Update(It.IsAny()), Times.Once);
87 | _storageMock.Verify(s => s.Store(It.IsAny()), Times.Never);
88 | }
89 |
90 | [Fact]
91 | public void StoreUser_ShouldStoreUser_IfUserDoesntExist()
92 | {
93 | var user = new MiunieUser
94 | {
95 | GuildId = 0,
96 | UserId = 0,
97 | Reputation = new Reputation()
98 | };
99 | _ = _storageMock.Setup(s => s.Store(It.IsAny()));
100 | _ = _storageMock.Setup(s => s.Update(It.IsAny()));
101 | _ = _storageMock.Setup(s => s.Exists(It.IsAny>>()))
102 | .Returns(false);
103 |
104 | _userProvider.StoreUser(user);
105 |
106 | _storageMock.Verify(s => s.Exists(It.IsAny>>()), Times.Once);
107 | _storageMock.Verify(s => s.Store(It.IsAny()), Times.Once);
108 | _storageMock.Verify(s => s.Update(It.IsAny()), Times.Never);
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/src/Miunie.Tests/Providers/TimeManipulationProviderTests.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Providers;
17 | using Miunie.Core.XUnit.Tests.Data;
18 | using Moq;
19 | using System;
20 | using Xunit;
21 |
22 | namespace Miunie.Core.XUnit.Tests.Providers
23 | {
24 | public class TimeManipulationProviderTests
25 | {
26 | private readonly ITimeManipulationProvider _provider;
27 | private readonly DummyMiunieUsers _dummyUsers;
28 |
29 | public TimeManipulationProviderTests()
30 | {
31 | _provider = new TimeManipulationProvider();
32 | _dummyUsers = new DummyMiunieUsers();
33 | }
34 |
35 | [Fact]
36 | public void InvalidTimeFrame_ShouldReturnNull()
37 | {
38 | var result = _provider.GetTimeSpanFromString("IncorrectTimeFrame", It.IsAny());
39 |
40 | Assert.Null(result);
41 | }
42 |
43 | [Theory]
44 | [InlineData("hours", 1)]
45 | [InlineData("hrs", 10)]
46 | [InlineData("hr", 20)]
47 | [InlineData("hr", 30)]
48 | [InlineData("hours", 3000)]
49 | public void TimeFrameFromHours_ShouldReturnTimeSpanWithSetHours(string timeFrame, int amountOfHours)
50 | {
51 | var expected = new TimeSpan(amountOfHours, 0, 0);
52 | var actual = _provider.GetTimeSpanFromString(timeFrame, amountOfHours);
53 |
54 | Assert.Equal(expected, actual);
55 | }
56 |
57 | [Theory]
58 | [InlineData("minutes", 1)]
59 | [InlineData("minute", 10)]
60 | [InlineData("mins", 20)]
61 | [InlineData("min", 21)]
62 | public void TimeFrameFromMinutes_ShouldReturnTimeSpanWithSetMinutes(string timeFrame, int amountOfMinutes)
63 | {
64 | var expected = new TimeSpan(0, amountOfMinutes, 0);
65 | var actual = _provider.GetTimeSpanFromString(timeFrame, amountOfMinutes);
66 |
67 | Assert.Equal(expected, actual);
68 | }
69 |
70 | [Theory]
71 | [InlineData("seconds", 1)]
72 | [InlineData("second", 10)]
73 | [InlineData("secs", 20)]
74 | [InlineData("sec", 21)]
75 | public void TimeFrameFromSeconds_ShouldReturnTimeSpanWithSetSeconds(string timeFrame, int amountOfSeconds)
76 | {
77 | var expected = new TimeSpan(0, 0, amountOfSeconds);
78 | var actual = _provider.GetTimeSpanFromString(timeFrame, amountOfSeconds);
79 |
80 | Assert.Equal(expected, actual);
81 | }
82 |
83 | [Theory]
84 | [InlineData(-3)]
85 | [InlineData(0)]
86 | public void ZeroOrNegativeAmountOfTime_ShouldReturnNull(int amountOfTime)
87 | {
88 | const string validTimeFrame = "hours";
89 | var result = _provider.GetTimeSpanFromString(validTimeFrame, amountOfTime);
90 |
91 | Assert.Null(result);
92 | }
93 |
94 | [Fact]
95 | public void EnteredDateTimeIsNull_ReturnsNull()
96 | {
97 | var result = _provider.GetDateTimeLocalToUser(null, _dummyUsers.DraxWithUtcTimeOffSet);
98 |
99 | Assert.Null(result);
100 | }
101 |
102 | [Fact]
103 | public void UserHasNoTimeSet_ReturnsEnteredDateTime()
104 | {
105 | var expectedDateTime = DateTime.UtcNow;
106 |
107 | var actual = _provider.GetDateTimeLocalToUser(expectedDateTime, _dummyUsers.PeterWithNoTimeSet);
108 |
109 | Assert.Equal(expectedDateTime, actual);
110 | }
111 |
112 | [Fact]
113 | public void DateTimeNullAndUserTimeNotSet_ShouldReturnNull()
114 | {
115 | var result = _provider.GetDateTimeLocalToUser(null, _dummyUsers.PeterWithNoTimeSet);
116 |
117 | Assert.Null(result);
118 | }
119 |
120 | [Fact]
121 | public void ValidDateTimeAndUserTimeSet_ShouldReturnDateTimeBasedOnUsersLocalTime()
122 | {
123 | var testDateTime = DateTime.UtcNow;
124 | var expectedUtcPlusOneDateTime = testDateTime.AddHours(1);
125 |
126 | var actual = _provider.GetDateTimeLocalToUser(testDateTime, _dummyUsers.PeterWithUtcPlusOneHourTimeSet);
127 |
128 | Assert.Equal(expectedUtcPlusOneDateTime, actual);
129 | }
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/src/Miunie.Tests/Services/ProfileServiceReputationTests.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Discord;
17 | using Miunie.Core.Entities.Discord;
18 | using Miunie.Core.Logging;
19 | using Miunie.Core.Providers;
20 | using Miunie.Core.XUnit.Tests.Data;
21 | using Moq;
22 | using System;
23 | using System.Linq.Expressions;
24 | using System.Threading.Tasks;
25 | using Xunit;
26 |
27 | namespace Miunie.Core.XUnit.Tests.Services
28 | {
29 | public class ProfileServiceReputationTests
30 | {
31 | private readonly Mock _repProviderMock;
32 | private readonly ProfileService _profileService;
33 | private readonly DummyMiunieUsers _users;
34 |
35 | private readonly Expression> _hasDraxId;
36 | private readonly Expression> _hasSenneId;
37 |
38 | public ProfileServiceReputationTests()
39 | {
40 | _repProviderMock = new Mock();
41 | var discordMsgMock = new Mock();
42 | _profileService = new ProfileService(discordMsgMock.Object, _repProviderMock.Object, new Mock().Object, new Mock().Object);
43 | _users = new DummyMiunieUsers();
44 |
45 | _hasDraxId = u => u.UserId == _users.Drax.UserId;
46 | _hasSenneId = u => u.UserId == _users.Senne.UserId;
47 | }
48 |
49 | [Fact]
50 | public async Task GiveReputationAsync_ShouldCheckForTimeoutBeforeAdding()
51 | {
52 | await _profileService.GiveReputationAsync(_users.Drax, _users.Senne, new MiunieChannel());
53 |
54 | _repProviderMock.Verify(
55 | rp => rp.CanAddReputation(
56 | It.Is(_hasDraxId),
57 | It.Is(_hasSenneId)), Times.Once());
58 |
59 | _repProviderMock.Verify(
60 | rp => rp.AddReputation(
61 | It.Is(_hasDraxId),
62 | It.Is(_hasSenneId)), Times.Once());
63 | }
64 |
65 | [Fact]
66 | public async Task GiveReputationAsync_ShouldNotAddRepToSelf()
67 | {
68 | await _profileService.GiveReputationAsync(_users.Senne, _users.Senne, new MiunieChannel());
69 |
70 | // NOTE(Peter):
71 | // Makes sure the service didn't add reputation to self
72 | // and that it didn't bother with checking the timeout either.
73 | _repProviderMock.VerifyNoOtherCalls();
74 | }
75 |
76 | [Fact]
77 | public async Task GiveReputationAsync_ShouldCheckForTimeoutBeforeRemoving()
78 | {
79 | await _profileService.RemoveReputationAsync(_users.Drax, _users.Senne, new MiunieChannel());
80 |
81 | _repProviderMock.Verify(
82 | rp => rp.CanRemoveReputation(
83 | It.Is(_hasDraxId),
84 | It.Is(_hasSenneId)), Times.Once());
85 |
86 | _repProviderMock.Verify(
87 | rp => rp.RemoveReputation(
88 | It.Is(_hasDraxId),
89 | It.Is(_hasSenneId)), Times.Once());
90 | }
91 |
92 | [Fact]
93 | public async Task GiveReputationAsync_ShouldNotRemoveRepFromSelf()
94 | {
95 | await _profileService.RemoveReputationAsync(_users.Senne, _users.Senne, new MiunieChannel());
96 |
97 | _repProviderMock.VerifyNoOtherCalls();
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/src/Miunie.Tests/Services/ProfileServiceTests.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Discord;
17 | using Miunie.Core.Entities.Discord;
18 | using Moq;
19 | using System.Threading.Tasks;
20 | using Xunit;
21 |
22 | namespace Miunie.Core.XUnit.Tests.Services
23 | {
24 | public class ProfileServiceTests
25 | {
26 | private readonly Mock _msgMock;
27 | private readonly ProfileService _profileService;
28 |
29 | public ProfileServiceTests()
30 | {
31 | _msgMock = new Mock();
32 | _profileService = new ProfileService(_msgMock.Object, null, null, null);
33 | }
34 |
35 | [Fact]
36 | public async Task ShowProfileAsync_ShouldExecuteOnce()
37 | {
38 | _ = _msgMock.Setup(m => m.SendMessageAsync(It.IsAny(), It.IsAny()))
39 | .Returns(Task.CompletedTask);
40 |
41 | await _profileService.ShowProfileAsync(null, null);
42 |
43 | _msgMock.Verify(m => m.SendMessageAsync(It.IsAny(), It.IsAny()), Times.Once);
44 | }
45 |
46 | [Fact]
47 | public async Task ShowGuildProfileAsync_ShouldExecuteOnce()
48 | {
49 | _ = _msgMock.Setup(m => m.SendMessageAsync(It.IsAny(), It.IsAny()))
50 | .Returns(Task.CompletedTask);
51 |
52 | await _profileService.ShowGuildProfileAsync(null, null);
53 |
54 | _msgMock.Verify(m => m.SendMessageAsync(It.IsAny(), It.IsAny()), Times.Once);
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/Miunie.Tests/Services/TimeServiceTests.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Discord;
17 | using Miunie.Core.Entities;
18 | using Miunie.Core.Entities.Discord;
19 | using Miunie.Core.Infrastructure;
20 | using Miunie.Core.Providers;
21 | using Moq;
22 | using System;
23 | using System.Threading.Tasks;
24 | using Xunit;
25 |
26 | namespace Miunie.Core.XUnit.Tests.Services
27 | {
28 | public class TimeServiceTests
29 | {
30 | private readonly Mock _messages;
31 | private readonly Mock _dateTime;
32 | private readonly Mock _users;
33 | private readonly Mock _timeManipulator;
34 | private readonly TimeService _service;
35 |
36 | public TimeServiceTests()
37 | {
38 | _messages = new Mock();
39 | _dateTime = new Mock();
40 | _users = new Mock();
41 | _timeManipulator = new Mock();
42 | _service = new TimeService(_messages.Object, _dateTime.Object, _users.Object, _timeManipulator.Object);
43 | }
44 |
45 | [Fact]
46 | public async Task NoTimezoneInfo_ShouldOutputWarning()
47 | {
48 | var channel = CreateTestChannel();
49 | var user = CreateUserWithoutOffset();
50 |
51 | await _service.OutputCurrentTimeForUserAsync(user, channel);
52 |
53 | AssertNoTimezoneInfoSent();
54 | AssertNoOtherMessages();
55 | }
56 |
57 | [Fact]
58 | public async Task CorrectOffset_ShouldOutputCorrectTime()
59 | {
60 | var channel = CreateTestChannel();
61 | var user = CreateUserWithOffset(TimeSpan.FromHours(2));
62 | SetCurrentTime(new DateTime(2020, 2, 21, 20, 30, 0));
63 | var expectedTime = new DateTime(2020, 2, 21, 22, 30, 0);
64 |
65 | await _service.OutputCurrentTimeForUserAsync(user, channel);
66 |
67 | AssertCorrectTimeInfoSent(expectedTime);
68 | AssertNoOtherMessages();
69 | }
70 |
71 | [Fact]
72 | public async Task SettingNewOffset_ShouldSaveAndOutputInfo()
73 | {
74 | SetCurrentTime(new DateTime(2020, 2, 22, 10, 59, 4));
75 | var channel = CreateTestChannel();
76 | var user = CreateUserWithoutOffset();
77 | var enteredDateTime = new DateTime(1, 1, 1, 8, 0, 0);
78 | var expectedOffset = TimeSpan.FromHours(-2);
79 |
80 | await _service.SetUtcOffsetForUserAsync(enteredDateTime, user, channel);
81 |
82 | AssertOffsetChangedInfoSent();
83 | AssertUserWithOffsetSaved(expectedOffset);
84 | AssertNoOtherMessages();
85 | }
86 |
87 | private MiunieChannel CreateTestChannel()
88 | {
89 | return new MiunieChannel
90 | {
91 | ChannelId = 10,
92 | GuildId = 900
93 | };
94 | }
95 |
96 | private MiunieUser CreateUserWithoutOffset()
97 | {
98 | return new MiunieUser
99 | {
100 | Name = "User",
101 | UtcTimeOffset = null
102 | };
103 | }
104 |
105 | private MiunieUser CreateUserWithOffset(TimeSpan offset)
106 | {
107 | return new MiunieUser
108 | {
109 | Name = "User",
110 | UtcTimeOffset = offset
111 | };
112 | }
113 |
114 | private void AssertOffsetChangedInfoSent()
115 | {
116 | _messages.Verify(m => m.SendMessageAsync(It.IsAny(), It.Is(pk => pk == PhraseKey.TIME_NEW_OFFSET_SET)));
117 | }
118 |
119 | private void AssertUserWithOffsetSaved(TimeSpan expectedOffset)
120 | {
121 | _users.Verify(u => u.StoreUser(It.Is(u => u.UtcTimeOffset == expectedOffset)));
122 | }
123 |
124 | private void AssertCorrectTimeInfoSent(DateTime expectedTime)
125 | {
126 | _messages.Verify(m => m.SendMessageAsync(It.IsAny(), It.Is(pk => pk == PhraseKey.TIME_TIMEZONE_INFO), It.IsAny(), It.Is(dt => dt == expectedTime)));
127 | }
128 |
129 | private void AssertNoTimezoneInfoSent()
130 | {
131 | _messages.Verify(m => m.SendMessageAsync(It.IsAny(), It.Is(pk => pk == PhraseKey.TIME_NO_TIMEZONE_INFO), It.IsAny()));
132 | }
133 |
134 | private void AssertNoOtherMessages()
135 | => _messages.VerifyNoOtherCalls();
136 |
137 | private void SetCurrentTime(DateTime dateTime)
138 | => _dateTime.Setup(dt => dt.UtcNow).Returns(dateTime);
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/src/Miunie.Tests/Services/YesNoServiceTests.cs:
--------------------------------------------------------------------------------
1 | // This file is part of Miunie.
2 | //
3 | // Miunie is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Miunie is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Miunie. If not, see .
15 |
16 | using Miunie.Core.Discord;
17 | using Miunie.Core.Entities;
18 | using Miunie.Core.Entities.Discord;
19 | using Moq;
20 | using System.Threading.Tasks;
21 | using Xunit;
22 |
23 | namespace Miunie.Core.XUnit.Tests.Services
24 | {
25 | public class YesNoServiceTests
26 | {
27 | [Fact]
28 | public async Task YesNo_ShouldDelegateProperly()
29 | {
30 | var messagesMock = new Mock();
31 | var service = new MiscService(messagesMock.Object);
32 |
33 | await service.SendRandomYesNoAnswerAsync(new MiunieChannel()).ConfigureAwait(false);
34 |
35 | messagesMock.Verify(m => m.SendMessageAsync(It.IsAny(), It.Is(pk => pk == PhraseKey.YES_NO_MAYBE)));
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/Miunie.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26124.0
5 | MinimumVisualStudioVersion = 15.0.26124.0
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Miunie.Core", "Miunie.Core\Miunie.Core.csproj", "{34A2664F-DB7E-45B1-8C6E-E5B9671337E8}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Miunie.Discord", "Miunie.Discord\Miunie.Discord.csproj", "{6677E885-5BB7-43D2-A2CE-0DE987F63367}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Miunie.Infrastructure", "Miunie.Infrastructure\Miunie.Infrastructure.csproj", "{792F5374-DDDD-464D-8C1B-F6BCB075397C}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Miunie.InversionOfControl", "Miunie.InversionOfControl\Miunie.InversionOfControl.csproj", "{396442A6-DB98-40D8-98D0-0432ABD1329E}"
13 | EndProject
14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Miunie.Tests", "Miunie.Tests\Miunie.Tests.csproj", "{63FF7E44-2237-4C38-97F3-F06DA9567447}"
15 | EndProject
16 | Global
17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
18 | Debug|Any CPU = Debug|Any CPU
19 | Debug|x64 = Debug|x64
20 | Debug|x86 = Debug|x86
21 | Release|Any CPU = Release|Any CPU
22 | Release|x64 = Release|x64
23 | Release|x86 = Release|x86
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
29 | {34A2664F-DB7E-45B1-8C6E-E5B9671337E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
30 | {34A2664F-DB7E-45B1-8C6E-E5B9671337E8}.Debug|Any CPU.Build.0 = Debug|Any CPU
31 | {34A2664F-DB7E-45B1-8C6E-E5B9671337E8}.Debug|x64.ActiveCfg = Debug|Any CPU
32 | {34A2664F-DB7E-45B1-8C6E-E5B9671337E8}.Debug|x64.Build.0 = Debug|Any CPU
33 | {34A2664F-DB7E-45B1-8C6E-E5B9671337E8}.Debug|x86.ActiveCfg = Debug|Any CPU
34 | {34A2664F-DB7E-45B1-8C6E-E5B9671337E8}.Debug|x86.Build.0 = Debug|Any CPU
35 | {34A2664F-DB7E-45B1-8C6E-E5B9671337E8}.Release|Any CPU.ActiveCfg = Release|Any CPU
36 | {34A2664F-DB7E-45B1-8C6E-E5B9671337E8}.Release|Any CPU.Build.0 = Release|Any CPU
37 | {34A2664F-DB7E-45B1-8C6E-E5B9671337E8}.Release|x64.ActiveCfg = Release|Any CPU
38 | {34A2664F-DB7E-45B1-8C6E-E5B9671337E8}.Release|x64.Build.0 = Release|Any CPU
39 | {34A2664F-DB7E-45B1-8C6E-E5B9671337E8}.Release|x86.ActiveCfg = Release|Any CPU
40 | {34A2664F-DB7E-45B1-8C6E-E5B9671337E8}.Release|x86.Build.0 = Release|Any CPU
41 | {6677E885-5BB7-43D2-A2CE-0DE987F63367}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
42 | {6677E885-5BB7-43D2-A2CE-0DE987F63367}.Debug|Any CPU.Build.0 = Debug|Any CPU
43 | {6677E885-5BB7-43D2-A2CE-0DE987F63367}.Debug|x64.ActiveCfg = Debug|Any CPU
44 | {6677E885-5BB7-43D2-A2CE-0DE987F63367}.Debug|x64.Build.0 = Debug|Any CPU
45 | {6677E885-5BB7-43D2-A2CE-0DE987F63367}.Debug|x86.ActiveCfg = Debug|Any CPU
46 | {6677E885-5BB7-43D2-A2CE-0DE987F63367}.Debug|x86.Build.0 = Debug|Any CPU
47 | {6677E885-5BB7-43D2-A2CE-0DE987F63367}.Release|Any CPU.ActiveCfg = Release|Any CPU
48 | {6677E885-5BB7-43D2-A2CE-0DE987F63367}.Release|Any CPU.Build.0 = Release|Any CPU
49 | {6677E885-5BB7-43D2-A2CE-0DE987F63367}.Release|x64.ActiveCfg = Release|Any CPU
50 | {6677E885-5BB7-43D2-A2CE-0DE987F63367}.Release|x64.Build.0 = Release|Any CPU
51 | {6677E885-5BB7-43D2-A2CE-0DE987F63367}.Release|x86.ActiveCfg = Release|Any CPU
52 | {6677E885-5BB7-43D2-A2CE-0DE987F63367}.Release|x86.Build.0 = Release|Any CPU
53 | {792F5374-DDDD-464D-8C1B-F6BCB075397C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
54 | {792F5374-DDDD-464D-8C1B-F6BCB075397C}.Debug|Any CPU.Build.0 = Debug|Any CPU
55 | {792F5374-DDDD-464D-8C1B-F6BCB075397C}.Debug|x64.ActiveCfg = Debug|Any CPU
56 | {792F5374-DDDD-464D-8C1B-F6BCB075397C}.Debug|x64.Build.0 = Debug|Any CPU
57 | {792F5374-DDDD-464D-8C1B-F6BCB075397C}.Debug|x86.ActiveCfg = Debug|Any CPU
58 | {792F5374-DDDD-464D-8C1B-F6BCB075397C}.Debug|x86.Build.0 = Debug|Any CPU
59 | {792F5374-DDDD-464D-8C1B-F6BCB075397C}.Release|Any CPU.ActiveCfg = Release|Any CPU
60 | {792F5374-DDDD-464D-8C1B-F6BCB075397C}.Release|Any CPU.Build.0 = Release|Any CPU
61 | {792F5374-DDDD-464D-8C1B-F6BCB075397C}.Release|x64.ActiveCfg = Release|Any CPU
62 | {792F5374-DDDD-464D-8C1B-F6BCB075397C}.Release|x64.Build.0 = Release|Any CPU
63 | {792F5374-DDDD-464D-8C1B-F6BCB075397C}.Release|x86.ActiveCfg = Release|Any CPU
64 | {792F5374-DDDD-464D-8C1B-F6BCB075397C}.Release|x86.Build.0 = Release|Any CPU
65 | {396442A6-DB98-40D8-98D0-0432ABD1329E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
66 | {396442A6-DB98-40D8-98D0-0432ABD1329E}.Debug|Any CPU.Build.0 = Debug|Any CPU
67 | {396442A6-DB98-40D8-98D0-0432ABD1329E}.Debug|x64.ActiveCfg = Debug|Any CPU
68 | {396442A6-DB98-40D8-98D0-0432ABD1329E}.Debug|x64.Build.0 = Debug|Any CPU
69 | {396442A6-DB98-40D8-98D0-0432ABD1329E}.Debug|x86.ActiveCfg = Debug|Any CPU
70 | {396442A6-DB98-40D8-98D0-0432ABD1329E}.Debug|x86.Build.0 = Debug|Any CPU
71 | {396442A6-DB98-40D8-98D0-0432ABD1329E}.Release|Any CPU.ActiveCfg = Release|Any CPU
72 | {396442A6-DB98-40D8-98D0-0432ABD1329E}.Release|Any CPU.Build.0 = Release|Any CPU
73 | {396442A6-DB98-40D8-98D0-0432ABD1329E}.Release|x64.ActiveCfg = Release|Any CPU
74 | {396442A6-DB98-40D8-98D0-0432ABD1329E}.Release|x64.Build.0 = Release|Any CPU
75 | {396442A6-DB98-40D8-98D0-0432ABD1329E}.Release|x86.ActiveCfg = Release|Any CPU
76 | {396442A6-DB98-40D8-98D0-0432ABD1329E}.Release|x86.Build.0 = Release|Any CPU
77 | {63FF7E44-2237-4C38-97F3-F06DA9567447}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
78 | {63FF7E44-2237-4C38-97F3-F06DA9567447}.Debug|Any CPU.Build.0 = Debug|Any CPU
79 | {63FF7E44-2237-4C38-97F3-F06DA9567447}.Debug|x64.ActiveCfg = Debug|Any CPU
80 | {63FF7E44-2237-4C38-97F3-F06DA9567447}.Debug|x64.Build.0 = Debug|Any CPU
81 | {63FF7E44-2237-4C38-97F3-F06DA9567447}.Debug|x86.ActiveCfg = Debug|Any CPU
82 | {63FF7E44-2237-4C38-97F3-F06DA9567447}.Debug|x86.Build.0 = Debug|Any CPU
83 | {63FF7E44-2237-4C38-97F3-F06DA9567447}.Release|Any CPU.ActiveCfg = Release|Any CPU
84 | {63FF7E44-2237-4C38-97F3-F06DA9567447}.Release|Any CPU.Build.0 = Release|Any CPU
85 | {63FF7E44-2237-4C38-97F3-F06DA9567447}.Release|x64.ActiveCfg = Release|Any CPU
86 | {63FF7E44-2237-4C38-97F3-F06DA9567447}.Release|x64.Build.0 = Release|Any CPU
87 | {63FF7E44-2237-4C38-97F3-F06DA9567447}.Release|x86.ActiveCfg = Release|Any CPU
88 | {63FF7E44-2237-4C38-97F3-F06DA9567447}.Release|x86.Build.0 = Release|Any CPU
89 | EndGlobalSection
90 | EndGlobal
91 |
--------------------------------------------------------------------------------
/src/stylecop.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
3 | "settings": {
4 | "documentationRules": {
5 | "companyName": "PlaceholderCompany",
6 | "copyrightText": "This file is part of Miunie.\n\n Miunie is free software: you can redistribute it and/or modify\n it under the terms of the GNU General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Miunie is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License\n along with Miunie. If not, see .",
7 | "xmlHeader": false,
8 | "headerDecoration": "-----------------------------------------------------------------------",
9 | "documentExposedElements": false,
10 | "documentInternalElements": false,
11 | "documentPrivateElements": false,
12 | "documentInterfaces": false
13 | },
14 | "orderingRules": {
15 | "usingDirectivesPlacement": "outsideNamespace",
16 | "systemUsingDirectivesFirst": false,
17 | "blankLinesBetweenUsingGroups": "omit"
18 | },
19 | "layoutRules": {
20 | "newlineAtEndOfFile": "require"
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------