Compare commits
3 commits
master
...
GeekbotBas
Author | SHA1 | Date | |
---|---|---|---|
7fb88bd106 | |||
295a1d575d | |||
8d9c436cfc |
401 changed files with 5619 additions and 11740 deletions
38
.deploy.yml
38
.deploy.yml
|
@ -1,38 +0,0 @@
|
||||||
---
|
|
||||||
- name: Geekbot Deploy
|
|
||||||
hosts: all
|
|
||||||
remote_user: geekbot
|
|
||||||
vars:
|
|
||||||
ansible_port: 65432
|
|
||||||
ansible_python_interpreter: /usr/bin/python3
|
|
||||||
tasks:
|
|
||||||
- name: Login to Gitlab Docker Registry
|
|
||||||
'community.docker.docker_login':
|
|
||||||
registry_url: "{{ lookup('env', 'CI_REGISTRY') }}"
|
|
||||||
username: "{{ lookup('env', 'CI_REGISTRY_USER') }}"
|
|
||||||
password: "{{ lookup('env', 'CI_REGISTRY_PASSWORD') }}"
|
|
||||||
reauthorize: yes
|
|
||||||
- name: Replace Prod Container
|
|
||||||
'community.docker.docker_container':
|
|
||||||
name: GeekbotProd
|
|
||||||
image: "{{ lookup('env', 'IMAGE_TAG') }}"
|
|
||||||
recreate: yes
|
|
||||||
pull: yes
|
|
||||||
restart_policy: always
|
|
||||||
keep_volumes: no
|
|
||||||
ports:
|
|
||||||
- "12995:12995"
|
|
||||||
env:
|
|
||||||
GEEKBOT_DB_HOST: "{{ lookup('env', 'GEEKBOT_DB_HOST') }}"
|
|
||||||
GEEKBOT_DB_USER: "{{ lookup('env', 'GEEKBOT_DB_USER') }}"
|
|
||||||
GEEKBOT_DB_PASSWORD: "{{ lookup('env', 'GEEKBOT_DB_PASSWORD') }}"
|
|
||||||
GEEKBOT_DB_PORT: "{{ lookup('env', 'GEEKBOT_DB_PORT') }}"
|
|
||||||
GEEKBOT_DB_DATABASE: "{{ lookup('env', 'GEEKBOT_DB_DATABASE') }}"
|
|
||||||
GEEKBOT_DB_REQUIRE_SSL: "true"
|
|
||||||
GEEKBOT_DB_TRUST_CERT: "true"
|
|
||||||
GEEKBOT_SUMOLOGIC: "{{ lookup('env', 'GEEKBOT_SUMOLOCIG') }}"
|
|
||||||
GEEKBOT_SENTRY: "{{ lookup('env', 'GEEKBOT_SENTRY') }}"
|
|
||||||
GEEKBOT_DB_REDSHIFT_COMPAT: "true"
|
|
||||||
- name: Cleanup Old Container
|
|
||||||
'community.docker.docker_prune':
|
|
||||||
images: yes
|
|
18
.gitignore
vendored
18
.gitignore
vendored
|
@ -1,10 +1,16 @@
|
||||||
/*/**/bin
|
Geekbot.net/bin
|
||||||
/*/**/obj
|
Geekbot.net/obj
|
||||||
src/Bot/tmp/
|
Geekbot.net/tmp/
|
||||||
src/Bot/Logs/*
|
Tests/bin
|
||||||
!/src/Bot/Logs/.keep
|
Tests/obj
|
||||||
|
Backup/
|
||||||
.vs/
|
.vs/
|
||||||
|
UpgradeLog.htm
|
||||||
.idea
|
.idea
|
||||||
.vscode
|
.vscode
|
||||||
|
Geekbot.net/Logs/*
|
||||||
|
!/Geekbot.net/Logs/.keep
|
||||||
Geekbot.net.sln.DotSettings.user
|
Geekbot.net.sln.DotSettings.user
|
||||||
app
|
Geekbot.net/temp/
|
||||||
|
WikipediaApi/bin/
|
||||||
|
WikipediaApi/obj/
|
||||||
|
|
|
@ -1,69 +1,65 @@
|
||||||
stages:
|
stages:
|
||||||
- build
|
- build
|
||||||
- docker
|
|
||||||
- deploy
|
|
||||||
- ops
|
- ops
|
||||||
|
- deploy
|
||||||
|
|
||||||
variables:
|
before_script:
|
||||||
VERSION: 4.4.0-V$CI_COMMIT_SHORT_SHA
|
- set -e
|
||||||
IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
|
- set -u
|
||||||
|
- set -o pipefail
|
||||||
|
|
||||||
Build:
|
build:
|
||||||
stage: build
|
stage: build
|
||||||
image: mcr.microsoft.com/dotnet/sdk:6.0
|
image: mcr.microsoft.com/dotnet/core/sdk:2.2
|
||||||
artifacts:
|
artifacts:
|
||||||
expire_in: 1h
|
expire_in: 1h
|
||||||
paths:
|
paths:
|
||||||
- app
|
- Geekbot.net/Binaries/
|
||||||
script:
|
script:
|
||||||
- dotnet restore
|
- dotnet restore -s https://api.nuget.org/v3/index.json -s https://www.myget.org/F/discord-net/api/v3/index.json
|
||||||
- dotnet test tests
|
- dotnet test Tests
|
||||||
- dotnet publish --version-suffix "$VERSION" -r linux-x64 -c Release -p:DebugType=embedded --no-self-contained -o ./app ./src/Startup/
|
- dotnet publish --version-suffix ${CI_COMMIT_SHA:0:8} --configuration Release -o Binaries ./
|
||||||
|
|
||||||
Package:
|
sentry:
|
||||||
stage: docker
|
|
||||||
image: docker
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
services:
|
|
||||||
- docker:stable-dind
|
|
||||||
script:
|
|
||||||
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
|
||||||
- docker build -t $IMAGE_TAG .
|
|
||||||
- docker push $IMAGE_TAG
|
|
||||||
|
|
||||||
Deploy:
|
|
||||||
stage: deploy
|
|
||||||
image: quay.io/ansible/ansible-runner:stable-2.12-latest
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
variables:
|
|
||||||
ANSIBLE_NOCOWS: 1
|
|
||||||
before_script:
|
|
||||||
- mkdir /root/.ssh
|
|
||||||
- cp $SSH_PRIVATE_KEY /root/.ssh/id_ed25519
|
|
||||||
- cp $SSH_PUBLIC_KEY /root/.ssh/id_ed25519.pub
|
|
||||||
- chmod -R 600 /root/.ssh
|
|
||||||
- ssh-keyscan -p 65432 $PROD_IP > /root/.ssh/known_hosts
|
|
||||||
script:
|
|
||||||
- ansible-galaxy collection install -r ansible-requirements.yml
|
|
||||||
- ansible-playbook -i $PROD_IP, .deploy.yml
|
|
||||||
|
|
||||||
Sentry:
|
|
||||||
stage: ops
|
stage: ops
|
||||||
image: getsentry/sentry-cli
|
image: getsentry/sentry-cli
|
||||||
allow_failure: true
|
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
script:
|
dependencies:
|
||||||
- sentry-cli releases new -p geekbot $VERSION
|
- build
|
||||||
- sentry-cli releases set-commits --auto $VERSION
|
script:
|
||||||
- sentry-cli releases deploys $VERSION new -e Production
|
- sentry-cli releases new -p geekbot 4.1.0-${CI_COMMIT_SHA:0:8}
|
||||||
|
- sentry-cli releases set-commits --auto 4.1.0-${CI_COMMIT_SHA:0:8}
|
||||||
|
- sentry-cli releases deploys 4.1.0-${CI_COMMIT_SHA:0:8} new -e Production
|
||||||
|
|
||||||
Github Mirror:
|
deploy:
|
||||||
stage: ops
|
stage: deploy
|
||||||
image: runebaas/rsync-ssh-git
|
image: runebaas/rsync-ssh-git
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
|
dependencies:
|
||||||
|
- build
|
||||||
|
- sentry
|
||||||
|
environment:
|
||||||
|
name: Production
|
||||||
|
url: https://discordapp.com/oauth2/authorize?client_id=171249478546882561&scope=bot&permissions=1416834054
|
||||||
|
before_script:
|
||||||
|
- eval $(ssh-agent -s)
|
||||||
|
- mkdir -p ~/.ssh
|
||||||
|
- '[[ -f /.dockerenv ]] && echo -e "Host *\n StrictHostKeyChecking no" > ~/.ssh/config'
|
||||||
|
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null
|
||||||
|
- chmod 700 ~/.ssh
|
||||||
|
script:
|
||||||
|
- rsync -rav -e "ssh -p 65432" ./Geekbot.net/Binaries/* geekbot@$DEPIP:$DEPPATH
|
||||||
|
- ssh -p 65432 geekbot@$DEPIP "sudo systemctl restart geekbot.service"
|
||||||
|
|
||||||
|
mirror:
|
||||||
|
stage: deploy
|
||||||
|
image: runebaas/rsync-ssh-git
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
dependencies:
|
||||||
|
- build
|
||||||
|
- sentry
|
||||||
script:
|
script:
|
||||||
- git push https://runebaas:$TOKEN@github.com/pizzaandcoffee/Geekbot.net.git origin/master:master -f
|
- git push https://runebaas:$TOKEN@github.com/pizzaandcoffee/Geekbot.net.git origin/master:master -f
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
FROM mcr.microsoft.com/dotnet/aspnet:6.0
|
FROM microsoft/dotnet:2.1-aspnetcore-runtime
|
||||||
|
|
||||||
COPY ./app /app/
|
COPY Geekbot.net/Binaries /app/
|
||||||
|
|
||||||
EXPOSE 12995/tcp
|
EXPOSE 12995/tcp
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
ENTRYPOINT ./Geekbot
|
ENTRYPOINT ./run.sh
|
||||||
|
|
|
@ -3,19 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 2013
|
# Visual Studio 2013
|
||||||
VisualStudioVersion = 12.0.0.0
|
VisualStudioVersion = 12.0.0.0
|
||||||
MinimumVisualStudioVersion = 10.0.0.1
|
MinimumVisualStudioVersion = 10.0.0.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "tests\Tests.csproj", "{4CAF5F02-EFFE-4FDA-BD44-EEADDBA9600E}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Geekbot.net", "Geekbot.net/Geekbot.net.csproj", "{FDCB3D92-E7B5-47BB-A9B5-CFAEFA57CDB4}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core", "src\Core\Core.csproj", "{47671723-52A9-4668-BBC5-2BA76AE3B288}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{4CAF5F02-EFFE-4FDA-BD44-EEADDBA9600E}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Web", "src\Web\Web.csproj", "{0A63D5DC-6325-4F53-8ED2-9843239B76CC}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WikipediaApi", "WikipediaApi\WikipediaApi.csproj", "{1084D499-EF94-4834-9E6A-B2AD81B60078}"
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bot", "src\Bot\Bot.csproj", "{DBF79896-9F7F-443D-B336-155E276DFF16}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commands", "src\Commands\Commands.csproj", "{7C771DFE-912A-4276-B0A6-047E09603F1E}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Interactions", "src\Interactions\Interactions.csproj", "{FF6859D9-C539-4910-BE1E-9ECFED2F46FA}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Startup", "src\Startup\Startup.csproj", "{A691B018-4B19-4A7A-A0F6-DBB17641254F}"
|
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
@ -23,34 +15,18 @@ Global
|
||||||
Release|Any CPU = Release|Any CPU
|
Release|Any CPU = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{FDCB3D92-E7B5-47BB-A9B5-CFAEFA57CDB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{FDCB3D92-E7B5-47BB-A9B5-CFAEFA57CDB4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{FDCB3D92-E7B5-47BB-A9B5-CFAEFA57CDB4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{FDCB3D92-E7B5-47BB-A9B5-CFAEFA57CDB4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{4CAF5F02-EFFE-4FDA-BD44-EEADDBA9600E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{4CAF5F02-EFFE-4FDA-BD44-EEADDBA9600E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{4CAF5F02-EFFE-4FDA-BD44-EEADDBA9600E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{4CAF5F02-EFFE-4FDA-BD44-EEADDBA9600E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{4CAF5F02-EFFE-4FDA-BD44-EEADDBA9600E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{4CAF5F02-EFFE-4FDA-BD44-EEADDBA9600E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{4CAF5F02-EFFE-4FDA-BD44-EEADDBA9600E}.Release|Any CPU.Build.0 = Release|Any CPU
|
{4CAF5F02-EFFE-4FDA-BD44-EEADDBA9600E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{47671723-52A9-4668-BBC5-2BA76AE3B288}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{1084D499-EF94-4834-9E6A-B2AD81B60078}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{47671723-52A9-4668-BBC5-2BA76AE3B288}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{1084D499-EF94-4834-9E6A-B2AD81B60078}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{47671723-52A9-4668-BBC5-2BA76AE3B288}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{1084D499-EF94-4834-9E6A-B2AD81B60078}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{47671723-52A9-4668-BBC5-2BA76AE3B288}.Release|Any CPU.Build.0 = Release|Any CPU
|
{1084D499-EF94-4834-9E6A-B2AD81B60078}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{0A63D5DC-6325-4F53-8ED2-9843239B76CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{0A63D5DC-6325-4F53-8ED2-9843239B76CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{0A63D5DC-6325-4F53-8ED2-9843239B76CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{0A63D5DC-6325-4F53-8ED2-9843239B76CC}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{DBF79896-9F7F-443D-B336-155E276DFF16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{DBF79896-9F7F-443D-B336-155E276DFF16}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{DBF79896-9F7F-443D-B336-155E276DFF16}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{DBF79896-9F7F-443D-B336-155E276DFF16}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{7C771DFE-912A-4276-B0A6-047E09603F1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{7C771DFE-912A-4276-B0A6-047E09603F1E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{7C771DFE-912A-4276-B0A6-047E09603F1E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{7C771DFE-912A-4276-B0A6-047E09603F1E}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{FF6859D9-C539-4910-BE1E-9ECFED2F46FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{FF6859D9-C539-4910-BE1E-9ECFED2F46FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{FF6859D9-C539-4910-BE1E-9ECFED2F46FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{FF6859D9-C539-4910-BE1E-9ECFED2F46FA}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{A691B018-4B19-4A7A-A0F6-DBB17641254F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{A691B018-4B19-4A7A-A0F6-DBB17641254F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{A691B018-4B19-4A7A-A0F6-DBB17641254F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{A691B018-4B19-4A7A-A0F6-DBB17641254F}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
268
Geekbot.net/Commands/Admin/Admin.cs
Normal file
268
Geekbot.net/Commands/Admin/Admin.cs
Normal file
|
@ -0,0 +1,268 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Discord;
|
||||||
|
using Discord.Commands;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using Geekbot.net.Database;
|
||||||
|
using Geekbot.net.Database.Models;
|
||||||
|
using Geekbot.net.Lib;
|
||||||
|
using Geekbot.net.Lib.CommandPreconditions;
|
||||||
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
|
using Geekbot.net.Lib.Extensions;
|
||||||
|
using Geekbot.net.Lib.Localization;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Commands.Admin
|
||||||
|
{
|
||||||
|
[Group("admin")]
|
||||||
|
[RequireUserPermission(GuildPermission.Administrator)]
|
||||||
|
[DisableInDirectMessage]
|
||||||
|
public class Admin : GeekbotBase
|
||||||
|
{
|
||||||
|
private readonly DiscordSocketClient _client;
|
||||||
|
private readonly IErrorHandler _errorHandler;
|
||||||
|
private readonly DatabaseContext _database;
|
||||||
|
private readonly ITranslationHandler _translation;
|
||||||
|
|
||||||
|
public Admin(DatabaseContext database, DiscordSocketClient client, IErrorHandler errorHandler,
|
||||||
|
ITranslationHandler translationHandler)
|
||||||
|
{
|
||||||
|
_database = database;
|
||||||
|
_client = client;
|
||||||
|
_errorHandler = errorHandler;
|
||||||
|
_translation = translationHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("welcome", RunMode = RunMode.Async)]
|
||||||
|
[Summary("Set a Welcome Message (use '$user' to mention the new joined user).")]
|
||||||
|
public async Task SetWelcomeMessage([Remainder, Summary("message")] string welcomeMessage)
|
||||||
|
{
|
||||||
|
var guild = await GetGuildSettings(Context.Guild.Id);
|
||||||
|
guild.WelcomeMessage = welcomeMessage;
|
||||||
|
_database.GuildSettings.Update(guild);
|
||||||
|
await _database.SaveChangesAsync();
|
||||||
|
|
||||||
|
var formatedMessage = welcomeMessage.Replace("$user", Context.User.Mention);
|
||||||
|
await ReplyAsync($"Welcome message has been changed\r\nHere is an example of how it would look:\r\n{formatedMessage}");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("welcomechannel", RunMode = RunMode.Async)]
|
||||||
|
[Summary("Set a channel for the welcome messages (by default it uses the top most channel)")]
|
||||||
|
public async Task SelectWelcomeChannel([Summary("#Channel")] ISocketMessageChannel channel)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var m = await channel.SendMessageAsync("...");
|
||||||
|
|
||||||
|
var guild = await GetGuildSettings(Context.Guild.Id);
|
||||||
|
guild.WelcomeChannel = channel.Id.AsLong();
|
||||||
|
_database.GuildSettings.Update(guild);
|
||||||
|
await _database.SaveChangesAsync();
|
||||||
|
|
||||||
|
await m.DeleteAsync();
|
||||||
|
|
||||||
|
await ReplyAsync("Successfully saved the welcome channel");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context, "That channel doesn't seem to exist or i don't have write permissions");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("modchannel", RunMode = RunMode.Async)]
|
||||||
|
[Summary("Set a channel for moderation purposes")]
|
||||||
|
public async Task SelectModChannel([Summary("#Channel")] ISocketMessageChannel channel)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var m = await channel.SendMessageAsync("verifying...");
|
||||||
|
|
||||||
|
var guild = await GetGuildSettings(Context.Guild.Id);
|
||||||
|
guild.ModChannel = channel.Id.AsLong();
|
||||||
|
_database.GuildSettings.Update(guild);
|
||||||
|
await _database.SaveChangesAsync();
|
||||||
|
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.AppendLine("Successfully saved mod channel, you can now do the following");
|
||||||
|
sb.AppendLine("- `!admin showleave` - send message to mod channel when someone leaves");
|
||||||
|
sb.AppendLine("- `!admin showdel` - send message to mod channel when someone deletes a message");
|
||||||
|
await m.ModifyAsync(e => e.Content = sb.ToString());
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context, "That channel doesn't seem to exist or i don't have write permissions");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("showleave", RunMode = RunMode.Async)]
|
||||||
|
[Summary("Toggle - notify modchannel when someone leaves")]
|
||||||
|
public async Task ShowLeave()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var guild = await GetGuildSettings(Context.Guild.Id);
|
||||||
|
var modChannel = await GetModChannel(guild.ModChannel.AsUlong());
|
||||||
|
if (modChannel == null) return;
|
||||||
|
|
||||||
|
guild.ShowLeave = !guild.ShowLeave;
|
||||||
|
_database.GuildSettings.Update(guild);
|
||||||
|
await _database.SaveChangesAsync();
|
||||||
|
await modChannel.SendMessageAsync(guild.ShowLeave
|
||||||
|
? "Saved - now sending messages here when someone leaves"
|
||||||
|
: "Saved - stopping sending messages here when someone leaves"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("showdel", RunMode = RunMode.Async)]
|
||||||
|
[Summary("Toggle - notify modchannel when someone deletes a message")]
|
||||||
|
public async Task ShowDelete()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var guild = await GetGuildSettings(Context.Guild.Id);
|
||||||
|
var modChannel = await GetModChannel(guild.ModChannel.AsUlong());
|
||||||
|
if (modChannel == null) return;
|
||||||
|
|
||||||
|
guild.ShowDelete = !guild.ShowDelete;
|
||||||
|
_database.GuildSettings.Update(guild);
|
||||||
|
await _database.SaveChangesAsync();
|
||||||
|
await modChannel.SendMessageAsync(guild.ShowDelete
|
||||||
|
? "Saved - now sending messages here when someone deletes a message"
|
||||||
|
: "Saved - stopping sending messages here when someone deletes a message"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("setlang", RunMode = RunMode.Async)]
|
||||||
|
[Summary("Change the bots language")]
|
||||||
|
public async Task SetLanguage([Summary("language")] string languageRaw)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var language = languageRaw.ToUpper();
|
||||||
|
var success = await _translation.SetLanguage(Context.Guild.Id, language);
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
var guild = await GetGuildSettings(Context.Guild.Id);
|
||||||
|
guild.Language = language;
|
||||||
|
_database.GuildSettings.Update(guild);
|
||||||
|
await _database.SaveChangesAsync();
|
||||||
|
|
||||||
|
var transContext = await _translation.GetGuildContext(Context);
|
||||||
|
await ReplyAsync(transContext.GetString("NewLanguageSet"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await ReplyAsync(
|
||||||
|
$"That doesn't seem to be a supported language\r\nSupported Languages are {string.Join(", ", _translation.SupportedLanguages)}");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("wiki", RunMode = RunMode.Async)]
|
||||||
|
[Summary("Change the wikipedia instance (use lang code in xx.wikipedia.org)")]
|
||||||
|
public async Task SetWikiLanguage([Summary("language")] string languageRaw)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var language = languageRaw.ToLower();
|
||||||
|
var guild = await GetGuildSettings(Context.Guild.Id);
|
||||||
|
guild.WikiLang = language;
|
||||||
|
_database.GuildSettings.Update(guild);
|
||||||
|
await _database.SaveChangesAsync();
|
||||||
|
|
||||||
|
await ReplyAsync($"Now using the {language} wikipedia");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("ping", RunMode = RunMode.Async)]
|
||||||
|
[Summary("Enable the ping reply.")]
|
||||||
|
public async Task TogglePing()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var guild = await GetGuildSettings(Context.Guild.Id);
|
||||||
|
guild.Ping = !guild.Ping;
|
||||||
|
_database.GuildSettings.Update(guild);
|
||||||
|
await _database.SaveChangesAsync();
|
||||||
|
await ReplyAsync(guild.Ping ? "i will reply to ping now" : "No more pongs...");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("hui", RunMode = RunMode.Async)]
|
||||||
|
[Summary("Enable the ping reply.")]
|
||||||
|
public async Task ToggleHui()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var guild = await GetGuildSettings(Context.Guild.Id);
|
||||||
|
guild.Hui = !guild.Hui;
|
||||||
|
_database.GuildSettings.Update(guild);
|
||||||
|
await _database.SaveChangesAsync();
|
||||||
|
await ReplyAsync(guild.Hui ? "i will reply to hui now" : "No more hui's...");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<GuildSettingsModel> GetGuildSettings(ulong guildId)
|
||||||
|
{
|
||||||
|
var guild = _database.GuildSettings.FirstOrDefault(g => g.GuildId.Equals(guildId.AsLong()));
|
||||||
|
if (guild != null) return guild;
|
||||||
|
Console.WriteLine("Adding non-exist Guild Settings to database");
|
||||||
|
_database.GuildSettings.Add(new GuildSettingsModel()
|
||||||
|
{
|
||||||
|
GuildId = guildId.AsLong(),
|
||||||
|
Hui = false,
|
||||||
|
Ping = false,
|
||||||
|
Language = "EN",
|
||||||
|
ShowDelete = false,
|
||||||
|
ShowLeave = false,
|
||||||
|
WikiLang = "en"
|
||||||
|
});
|
||||||
|
await _database.SaveChangesAsync();
|
||||||
|
return _database.GuildSettings.FirstOrDefault(g => g.GuildId.Equals(guildId.AsLong()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<ISocketMessageChannel> GetModChannel(ulong channelId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if(channelId == ulong.MinValue) throw new Exception();
|
||||||
|
var modChannel = (ISocketMessageChannel) _client.GetChannel(channelId);
|
||||||
|
if(modChannel == null) throw new Exception();
|
||||||
|
return modChannel;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
await ReplyAsync(
|
||||||
|
"Modchannel doesn't seem to exist, please set one with `!admin modchannel [channelId]`");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
58
Geekbot.net/Commands/Admin/Mod.cs
Normal file
58
Geekbot.net/Commands/Admin/Mod.cs
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Discord;
|
||||||
|
using Discord.Commands;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using Geekbot.net.Lib;
|
||||||
|
using Geekbot.net.Lib.CommandPreconditions;
|
||||||
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
|
using Geekbot.net.Lib.UserRepository;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Commands.Admin
|
||||||
|
{
|
||||||
|
[Group("mod")]
|
||||||
|
[RequireUserPermission(GuildPermission.KickMembers)]
|
||||||
|
[RequireUserPermission(GuildPermission.ManageMessages)]
|
||||||
|
[RequireUserPermission(GuildPermission.ManageRoles)]
|
||||||
|
[DisableInDirectMessage]
|
||||||
|
public class Mod : GeekbotBase
|
||||||
|
{
|
||||||
|
private readonly DiscordSocketClient _client;
|
||||||
|
private readonly IErrorHandler _errorHandler;
|
||||||
|
private readonly IUserRepository _userRepository;
|
||||||
|
|
||||||
|
public Mod(IUserRepository userRepositry, IErrorHandler errorHandler, DiscordSocketClient client)
|
||||||
|
{
|
||||||
|
_userRepository = userRepositry;
|
||||||
|
_errorHandler = errorHandler;
|
||||||
|
_client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("namehistory", RunMode = RunMode.Async)]
|
||||||
|
[Summary("See past usernames of an user")]
|
||||||
|
public async Task UsernameHistory([Summary("@someone")] IUser user)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var userRepo = _userRepository.Get(user.Id);
|
||||||
|
if (userRepo != null && userRepo.UsedNames != null)
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.AppendLine($":bust_in_silhouette: {user.Username} has been known as:");
|
||||||
|
foreach (var name in userRepo.UsedNames) sb.AppendLine($"- `{name.Name}`");
|
||||||
|
await ReplyAsync(sb.ToString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await ReplyAsync($"No name changes found for {user.Username}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context,
|
||||||
|
$"I don't have enough permissions do that");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,30 +3,30 @@ using System.Threading.Tasks;
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using Geekbot.Core;
|
using Geekbot.net.Lib;
|
||||||
using Geekbot.Core.ErrorHandling;
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
using Geekbot.Core.GlobalSettings;
|
using Geekbot.net.Lib.GlobalSettings;
|
||||||
using Geekbot.Core.GuildSettingsManager;
|
using Geekbot.net.Lib.Logger;
|
||||||
using Geekbot.Core.Logger;
|
using Geekbot.net.Lib.UserRepository;
|
||||||
using Geekbot.Core.UserRepository;
|
|
||||||
|
|
||||||
namespace Geekbot.Bot.Commands.Admin.Owner
|
namespace Geekbot.net.Commands.Admin.Owner
|
||||||
{
|
{
|
||||||
[Group("owner")]
|
[Group("owner")]
|
||||||
[RequireOwner]
|
[RequireOwner]
|
||||||
public class Owner : GeekbotCommandBase
|
public class Owner : GeekbotBase
|
||||||
{
|
{
|
||||||
private readonly DiscordSocketClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
|
private readonly IErrorHandler _errorHandler;
|
||||||
private readonly IGlobalSettings _globalSettings;
|
private readonly IGlobalSettings _globalSettings;
|
||||||
private readonly IGeekbotLogger _logger;
|
private readonly IGeekbotLogger _logger;
|
||||||
private readonly IUserRepository _userRepository;
|
private readonly IUserRepository _userRepository;
|
||||||
|
|
||||||
public Owner(DiscordSocketClient client, IGeekbotLogger logger, IUserRepository userRepositry, IErrorHandler errorHandler, IGlobalSettings globalSettings,
|
public Owner(DiscordSocketClient client, IGeekbotLogger logger, IUserRepository userRepositry, IErrorHandler errorHandler, IGlobalSettings globalSettings)
|
||||||
IGuildSettingsManager guildSettingsManager) : base(errorHandler, guildSettingsManager)
|
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_userRepository = userRepositry;
|
_userRepository = userRepositry;
|
||||||
|
_errorHandler = errorHandler;
|
||||||
_globalSettings = globalSettings;
|
_globalSettings = globalSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ namespace Geekbot.Bot.Commands.Admin.Owner
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
await ErrorHandler.HandleCommandException(e, Context,
|
await _errorHandler.HandleCommandException(e, Context,
|
||||||
"Couldn't complete User Repository, see console for more info");
|
"Couldn't complete User Repository, see console for more info");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,10 +90,10 @@ namespace Geekbot.Bot.Commands.Admin.Owner
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
await ErrorHandler.HandleCommandException(e, Context);
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Command("refreshuser", RunMode = RunMode.Async)]
|
[Command("refreshuser", RunMode = RunMode.Async)]
|
||||||
[Summary("Refresh a user in the user cache")]
|
[Summary("Refresh a user in the user cache")]
|
||||||
public async Task PopUserRepoCommand([Summary("user-id")] ulong userId)
|
public async Task PopUserRepoCommand([Summary("user-id")] ulong userId)
|
||||||
|
@ -106,7 +106,7 @@ namespace Geekbot.Bot.Commands.Admin.Owner
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
await ErrorHandler.HandleCommandException(e, Context);
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ namespace Geekbot.Bot.Commands.Admin.Owner
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
await ErrorHandler.HandleCommandException(e, Context);
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,33 +1,32 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Discord.Net;
|
using Discord.Net;
|
||||||
using Geekbot.Bot.CommandPreconditions;
|
using Geekbot.net.Database;
|
||||||
using Geekbot.Core;
|
using Geekbot.net.Database.Models;
|
||||||
using Geekbot.Core.Database;
|
using Geekbot.net.Lib;
|
||||||
using Geekbot.Core.Database.Models;
|
using Geekbot.net.Lib.CommandPreconditions;
|
||||||
using Geekbot.Core.ErrorHandling;
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
using Geekbot.Core.Extensions;
|
using Geekbot.net.Lib.Extensions;
|
||||||
using Geekbot.Core.GuildSettingsManager;
|
using Geekbot.net.Lib.ReactionListener;
|
||||||
using Geekbot.Core.ReactionListener;
|
|
||||||
using Localization = Geekbot.Core.Localization;
|
|
||||||
|
|
||||||
namespace Geekbot.Bot.Commands.Admin
|
namespace Geekbot.net.Commands.Admin
|
||||||
{
|
{
|
||||||
[Group("role")]
|
[Group("role")]
|
||||||
[DisableInDirectMessage]
|
[DisableInDirectMessage]
|
||||||
public class Role : GeekbotCommandBase
|
public class Role : GeekbotBase
|
||||||
{
|
{
|
||||||
private readonly DatabaseContext _database;
|
private readonly DatabaseContext _database;
|
||||||
|
private readonly IErrorHandler _errorHandler;
|
||||||
private readonly IReactionListener _reactionListener;
|
private readonly IReactionListener _reactionListener;
|
||||||
|
|
||||||
public Role(DatabaseContext database, IErrorHandler errorHandler, IReactionListener reactionListener, IGuildSettingsManager guildSettingsManager) : base(errorHandler, guildSettingsManager)
|
public Role(DatabaseContext database, IErrorHandler errorHandler, IReactionListener reactionListener)
|
||||||
{
|
{
|
||||||
_database = database;
|
_database = database;
|
||||||
|
_errorHandler = errorHandler;
|
||||||
_reactionListener = reactionListener;
|
_reactionListener = reactionListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,19 +39,19 @@ namespace Geekbot.Bot.Commands.Admin
|
||||||
var roles = _database.RoleSelfService.Where(g => g.GuildId.Equals(Context.Guild.Id.AsLong())).ToList();
|
var roles = _database.RoleSelfService.Where(g => g.GuildId.Equals(Context.Guild.Id.AsLong())).ToList();
|
||||||
if (roles.Count == 0)
|
if (roles.Count == 0)
|
||||||
{
|
{
|
||||||
await ReplyAsync(Localization.Role.NoRolesConfigured);
|
await ReplyAsync(Context.Translations.GetString("NoRolesConfigured"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
sb.AppendLine(string.Format(Localization.Role.ListHeader, Context.Guild.Name));
|
sb.AppendLine(Context.Translations.GetString("ListHeader", Context.Guild.Name));
|
||||||
sb.AppendLine(Localization.Role.ListInstruction);
|
sb.AppendLine(Context.Translations.GetString("ListInstruction"));
|
||||||
foreach (var role in roles) sb.AppendLine($"- {role.WhiteListName}");
|
foreach (var role in roles) sb.AppendLine($"- {role.WhiteListName}");
|
||||||
await ReplyAsync(sb.ToString());
|
await ReplyAsync(sb.ToString());
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
await ErrorHandler.HandleCommandException(e, Context);
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,38 +70,31 @@ namespace Geekbot.Bot.Commands.Admin
|
||||||
var role = Context.Guild.Roles.First(r => r.Id == roleFromDb.RoleId.AsUlong());
|
var role = Context.Guild.Roles.First(r => r.Id == roleFromDb.RoleId.AsUlong());
|
||||||
if (role == null)
|
if (role == null)
|
||||||
{
|
{
|
||||||
await ReplyAsync(Localization.Role.RoleNotFound);
|
await ReplyAsync(Context.Translations.GetString("RoleNotFound"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (guildUser.RoleIds.Contains(role.Id))
|
if (guildUser.RoleIds.Contains(role.Id))
|
||||||
{
|
{
|
||||||
await guildUser.RemoveRoleAsync(role);
|
await guildUser.RemoveRoleAsync(role);
|
||||||
await ReplyAsync(string.Format(Localization.Role.RemovedUserFromRole, role.Name));
|
await ReplyAsync(Context.Translations.GetString("RemovedUserFromRole", role.Name));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await guildUser.AddRoleAsync(role);
|
await guildUser.AddRoleAsync(role);
|
||||||
await ReplyAsync(string.Format(Localization.Role.AddedUserFromRole, role.Name));
|
await ReplyAsync(Context.Translations.GetString("AddedUserFromRole", role.Name));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await ReplyAsync(Localization.Role.RoleNotFound);
|
await ReplyAsync(Context.Translations.GetString("RoleNotFound"));
|
||||||
}
|
}
|
||||||
catch (HttpException e)
|
catch (HttpException e)
|
||||||
{
|
{
|
||||||
if (e.HttpCode == HttpStatusCode.Forbidden)
|
await _errorHandler.HandleHttpException(e, Context);
|
||||||
{
|
|
||||||
await ReplyAsync(Localization.Internal.Http403);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await ErrorHandler.HandleCommandException(e, Context);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
await ErrorHandler.HandleCommandException(e, Context);
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +107,7 @@ namespace Geekbot.Bot.Commands.Admin
|
||||||
{
|
{
|
||||||
if (role.IsManaged)
|
if (role.IsManaged)
|
||||||
{
|
{
|
||||||
await ReplyAsync(Localization.Role.CannotAddManagedRole);
|
await ReplyAsync(Context.Translations.GetString("CannotAddManagedRole"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +117,7 @@ namespace Geekbot.Bot.Commands.Admin
|
||||||
|| role.Permissions.BanMembers
|
|| role.Permissions.BanMembers
|
||||||
|| role.Permissions.KickMembers)
|
|| role.Permissions.KickMembers)
|
||||||
{
|
{
|
||||||
await ReplyAsync(Localization.Role.CannotAddDangerousRole);
|
await ReplyAsync(Context.Translations.GetString("CannotAddDangerousRole"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,11 +128,11 @@ namespace Geekbot.Bot.Commands.Admin
|
||||||
WhiteListName = roleName
|
WhiteListName = roleName
|
||||||
});
|
});
|
||||||
await _database.SaveChangesAsync();
|
await _database.SaveChangesAsync();
|
||||||
await ReplyAsync(string.Format(Localization.Role.AddedRoleToWhitelist, role.Name));
|
await ReplyAsync(Context.Translations.GetString("CannotAddDangerousRole", role.Name));
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
await ErrorHandler.HandleCommandException(e, Context);
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,40 +149,49 @@ namespace Geekbot.Bot.Commands.Admin
|
||||||
{
|
{
|
||||||
_database.RoleSelfService.Remove(roleFromDb);
|
_database.RoleSelfService.Remove(roleFromDb);
|
||||||
await _database.SaveChangesAsync();
|
await _database.SaveChangesAsync();
|
||||||
await ReplyAsync(string.Format(Localization.Role.RemovedRoleFromWhitelist, roleName));
|
await ReplyAsync(Context.Translations.GetString("RemovedRoleFromWhitelist", roleName));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await ReplyAsync(Localization.Role.RoleNotFound);
|
await ReplyAsync(Context.Translations.GetString("RoleNotFound"));
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
await ErrorHandler.HandleCommandException(e, Context);
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[RequireUserPermission(GuildPermission.ManageRoles)]
|
[RequireUserPermission(GuildPermission.ManageRoles)]
|
||||||
[Summary("Give a role by clicking on an emoji")]
|
[Summary("Give a role by clicking on an emoji")]
|
||||||
[Command("listen", RunMode = RunMode.Async)]
|
[Command("listen", RunMode = RunMode.Async)]
|
||||||
public async Task AddListener([Summary("message-ID")] string messageIdStr, [Summary("Emoji")] string emoji, [Summary("@role")] IRole role)
|
public async Task AddListener([Summary("message-ID")] string messageId, [Summary("Emoji")] string emoji, [Summary("@role")] IRole role)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var messageId = ulong.Parse(messageIdStr);
|
var message = (IUserMessage) await Context.Channel.GetMessageAsync(ulong.Parse(messageId));
|
||||||
var message = (IUserMessage) await Context.Channel.GetMessageAsync(messageId);
|
IEmote emote;
|
||||||
var emote = _reactionListener.ConvertStringToEmote(emoji);
|
if (!emoji.StartsWith('<'))
|
||||||
|
{
|
||||||
|
var emo = new Emoji(emoji);
|
||||||
|
emote = emo;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
emote = Emote.Parse(emoji);
|
||||||
|
}
|
||||||
await message.AddReactionAsync(emote);
|
await message.AddReactionAsync(emote);
|
||||||
await _reactionListener.AddRoleToListener(messageId, Context.Guild.Id, emoji, role);
|
await _reactionListener.AddRoleToListener(messageId, emote, role);
|
||||||
await Context.Message.DeleteAsync();
|
await Context.Message.DeleteAsync();
|
||||||
}
|
}
|
||||||
catch (HttpException)
|
catch (HttpException e)
|
||||||
{
|
{
|
||||||
await Context.Channel.SendMessageAsync("Custom emojis from other servers are not supported");
|
await Context.Channel.SendMessageAsync("Custom emojis from other servers are not supported");
|
||||||
|
Console.WriteLine(e);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
await ErrorHandler.HandleCommandException(e, Context);
|
await Context.Channel.SendMessageAsync("Something went wrong... please try again on a new message");
|
||||||
|
Console.WriteLine(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,14 +3,14 @@ using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Geekbot.Core;
|
using Geekbot.net.Lib;
|
||||||
using Geekbot.Core.ErrorHandling;
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
using Geekbot.Core.Extensions;
|
using Geekbot.net.Lib.Extensions;
|
||||||
using PokeAPI;
|
using PokeAPI;
|
||||||
|
|
||||||
namespace Geekbot.Bot.Commands.Games
|
namespace Geekbot.net.Commands.Games
|
||||||
{
|
{
|
||||||
public class Pokedex : TransactionModuleBase
|
public class Pokedex : GeekbotBase
|
||||||
{
|
{
|
||||||
private readonly IErrorHandler _errorHandler;
|
private readonly IErrorHandler _errorHandler;
|
||||||
|
|
96
Geekbot.net/Commands/Games/Roll.cs
Normal file
96
Geekbot.net/Commands/Games/Roll.cs
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Discord.Commands;
|
||||||
|
using Geekbot.net.Database;
|
||||||
|
using Geekbot.net.Database.Models;
|
||||||
|
using Geekbot.net.Lib;
|
||||||
|
using Geekbot.net.Lib.AlmostRedis;
|
||||||
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
|
using Geekbot.net.Lib.Extensions;
|
||||||
|
using Geekbot.net.Lib.Localization;
|
||||||
|
using Geekbot.net.Lib.RandomNumberGenerator;
|
||||||
|
using StackExchange.Redis;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Commands.Games
|
||||||
|
{
|
||||||
|
public class Roll : GeekbotBase
|
||||||
|
{
|
||||||
|
private readonly IErrorHandler _errorHandler;
|
||||||
|
private readonly IAlmostRedis _redis;
|
||||||
|
private readonly DatabaseContext _database;
|
||||||
|
private readonly IRandomNumberGenerator _randomNumberGenerator;
|
||||||
|
|
||||||
|
public Roll(IAlmostRedis redis, IErrorHandler errorHandler, DatabaseContext database, IRandomNumberGenerator randomNumberGenerator)
|
||||||
|
{
|
||||||
|
_redis = redis;
|
||||||
|
_database = database;
|
||||||
|
_randomNumberGenerator = randomNumberGenerator;
|
||||||
|
_errorHandler = errorHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("roll", RunMode = RunMode.Async)]
|
||||||
|
[Summary("Guess which number the bot will roll (1-100")]
|
||||||
|
public async Task RollCommand([Remainder] [Summary("guess")] string stuff = null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var number = _randomNumberGenerator.Next(1, 100);
|
||||||
|
var guess = 1000;
|
||||||
|
int.TryParse(stuff, out guess);
|
||||||
|
if (guess <= 100 && guess > 0)
|
||||||
|
{
|
||||||
|
var prevRoll = _redis.Db.HashGet($"{Context.Guild.Id}:RollsPrevious2", Context.Message.Author.Id).ToString()?.Split('|');
|
||||||
|
if (prevRoll?.Length == 2)
|
||||||
|
{
|
||||||
|
if (prevRoll[0] == guess.ToString() && DateTime.Parse(prevRoll[1]) > DateTime.Now.AddDays(-1))
|
||||||
|
{
|
||||||
|
await ReplyAsync(Context.Translations.GetString("NoPrevGuess", Context.Message.Author.Mention));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_redis.Db.HashSet($"{Context.Guild.Id}:RollsPrevious2", new[] {new HashEntry(Context.Message.Author.Id, $"{guess}|{DateTime.Now}")});
|
||||||
|
|
||||||
|
await ReplyAsync(Context.Translations.GetString("Rolled", Context.Message.Author.Mention, number, guess));
|
||||||
|
if (guess == number)
|
||||||
|
{
|
||||||
|
await ReplyAsync(Context.Translations.GetString("Gratz", Context.Message.Author));
|
||||||
|
_redis.Db.HashIncrement($"{Context.Guild.Id}:Rolls", Context.User.Id.ToString());
|
||||||
|
var user = await GetUser(Context.User.Id);
|
||||||
|
user.Rolls += 1;
|
||||||
|
_database.Rolls.Update(user);
|
||||||
|
await _database.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await ReplyAsync(Context.Translations.GetString("RolledNoGuess", Context.Message.Author.Mention, number));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<RollsModel> GetUser(ulong userId)
|
||||||
|
{
|
||||||
|
var user = _database.Rolls.FirstOrDefault(u =>u.GuildId.Equals(Context.Guild.Id.AsLong()) && u.UserId.Equals(userId.AsLong())) ?? await CreateNewRow(userId);
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<RollsModel> CreateNewRow(ulong userId)
|
||||||
|
{
|
||||||
|
var user = new RollsModel()
|
||||||
|
{
|
||||||
|
GuildId = Context.Guild.Id.AsLong(),
|
||||||
|
UserId = userId.AsLong(),
|
||||||
|
Rolls = 0
|
||||||
|
};
|
||||||
|
var newUser = _database.Rolls.Add(user).Entity;
|
||||||
|
await _database.SaveChangesAsync();
|
||||||
|
return newUser;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
69
Geekbot.net/Commands/Integrations/Google/Google.cs
Normal file
69
Geekbot.net/Commands/Integrations/Google/Google.cs
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Discord;
|
||||||
|
using Discord.Commands;
|
||||||
|
using Geekbot.net.Lib;
|
||||||
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
|
using Geekbot.net.Lib.GlobalSettings;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Commands.Integrations.Google
|
||||||
|
{
|
||||||
|
public class Google : GeekbotBase
|
||||||
|
{
|
||||||
|
private readonly IErrorHandler _errorHandler;
|
||||||
|
private readonly IGlobalSettings _globalSettings;
|
||||||
|
|
||||||
|
public Google(IErrorHandler errorHandler, IGlobalSettings globalSettings)
|
||||||
|
{
|
||||||
|
_errorHandler = errorHandler;
|
||||||
|
_globalSettings = globalSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("google", RunMode = RunMode.Async)]
|
||||||
|
[Summary("Google Something.")]
|
||||||
|
public async Task AskGoogle([Remainder, Summary("search-text")] string searchText)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var client = new WebClient())
|
||||||
|
{
|
||||||
|
var apiKey = _globalSettings.GetKey("GoogleGraphKey");
|
||||||
|
if (string.IsNullOrEmpty(apiKey))
|
||||||
|
{
|
||||||
|
await ReplyAsync("No Google API key has been set, please contact my owner");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var url = new Uri($"https://kgsearch.googleapis.com/v1/entities:search?languages=en&limit=1&query={searchText}&key={apiKey}");
|
||||||
|
var responseString = client.DownloadString(url);
|
||||||
|
var response = JsonConvert.DeserializeObject<GoogleKgApiResponseDto>(responseString);
|
||||||
|
|
||||||
|
if (!response.ItemListElement.Any())
|
||||||
|
{
|
||||||
|
await ReplyAsync("No results were found...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var data = response.ItemListElement.First().Result;
|
||||||
|
var eb = new EmbedBuilder
|
||||||
|
{
|
||||||
|
Title = data.Name
|
||||||
|
};
|
||||||
|
if(!string.IsNullOrEmpty(data.Description)) eb.WithDescription(data.Description);
|
||||||
|
if(!string.IsNullOrEmpty(data.DetailedDtoDescription?.Url)) eb.WithUrl(data.DetailedDtoDescription.Url);
|
||||||
|
if(!string.IsNullOrEmpty(data.DetailedDtoDescription?.ArticleBody)) eb.AddField("Details", data.DetailedDtoDescription.ArticleBody);
|
||||||
|
if(!string.IsNullOrEmpty(data.Image?.ContentUrl)) eb.WithThumbnailUrl(data.Image.ContentUrl);
|
||||||
|
|
||||||
|
await ReplyAsync("", false, eb.Build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace Geekbot.net.Commands.Integrations.Google
|
||||||
|
{
|
||||||
|
public class GoogleKgApiDetailedDto
|
||||||
|
{
|
||||||
|
public string ArticleBody { get; set; }
|
||||||
|
public string Url { get; set; }
|
||||||
|
public string License { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace Geekbot.net.Commands.Integrations.Google
|
||||||
|
{
|
||||||
|
public class GoogleKgApiElementDto
|
||||||
|
{
|
||||||
|
public GoogleKgApiResultDto Result { get; set; }
|
||||||
|
public double ResultScore { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace Geekbot.net.Commands.Integrations.Google
|
||||||
|
{
|
||||||
|
public class GoogleKgApiImageDto
|
||||||
|
{
|
||||||
|
public string ContentUrl { get; set; }
|
||||||
|
public string Url { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Commands.Integrations.Google
|
||||||
|
{
|
||||||
|
public class GoogleKgApiResponseDto
|
||||||
|
{
|
||||||
|
public List<GoogleKgApiElementDto> ItemListElement { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
namespace Geekbot.net.Commands.Integrations.Google
|
||||||
|
{
|
||||||
|
public class GoogleKgApiResultDto
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
public GoogleKgApiImageDto Image { get; set; }
|
||||||
|
public GoogleKgApiDetailedDto DetailedDtoDescription { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,15 +4,15 @@ using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Geekbot.Core;
|
using Geekbot.net.Lib;
|
||||||
using Geekbot.Core.Converters;
|
using Geekbot.net.Lib.Converters;
|
||||||
using Geekbot.Core.ErrorHandling;
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
using Geekbot.Core.Extensions;
|
using Geekbot.net.Lib.Extensions;
|
||||||
using MtgApiManager.Lib.Service;
|
using MtgApiManager.Lib.Service;
|
||||||
|
|
||||||
namespace Geekbot.Bot.Commands.Integrations
|
namespace Geekbot.net.Commands.Integrations
|
||||||
{
|
{
|
||||||
public class MagicTheGathering : TransactionModuleBase
|
public class MagicTheGathering : GeekbotBase
|
||||||
{
|
{
|
||||||
private readonly IErrorHandler _errorHandler;
|
private readonly IErrorHandler _errorHandler;
|
||||||
private readonly IMtgManaConverter _manaConverter;
|
private readonly IMtgManaConverter _manaConverter;
|
||||||
|
@ -29,34 +29,22 @@ namespace Geekbot.Bot.Commands.Integrations
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var message = await Context.Channel.SendMessageAsync($":mag: Looking up \"{cardName}\", please wait...");
|
|
||||||
|
|
||||||
var service = new CardService();
|
var service = new CardService();
|
||||||
var result = service
|
var result = service
|
||||||
.Where(x => x.Name, cardName)
|
.Where(x => x.Name, cardName)
|
||||||
// fewer cards less risk of deserialization problems, don't need more than one anyways...
|
// fewer cards less risk of deserialization problems, don't need more than one anyways...
|
||||||
.Where(x => x.PageSize, 1);
|
.Where(x => x.PageSize, 1);
|
||||||
|
|
||||||
var cards = await result.AllAsync();
|
var card = result.All().Value.FirstOrDefault();
|
||||||
if (!cards.IsSuccess)
|
|
||||||
{
|
|
||||||
await message.ModifyAsync(properties => properties.Content = $":warning: The Gatherer reacted in an unexpected way: {cards.Exception.Message}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var card = cards.Value.FirstOrDefault();
|
|
||||||
|
|
||||||
if (card == null)
|
if (card == null)
|
||||||
{
|
{
|
||||||
await message.ModifyAsync(properties => properties.Content = ":red_circle: I couldn't find a card with that name...");
|
await ReplyAsync("I couldn't find that card...");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var eb = new EmbedBuilder
|
var eb = new EmbedBuilder();
|
||||||
{
|
eb.Title = card.Name;
|
||||||
Title = card.Name,
|
eb.Description = card.Type;
|
||||||
Description = card.Type
|
|
||||||
};
|
|
||||||
|
|
||||||
if (card.Colors != null) eb.WithColor(GetColor(card.Colors));
|
if (card.Colors != null) eb.WithColor(GetColor(card.Colors));
|
||||||
|
|
||||||
|
@ -76,11 +64,7 @@ namespace Geekbot.Bot.Commands.Integrations
|
||||||
if (card.Legalities != null && card.Legalities.Count > 0)
|
if (card.Legalities != null && card.Legalities.Count > 0)
|
||||||
eb.AddField("Legality", string.Join(", ", card.Legalities.Select(e => e.Format)));
|
eb.AddField("Legality", string.Join(", ", card.Legalities.Select(e => e.Format)));
|
||||||
|
|
||||||
await message.ModifyAsync(properties =>
|
await ReplyAsync("", false, eb.Build());
|
||||||
{
|
|
||||||
properties.Content = string.Empty;
|
|
||||||
properties.Embed = eb.Build();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -91,15 +75,21 @@ namespace Geekbot.Bot.Commands.Integrations
|
||||||
private Color GetColor(IEnumerable<string> colors)
|
private Color GetColor(IEnumerable<string> colors)
|
||||||
{
|
{
|
||||||
var color = colors.FirstOrDefault();
|
var color = colors.FirstOrDefault();
|
||||||
return color switch
|
switch (color)
|
||||||
{
|
{
|
||||||
"Black" => new Color(203, 194, 191),
|
case "Black":
|
||||||
"White" => new Color(255, 251, 213),
|
return new Color(203, 194, 191);
|
||||||
"Blue" => new Color(170, 224, 250),
|
case "White":
|
||||||
"Red" => new Color(250, 170, 143),
|
return new Color(255, 251, 213);
|
||||||
"Green" => new Color(155, 211, 174),
|
case "Blue":
|
||||||
_ => new Color(204, 194, 212)
|
return new Color(170, 224, 250);
|
||||||
};
|
case "Red":
|
||||||
|
return new Color(250, 170, 143);
|
||||||
|
case "Green":
|
||||||
|
return new Color(155, 211, 174);
|
||||||
|
default:
|
||||||
|
return new Color(204, 194, 212);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
129
Geekbot.net/Commands/Integrations/Mal.cs
Normal file
129
Geekbot.net/Commands/Integrations/Mal.cs
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Web;
|
||||||
|
using System.Xml;
|
||||||
|
using Discord;
|
||||||
|
using Discord.Commands;
|
||||||
|
using Geekbot.net.Lib;
|
||||||
|
using Geekbot.net.Lib.Clients;
|
||||||
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
|
using Geekbot.net.Lib.Extensions;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Commands.Integrations
|
||||||
|
{
|
||||||
|
public class Mal : GeekbotBase
|
||||||
|
{
|
||||||
|
private readonly IErrorHandler _errorHandler;
|
||||||
|
private readonly IMalClient _malClient;
|
||||||
|
|
||||||
|
public Mal(IMalClient malClient, IErrorHandler errorHandler)
|
||||||
|
{
|
||||||
|
_malClient = malClient;
|
||||||
|
_errorHandler = errorHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("anime", RunMode = RunMode.Async)]
|
||||||
|
[Summary("Show Info about an Anime.")]
|
||||||
|
public async Task SearchAnime([Remainder] [Summary("anime-name")] string animeName)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_malClient.IsLoggedIn())
|
||||||
|
{
|
||||||
|
var anime = await _malClient.GetAnime(animeName);
|
||||||
|
if (anime != null)
|
||||||
|
{
|
||||||
|
var eb = new EmbedBuilder();
|
||||||
|
|
||||||
|
var description = HttpUtility.HtmlDecode(anime.Synopsis)
|
||||||
|
.Replace("<br />", "")
|
||||||
|
.Replace("[i]", "*")
|
||||||
|
.Replace("[/i]", "*");
|
||||||
|
|
||||||
|
eb.Title = anime.Title;
|
||||||
|
eb.Description = description;
|
||||||
|
eb.ImageUrl = anime.Image;
|
||||||
|
eb.AddInlineField("Premiered", $"{anime.StartDate}");
|
||||||
|
eb.AddInlineField("Ended", anime.EndDate == "0000-00-00" ? "???" : anime.EndDate);
|
||||||
|
eb.AddInlineField("Status", anime.Status);
|
||||||
|
eb.AddInlineField("Episodes", anime.Episodes);
|
||||||
|
eb.AddInlineField("MAL Score", anime.Score);
|
||||||
|
eb.AddInlineField("Type", anime.Type);
|
||||||
|
eb.AddField("MAL Link", $"https://myanimelist.net/anime/{anime.Id}");
|
||||||
|
|
||||||
|
await ReplyAsync("", false, eb.Build());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await ReplyAsync("No anime found with that name...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await ReplyAsync(
|
||||||
|
"Unfortunally i'm not connected to MyAnimeList.net, please tell my senpai to connect me");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (XmlException e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context, "The MyAnimeList.net API refused to answer");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("manga", RunMode = RunMode.Async)]
|
||||||
|
[Summary("Show Info about a Manga.")]
|
||||||
|
public async Task SearchManga([Remainder] [Summary("manga-name")] string mangaName)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_malClient.IsLoggedIn())
|
||||||
|
{
|
||||||
|
var manga = await _malClient.GetManga(mangaName);
|
||||||
|
if (manga != null)
|
||||||
|
{
|
||||||
|
var eb = new EmbedBuilder();
|
||||||
|
|
||||||
|
var description = HttpUtility.HtmlDecode(manga.Synopsis)
|
||||||
|
.Replace("<br />", "")
|
||||||
|
.Replace("[i]", "*")
|
||||||
|
.Replace("[/i]", "*");
|
||||||
|
|
||||||
|
eb.Title = manga.Title;
|
||||||
|
eb.Description = description;
|
||||||
|
eb.ImageUrl = manga.Image;
|
||||||
|
eb.AddInlineField("Premiered", $"{manga.StartDate}");
|
||||||
|
eb.AddInlineField("Ended", manga.EndDate == "0000-00-00" ? "???" : manga.EndDate);
|
||||||
|
eb.AddInlineField("Status", manga.Status);
|
||||||
|
eb.AddInlineField("Volumes", manga.Volumes);
|
||||||
|
eb.AddInlineField("Chapters", manga.Chapters);
|
||||||
|
eb.AddInlineField("MAL Score", manga.Score);
|
||||||
|
eb.AddField("MAL Link", $"https://myanimelist.net/manga/{manga.Id}");
|
||||||
|
|
||||||
|
await ReplyAsync("", false, eb.Build());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await ReplyAsync("No manga found with that name...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await ReplyAsync(
|
||||||
|
"Unfortunally i'm not connected to MyAnimeList.net, please tell my senpai to connect me");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (XmlException e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context, "The MyAnimeList.net API refused to answer");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
namespace Geekbot.net.Commands.Integrations.UbranDictionary
|
||||||
|
{
|
||||||
|
internal class UrbanListItemDto
|
||||||
|
{
|
||||||
|
public string Definition { get; set; }
|
||||||
|
public string Permalink { get; set; }
|
||||||
|
public string ThumbsUp { get; set; }
|
||||||
|
public string Word { get; set; }
|
||||||
|
public string Example { get; set; }
|
||||||
|
public string ThumbsDown { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Commands.Integrations.UbranDictionary
|
||||||
|
{
|
||||||
|
internal class UrbanResponseDto
|
||||||
|
{
|
||||||
|
public string[] Tags { get; set; }
|
||||||
|
public List<UrbanListItemDto> List { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Discord;
|
||||||
|
using Discord.Commands;
|
||||||
|
using Geekbot.net.Lib;
|
||||||
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
|
using Geekbot.net.Lib.Extensions;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Commands.Integrations.UbranDictionary
|
||||||
|
{
|
||||||
|
public class UrbanDictionary : GeekbotBase
|
||||||
|
{
|
||||||
|
private readonly IErrorHandler _errorHandler;
|
||||||
|
|
||||||
|
public UrbanDictionary(IErrorHandler errorHandler)
|
||||||
|
{
|
||||||
|
_errorHandler = errorHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("urban", RunMode = RunMode.Async)]
|
||||||
|
[Summary("Lookup something on urban dictionary")]
|
||||||
|
public async Task UrbanDefine([Remainder] [Summary("word")] string word)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var client = new HttpClient())
|
||||||
|
{
|
||||||
|
client.BaseAddress = new Uri("https://api.urbandictionary.com");
|
||||||
|
var response = await client.GetAsync($"/v0/define?term={word}");
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
var stringResponse = await response.Content.ReadAsStringAsync();
|
||||||
|
var definitions = JsonConvert.DeserializeObject<UrbanResponseDto>(stringResponse);
|
||||||
|
if (definitions.List.Count == 0)
|
||||||
|
{
|
||||||
|
await ReplyAsync("That word hasn't been defined...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var definition = definitions.List.First(e => !string.IsNullOrWhiteSpace(e.Example));
|
||||||
|
|
||||||
|
var eb = new EmbedBuilder();
|
||||||
|
eb.WithAuthor(new EmbedAuthorBuilder
|
||||||
|
{
|
||||||
|
Name = definition.Word,
|
||||||
|
Url = definition.Permalink
|
||||||
|
});
|
||||||
|
eb.WithColor(new Color(239, 255, 0));
|
||||||
|
if (!string.IsNullOrEmpty(definition.Definition)) eb.Description = definition.Definition;
|
||||||
|
if (!string.IsNullOrEmpty(definition.Example)) eb.AddField("Example", definition.Example ?? "(no example given...)");
|
||||||
|
if (!string.IsNullOrEmpty(definition.ThumbsUp)) eb.AddInlineField("Upvotes", definition.ThumbsUp);
|
||||||
|
if (!string.IsNullOrEmpty(definition.ThumbsDown)) eb.AddInlineField("Downvotes", definition.ThumbsDown);
|
||||||
|
if (definitions.Tags?.Length > 0) eb.AddField("Tags", string.Join(", ", definitions.Tags));
|
||||||
|
|
||||||
|
await ReplyAsync("", false, eb.Build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,17 +5,17 @@ using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Geekbot.Core;
|
using Geekbot.net.Database;
|
||||||
using Geekbot.Core.Database;
|
using Geekbot.net.Lib;
|
||||||
using Geekbot.Core.ErrorHandling;
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
using Geekbot.Core.Extensions;
|
using Geekbot.net.Lib.Extensions;
|
||||||
using Geekbot.Core.WikipediaClient;
|
|
||||||
using Geekbot.Core.WikipediaClient.Page;
|
|
||||||
using HtmlAgilityPack;
|
using HtmlAgilityPack;
|
||||||
|
using WikipediaApi;
|
||||||
|
using WikipediaApi.Page;
|
||||||
|
|
||||||
namespace Geekbot.Bot.Commands.Integrations
|
namespace Geekbot.net.Commands.Integrations
|
||||||
{
|
{
|
||||||
public class Wikipedia : TransactionModuleBase
|
public class Wikipedia : GeekbotBase
|
||||||
{
|
{
|
||||||
private readonly IErrorHandler _errorHandler;
|
private readonly IErrorHandler _errorHandler;
|
||||||
private readonly IWikipediaClient _wikipediaClient;
|
private readonly IWikipediaClient _wikipediaClient;
|
59
Geekbot.net/Commands/Integrations/Youtube.cs
Normal file
59
Geekbot.net/Commands/Integrations/Youtube.cs
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Discord.Commands;
|
||||||
|
using Geekbot.net.Lib;
|
||||||
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
|
using Geekbot.net.Lib.GlobalSettings;
|
||||||
|
using Google.Apis.Services;
|
||||||
|
using Google.Apis.YouTube.v3;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Commands.Integrations
|
||||||
|
{
|
||||||
|
public class Youtube : GeekbotBase
|
||||||
|
{
|
||||||
|
private readonly IGlobalSettings _globalSettings;
|
||||||
|
private readonly IErrorHandler _errorHandler;
|
||||||
|
|
||||||
|
public Youtube(IGlobalSettings globalSettings, IErrorHandler errorHandler)
|
||||||
|
{
|
||||||
|
_globalSettings = globalSettings;
|
||||||
|
_errorHandler = errorHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("yt", RunMode = RunMode.Async)]
|
||||||
|
[Summary("Search for something on youtube.")]
|
||||||
|
public async Task Yt([Remainder] [Summary("title")] string searchQuery)
|
||||||
|
{
|
||||||
|
var key = _globalSettings.GetKey("YoutubeKey");
|
||||||
|
if (string.IsNullOrEmpty(key))
|
||||||
|
{
|
||||||
|
await ReplyAsync("No youtube key set, please tell my senpai to set one");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var youtubeService = new YouTubeService(new BaseClientService.Initializer
|
||||||
|
{
|
||||||
|
ApiKey = key,
|
||||||
|
ApplicationName = GetType().ToString()
|
||||||
|
});
|
||||||
|
|
||||||
|
var searchListRequest = youtubeService.Search.List("snippet");
|
||||||
|
searchListRequest.Q = searchQuery;
|
||||||
|
searchListRequest.MaxResults = 2;
|
||||||
|
|
||||||
|
var searchListResponse = await searchListRequest.ExecuteAsync();
|
||||||
|
|
||||||
|
var result = searchListResponse.Items[0];
|
||||||
|
|
||||||
|
await ReplyAsync(
|
||||||
|
$"\"{result.Snippet.Title}\" from \"{result.Snippet.ChannelTitle}\" https://youtu.be/{result.Id.VideoId}");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,13 +2,13 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Geekbot.Core;
|
using Geekbot.net.Lib;
|
||||||
using Geekbot.Core.ErrorHandling;
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
using Geekbot.Core.RandomNumberGenerator;
|
using Geekbot.net.Lib.RandomNumberGenerator;
|
||||||
|
|
||||||
namespace Geekbot.Bot.Commands.Randomness
|
namespace Geekbot.net.Commands.Randomness
|
||||||
{
|
{
|
||||||
public class BenedictCumberbatchNameGenerator : TransactionModuleBase
|
public class BenedictCumberbatchNameGenerator : GeekbotBase
|
||||||
{
|
{
|
||||||
private readonly IErrorHandler _errorHandler;
|
private readonly IErrorHandler _errorHandler;
|
||||||
private readonly IRandomNumberGenerator _randomNumberGenerator;
|
private readonly IRandomNumberGenerator _randomNumberGenerator;
|
||||||
|
@ -19,7 +19,7 @@ namespace Geekbot.Bot.Commands.Randomness
|
||||||
_randomNumberGenerator = randomNumberGenerator;
|
_randomNumberGenerator = randomNumberGenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Command("bdcb", RunMode = RunMode.Async)]
|
[Command("bdcc", RunMode = RunMode.Async)]
|
||||||
[Summary("Benedict Cumberbatch Name Generator")]
|
[Summary("Benedict Cumberbatch Name Generator")]
|
||||||
public async Task GetQuote()
|
public async Task GetQuote()
|
||||||
{
|
{
|
||||||
|
@ -60,4 +60,4 @@ namespace Geekbot.Bot.Commands.Randomness
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
53
Geekbot.net/Commands/Randomness/Cat/Cat.cs
Normal file
53
Geekbot.net/Commands/Randomness/Cat/Cat.cs
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Discord;
|
||||||
|
using Discord.Commands;
|
||||||
|
using Geekbot.net.Lib;
|
||||||
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Commands.Randomness.Cat
|
||||||
|
{
|
||||||
|
public class Cat : GeekbotBase
|
||||||
|
{
|
||||||
|
private readonly IErrorHandler _errorHandler;
|
||||||
|
|
||||||
|
public Cat(IErrorHandler errorHandler)
|
||||||
|
{
|
||||||
|
_errorHandler = errorHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("cat", RunMode = RunMode.Async)]
|
||||||
|
[Summary("Return a random image of a cat.")]
|
||||||
|
public async Task Say()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var client = new HttpClient())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
client.BaseAddress = new Uri("https://aws.random.cat");
|
||||||
|
var response = await client.GetAsync("/meow");
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
var stringResponse = await response.Content.ReadAsStringAsync();
|
||||||
|
var catFile = JsonConvert.DeserializeObject<CatResponseDto>(stringResponse);
|
||||||
|
var eb = new EmbedBuilder();
|
||||||
|
eb.ImageUrl = catFile.File;
|
||||||
|
await ReplyAsync("", false, eb.Build());
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
await ReplyAsync("Seems like the dog cought the cat (error occured)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
7
Geekbot.net/Commands/Randomness/Cat/CatResponseDto.cs
Normal file
7
Geekbot.net/Commands/Randomness/Cat/CatResponseDto.cs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
namespace Geekbot.net.Commands.Randomness.Cat
|
||||||
|
{
|
||||||
|
internal class CatResponseDto
|
||||||
|
{
|
||||||
|
public string File { get; set; }
|
||||||
|
}
|
||||||
|
}
|
72
Geekbot.net/Commands/Randomness/CheckEm.cs
Normal file
72
Geekbot.net/Commands/Randomness/CheckEm.cs
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Discord.Commands;
|
||||||
|
using Geekbot.net.Lib;
|
||||||
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
|
using Geekbot.net.Lib.Media;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Commands.Randomness
|
||||||
|
{
|
||||||
|
public class CheckEm : GeekbotBase
|
||||||
|
{
|
||||||
|
private readonly IMediaProvider _checkEmImages;
|
||||||
|
private readonly IErrorHandler _errorHandler;
|
||||||
|
|
||||||
|
public CheckEm(IMediaProvider mediaProvider, IErrorHandler errorHandler)
|
||||||
|
{
|
||||||
|
_checkEmImages = mediaProvider;
|
||||||
|
_errorHandler = errorHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("checkem", RunMode = RunMode.Async)]
|
||||||
|
[Summary("Check for dubs")]
|
||||||
|
public async Task MuhDubs()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var number = new Random().Next(10000000, 99999999);
|
||||||
|
var dubtriqua = "";
|
||||||
|
|
||||||
|
var ns = GetIntArray(number);
|
||||||
|
if (ns[7] == ns[6])
|
||||||
|
{
|
||||||
|
dubtriqua = "DUBS";
|
||||||
|
if (ns[6] == ns[5])
|
||||||
|
{
|
||||||
|
dubtriqua = "TRIPS";
|
||||||
|
if (ns[5] == ns[4])
|
||||||
|
dubtriqua = "QUADS";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.AppendLine($"Check em {Context.User.Mention}");
|
||||||
|
sb.AppendLine($"**{number}**");
|
||||||
|
if (!string.IsNullOrEmpty(dubtriqua))
|
||||||
|
sb.AppendLine($":tada: {dubtriqua} :tada:");
|
||||||
|
sb.AppendLine(_checkEmImages.GetCheckem());
|
||||||
|
|
||||||
|
await ReplyAsync(sb.ToString());
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int[] GetIntArray(int num)
|
||||||
|
{
|
||||||
|
var listOfInts = new List<int>();
|
||||||
|
while (num > 0)
|
||||||
|
{
|
||||||
|
listOfInts.Add(num % 10);
|
||||||
|
num = num / 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
listOfInts.Reverse();
|
||||||
|
return listOfInts.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace Geekbot.net.Commands.Randomness.Chuck
|
||||||
|
{
|
||||||
|
internal class ChuckNorrisJokeResponseDto
|
||||||
|
{
|
||||||
|
public string Value { get; set; }
|
||||||
|
}
|
||||||
|
}
|
52
Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokes.cs
Normal file
52
Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokes.cs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Discord.Commands;
|
||||||
|
using Geekbot.net.Lib;
|
||||||
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Commands.Randomness.Chuck
|
||||||
|
{
|
||||||
|
public class ChuckNorrisJokes : GeekbotBase
|
||||||
|
{
|
||||||
|
private readonly IErrorHandler _errorHandler;
|
||||||
|
|
||||||
|
public ChuckNorrisJokes(IErrorHandler errorHandler)
|
||||||
|
{
|
||||||
|
_errorHandler = errorHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("chuck", RunMode = RunMode.Async)]
|
||||||
|
[Summary("A random chuck norris joke")]
|
||||||
|
public async Task Say()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var client = new HttpClient())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
client.DefaultRequestHeaders.Accept.Clear();
|
||||||
|
client.DefaultRequestHeaders.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json"));
|
||||||
|
var response = await client.GetAsync("https://api.chucknorris.io/jokes/random");
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
var stringResponse = await response.Content.ReadAsStringAsync();
|
||||||
|
var data = JsonConvert.DeserializeObject<ChuckNorrisJokeResponseDto>(stringResponse);
|
||||||
|
await ReplyAsync(data.Value);
|
||||||
|
}
|
||||||
|
catch (HttpRequestException)
|
||||||
|
{
|
||||||
|
await ReplyAsync("Api down...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace Geekbot.net.Commands.Randomness.Dad
|
||||||
|
{
|
||||||
|
internal class DadJokeResponseDto
|
||||||
|
{
|
||||||
|
public string Joke { get; set; }
|
||||||
|
}
|
||||||
|
}
|
52
Geekbot.net/Commands/Randomness/Dad/DadJokes.cs
Normal file
52
Geekbot.net/Commands/Randomness/Dad/DadJokes.cs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Discord.Commands;
|
||||||
|
using Geekbot.net.Lib;
|
||||||
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Commands.Randomness.Dad
|
||||||
|
{
|
||||||
|
public class DadJokes : GeekbotBase
|
||||||
|
{
|
||||||
|
private readonly IErrorHandler _errorHandler;
|
||||||
|
|
||||||
|
public DadJokes(IErrorHandler errorHandler)
|
||||||
|
{
|
||||||
|
_errorHandler = errorHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("dad", RunMode = RunMode.Async)]
|
||||||
|
[Summary("A random dad joke")]
|
||||||
|
public async Task Say()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var client = new HttpClient())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
client.DefaultRequestHeaders.Accept.Clear();
|
||||||
|
client.DefaultRequestHeaders.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json"));
|
||||||
|
var response = await client.GetAsync("https://icanhazdadjoke.com/");
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
var stringResponse = await response.Content.ReadAsStringAsync();
|
||||||
|
var data = JsonConvert.DeserializeObject<DadJokeResponseDto>(stringResponse);
|
||||||
|
await ReplyAsync(data.Joke);
|
||||||
|
}
|
||||||
|
catch (HttpRequestException)
|
||||||
|
{
|
||||||
|
await ReplyAsync("Api down...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
53
Geekbot.net/Commands/Randomness/Dog/Dog.cs
Normal file
53
Geekbot.net/Commands/Randomness/Dog/Dog.cs
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Discord;
|
||||||
|
using Discord.Commands;
|
||||||
|
using Geekbot.net.Lib;
|
||||||
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Commands.Randomness.Dog
|
||||||
|
{
|
||||||
|
public class Dog : GeekbotBase
|
||||||
|
{
|
||||||
|
private readonly IErrorHandler _errorHandler;
|
||||||
|
|
||||||
|
public Dog(IErrorHandler errorHandler)
|
||||||
|
{
|
||||||
|
_errorHandler = errorHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("dog", RunMode = RunMode.Async)]
|
||||||
|
[Summary("Return a random image of a dog.")]
|
||||||
|
public async Task Say()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var client = new HttpClient())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
client.BaseAddress = new Uri("http://random.dog");
|
||||||
|
var response = await client.GetAsync("/woof.json");
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
var stringResponse = await response.Content.ReadAsStringAsync();
|
||||||
|
var dogFile = JsonConvert.DeserializeObject<DogResponseDto>(stringResponse);
|
||||||
|
var eb = new EmbedBuilder();
|
||||||
|
eb.ImageUrl = dogFile.Url;
|
||||||
|
await ReplyAsync("", false, eb.Build());
|
||||||
|
}
|
||||||
|
catch (HttpRequestException e)
|
||||||
|
{
|
||||||
|
await ReplyAsync($"Seems like the dog got lost (error occured)\r\n{e.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
7
Geekbot.net/Commands/Randomness/Dog/DogResponseDto.cs
Normal file
7
Geekbot.net/Commands/Randomness/Dog/DogResponseDto.cs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
namespace Geekbot.net.Commands.Randomness.Dog
|
||||||
|
{
|
||||||
|
internal class DogResponseDto
|
||||||
|
{
|
||||||
|
public string Url { get; set; }
|
||||||
|
}
|
||||||
|
}
|
58
Geekbot.net/Commands/Randomness/EightBall.cs
Normal file
58
Geekbot.net/Commands/Randomness/EightBall.cs
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Discord.Commands;
|
||||||
|
using Geekbot.net.Lib;
|
||||||
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Commands.Randomness
|
||||||
|
{
|
||||||
|
public class EightBall : GeekbotBase
|
||||||
|
{
|
||||||
|
private readonly IErrorHandler _errorHandler;
|
||||||
|
|
||||||
|
public EightBall(IErrorHandler errorHandler)
|
||||||
|
{
|
||||||
|
_errorHandler = errorHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("8ball", RunMode = RunMode.Async)]
|
||||||
|
[Summary("Ask 8Ball a Question.")]
|
||||||
|
public async Task Ball([Remainder] [Summary("question")] string echo)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var replies = new List<string>
|
||||||
|
{
|
||||||
|
"It is certain",
|
||||||
|
"It is decidedly so",
|
||||||
|
"Without a doubt",
|
||||||
|
"Yes, definitely",
|
||||||
|
"You may rely on it",
|
||||||
|
"As I see it, yes",
|
||||||
|
"Most likely",
|
||||||
|
"Outlook good",
|
||||||
|
"Yes",
|
||||||
|
"Signs point to yes",
|
||||||
|
"Reply hazy try again",
|
||||||
|
"Ask again later",
|
||||||
|
"Better not tell you now",
|
||||||
|
"Cannot predict now",
|
||||||
|
"Concentrate and ask again",
|
||||||
|
"Don't count on it",
|
||||||
|
"My reply is no",
|
||||||
|
"My sources say no",
|
||||||
|
"Outlook not so good",
|
||||||
|
"Very doubtful"
|
||||||
|
};
|
||||||
|
|
||||||
|
var answer = new Random().Next(replies.Count);
|
||||||
|
await ReplyAsync(replies[answer]);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Geekbot.Core;
|
using Geekbot.net.Lib;
|
||||||
using Geekbot.Core.Media;
|
using Geekbot.net.Lib.Media;
|
||||||
|
|
||||||
namespace Geekbot.Bot.Commands.Randomness
|
namespace Geekbot.net.Commands.Randomness
|
||||||
{
|
{
|
||||||
public class Fortune : TransactionModuleBase
|
public class Fortune : GeekbotBase
|
||||||
{
|
{
|
||||||
private readonly IFortunesProvider _fortunes;
|
private readonly IFortunesProvider _fortunes;
|
||||||
|
|
39
Geekbot.net/Commands/Randomness/Gdq.cs
Normal file
39
Geekbot.net/Commands/Randomness/Gdq.cs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
using System;
|
||||||
|
using System.Net;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Discord.Commands;
|
||||||
|
using Geekbot.net.Lib;
|
||||||
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Commands.Randomness
|
||||||
|
{
|
||||||
|
public class Gdq : GeekbotBase
|
||||||
|
{
|
||||||
|
private readonly IErrorHandler _errorHandler;
|
||||||
|
|
||||||
|
public Gdq(IErrorHandler errorHandler)
|
||||||
|
{
|
||||||
|
_errorHandler = errorHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("gdq", RunMode = RunMode.Async)]
|
||||||
|
[Summary("Get a quote from the GDQ donation generator.")]
|
||||||
|
public async Task GetQuote()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var client = new WebClient())
|
||||||
|
{
|
||||||
|
var url = new Uri("http://taskinoz.com/gdq/api/");
|
||||||
|
var response = client.DownloadString(url);
|
||||||
|
|
||||||
|
await ReplyAsync(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
54
Geekbot.net/Commands/Randomness/Kanye/Kanye.cs
Normal file
54
Geekbot.net/Commands/Randomness/Kanye/Kanye.cs
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Discord.Commands;
|
||||||
|
using Geekbot.net.Commands.Randomness.Dad;
|
||||||
|
using Geekbot.net.Lib;
|
||||||
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
|
using Microsoft.AspNetCore.Hosting.Internal;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Commands.Randomness.Kanye
|
||||||
|
{
|
||||||
|
public class Kanye : GeekbotBase
|
||||||
|
{
|
||||||
|
private readonly IErrorHandler _errorHandler;
|
||||||
|
|
||||||
|
public Kanye(IErrorHandler errorHandler)
|
||||||
|
{
|
||||||
|
_errorHandler = errorHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("kanye", RunMode = RunMode.Async)]
|
||||||
|
[Summary("A random kayne west quote")]
|
||||||
|
public async Task Say()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var client = new HttpClient())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
client.DefaultRequestHeaders.Accept.Clear();
|
||||||
|
client.DefaultRequestHeaders.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json"));
|
||||||
|
var response = await client.GetAsync("https://api.kanye.rest/");
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
var stringResponse = await response.Content.ReadAsStringAsync();
|
||||||
|
var data = JsonConvert.DeserializeObject<KanyeResponseDto>(stringResponse);
|
||||||
|
await ReplyAsync(data.Quote);
|
||||||
|
}
|
||||||
|
catch (HttpRequestException)
|
||||||
|
{
|
||||||
|
await ReplyAsync("Api down...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace Geekbot.net.Commands.Randomness.Kanye
|
||||||
|
{
|
||||||
|
public class KanyeResponseDto
|
||||||
|
{
|
||||||
|
public string Id { get; set; }
|
||||||
|
public string Quote { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +1,12 @@
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Geekbot.Core;
|
using Geekbot.net.Lib;
|
||||||
using Geekbot.Core.Media;
|
using Geekbot.net.Lib.Media;
|
||||||
|
|
||||||
namespace Geekbot.Bot.Commands.Randomness
|
namespace Geekbot.net.Commands.Randomness
|
||||||
{
|
{
|
||||||
public class RandomAnimals : TransactionModuleBase
|
public class RandomAnimals : GeekbotBase
|
||||||
{
|
{
|
||||||
private readonly IMediaProvider _mediaProvider;
|
private readonly IMediaProvider _mediaProvider;
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ namespace Geekbot.Bot.Commands.Randomness
|
||||||
[Summary("Get a random panda image")]
|
[Summary("Get a random panda image")]
|
||||||
public async Task Panda()
|
public async Task Panda()
|
||||||
{
|
{
|
||||||
await ReplyAsync("", false, Eb(_mediaProvider.GetMedia(MediaType.Panda)));
|
await ReplyAsync("", false, Eb(_mediaProvider.GetPanda()));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Command("croissant", RunMode = RunMode.Async)]
|
[Command("croissant", RunMode = RunMode.Async)]
|
||||||
|
@ -27,50 +27,50 @@ namespace Geekbot.Bot.Commands.Randomness
|
||||||
[Summary("Get a random croissant image")]
|
[Summary("Get a random croissant image")]
|
||||||
public async Task Croissant()
|
public async Task Croissant()
|
||||||
{
|
{
|
||||||
await ReplyAsync("", false, Eb(_mediaProvider.GetMedia(MediaType.Croissant)));
|
await ReplyAsync("", false, Eb(_mediaProvider.GetCrossant()));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Command("pumpkin", RunMode = RunMode.Async)]
|
[Command("pumpkin", RunMode = RunMode.Async)]
|
||||||
[Summary("Get a random pumpkin image")]
|
[Summary("Get a random pumpkin image")]
|
||||||
public async Task Pumpkin()
|
public async Task Pumpkin()
|
||||||
{
|
{
|
||||||
await ReplyAsync("", false, Eb(_mediaProvider.GetMedia(MediaType.Pumpkin)));
|
await ReplyAsync("", false, Eb(_mediaProvider.GetPumpkin()));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Command("squirrel", RunMode = RunMode.Async)]
|
[Command("squirrel", RunMode = RunMode.Async)]
|
||||||
[Summary("Get a random squirrel image")]
|
[Summary("Get a random squirrel image")]
|
||||||
public async Task Squirrel()
|
public async Task Squirrel()
|
||||||
{
|
{
|
||||||
await ReplyAsync("", false, Eb(_mediaProvider.GetMedia(MediaType.Squirrel)));
|
await ReplyAsync("", false, Eb(_mediaProvider.GetSquirrel()));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Command("turtle", RunMode = RunMode.Async)]
|
[Command("turtle", RunMode = RunMode.Async)]
|
||||||
[Summary("Get a random turtle image")]
|
[Summary("Get a random turtle image")]
|
||||||
public async Task Turtle()
|
public async Task Turtle()
|
||||||
{
|
{
|
||||||
await ReplyAsync("", false, Eb(_mediaProvider.GetMedia(MediaType.Turtle)));
|
await ReplyAsync("", false, Eb(_mediaProvider.GetTurtle()));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Command("penguin", RunMode = RunMode.Async)]
|
[Command("pinguin", RunMode = RunMode.Async)]
|
||||||
[Alias("pengu")]
|
[Alias("pingu")]
|
||||||
[Summary("Get a random penguin image")]
|
[Summary("Get a random pinguin image")]
|
||||||
public async Task Penguin()
|
public async Task Pinguin()
|
||||||
{
|
{
|
||||||
await ReplyAsync("", false, Eb(_mediaProvider.GetMedia(MediaType.Penguin)));
|
await ReplyAsync("", false, Eb(_mediaProvider.GetPinguin()));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Command("fox", RunMode = RunMode.Async)]
|
[Command("fox", RunMode = RunMode.Async)]
|
||||||
[Summary("Get a random fox image")]
|
[Summary("Get a random fox image")]
|
||||||
public async Task Fox()
|
public async Task Fox()
|
||||||
{
|
{
|
||||||
await ReplyAsync("", false, Eb(_mediaProvider.GetMedia(MediaType.Fox)));
|
await ReplyAsync("", false, Eb(_mediaProvider.GetFox()));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Command("dab", RunMode = RunMode.Async)]
|
[Command("dab", RunMode = RunMode.Async)]
|
||||||
[Summary("Get a random dab image")]
|
[Summary("Get a random dab image")]
|
||||||
public async Task Dab()
|
public async Task Dab()
|
||||||
{
|
{
|
||||||
await ReplyAsync("", false, Eb(_mediaProvider.GetMedia(MediaType.Dab)));
|
await ReplyAsync("", false, Eb(_mediaProvider.GetDab()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Embed Eb(string image)
|
private static Embed Eb(string image)
|
|
@ -3,25 +3,25 @@ using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Geekbot.Core;
|
using Geekbot.net.Database;
|
||||||
using Geekbot.Core.Database;
|
using Geekbot.net.Database.Models;
|
||||||
using Geekbot.Core.Database.Models;
|
using Geekbot.net.Lib;
|
||||||
using Geekbot.Core.ErrorHandling;
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
using Geekbot.Core.Extensions;
|
using Geekbot.net.Lib.Extensions;
|
||||||
using Geekbot.Core.GuildSettingsManager;
|
using Geekbot.net.Lib.RandomNumberGenerator;
|
||||||
using Geekbot.Core.RandomNumberGenerator;
|
|
||||||
using Localization = Geekbot.Core.Localization;
|
|
||||||
|
|
||||||
namespace Geekbot.Bot.Commands.Randomness
|
namespace Geekbot.net.Commands.Randomness
|
||||||
{
|
{
|
||||||
public class Ship : GeekbotCommandBase
|
public class Ship : GeekbotBase
|
||||||
{
|
{
|
||||||
|
private readonly IErrorHandler _errorHandler;
|
||||||
private readonly IRandomNumberGenerator _randomNumberGenerator;
|
private readonly IRandomNumberGenerator _randomNumberGenerator;
|
||||||
private readonly DatabaseContext _database;
|
private readonly DatabaseContext _database;
|
||||||
|
|
||||||
public Ship(DatabaseContext database, IErrorHandler errorHandler, IRandomNumberGenerator randomNumberGenerator, IGuildSettingsManager guildSettingsManager) : base(errorHandler, guildSettingsManager)
|
public Ship(DatabaseContext database, IErrorHandler errorHandler, IRandomNumberGenerator randomNumberGenerator)
|
||||||
{
|
{
|
||||||
_database = database;
|
_database = database;
|
||||||
|
_errorHandler = errorHandler;
|
||||||
_randomNumberGenerator = randomNumberGenerator;
|
_randomNumberGenerator = randomNumberGenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,45 +56,45 @@ namespace Geekbot.Bot.Commands.Randomness
|
||||||
shippingRate = dbval.Strength;
|
shippingRate = dbval.Strength;
|
||||||
}
|
}
|
||||||
|
|
||||||
var reply = $":heartpulse: **{Localization.Ship.Matchmaking}** :heartpulse:\r\n";
|
var reply = ":heartpulse: **Matchmaking** :heartpulse:\r\n";
|
||||||
reply += $":two_hearts: {user1.Mention} :heart: {user2.Mention} :two_hearts:\r\n";
|
reply = reply + $":two_hearts: {user1.Mention} :heart: {user2.Mention} :two_hearts:\r\n";
|
||||||
reply += $"0% [{BlockCounter(shippingRate)}] 100% - {DeterminateSuccess(shippingRate)}";
|
reply = reply + $"0% [{BlockCounter(shippingRate)}] 100% - {DeterminateSuccess(shippingRate)}";
|
||||||
await ReplyAsync(reply);
|
await ReplyAsync(reply);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
await ErrorHandler.HandleCommandException(e, Context);
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string DeterminateSuccess(int rate)
|
private string DeterminateSuccess(int rate)
|
||||||
{
|
{
|
||||||
return (rate / 20) switch
|
if (rate < 20)
|
||||||
{
|
return "Not gonna happen";
|
||||||
0 => Localization.Ship.NotGoingToHappen,
|
if (rate >= 20 && rate < 40)
|
||||||
1 => Localization.Ship.NotSuchAGoodIdea,
|
return "Not such a good idea";
|
||||||
2 => Localization.Ship.ThereMightBeAChance,
|
if (rate >= 40 && rate < 60)
|
||||||
3 => Localization.Ship.CouldWork,
|
return "There might be a chance";
|
||||||
4 => Localization.Ship.ItsAMatch,
|
if (rate >= 60 && rate < 80)
|
||||||
_ => "nope"
|
return "Almost a match, but could work";
|
||||||
};
|
return rate >= 80 ? "It's a match" : "a";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string BlockCounter(int rate)
|
private string BlockCounter(int rate)
|
||||||
{
|
{
|
||||||
var amount = rate / 10;
|
var amount = Math.Floor(decimal.Floor(rate / 10));
|
||||||
Console.WriteLine(amount);
|
Console.WriteLine(amount);
|
||||||
var blocks = "";
|
var blocks = "";
|
||||||
for (var i = 1; i <= 10; i++)
|
for (var i = 1; i <= 10; i++)
|
||||||
if (i <= amount)
|
if (i <= amount)
|
||||||
{
|
{
|
||||||
blocks += ":white_medium_small_square:";
|
blocks = blocks + ":white_medium_small_square:";
|
||||||
if (i == amount)
|
if (i == amount)
|
||||||
blocks += $" {rate}% ";
|
blocks = blocks + $" {rate}% ";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
blocks += ":black_medium_small_square:";
|
blocks = blocks + ":black_medium_small_square:";
|
||||||
}
|
}
|
||||||
|
|
||||||
return blocks;
|
return blocks;
|
|
@ -4,15 +4,15 @@ using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Geekbot.Core;
|
using Geekbot.net.Database;
|
||||||
using Geekbot.Core.Database;
|
using Geekbot.net.Database.Models;
|
||||||
using Geekbot.Core.Database.Models;
|
using Geekbot.net.Lib;
|
||||||
using Geekbot.Core.ErrorHandling;
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
using Geekbot.Core.Extensions;
|
using Geekbot.net.Lib.Extensions;
|
||||||
|
|
||||||
namespace Geekbot.Bot.Commands.Randomness
|
namespace Geekbot.net.Commands.Randomness
|
||||||
{
|
{
|
||||||
public class Slap : TransactionModuleBase
|
public class Slap : GeekbotBase
|
||||||
{
|
{
|
||||||
private readonly IErrorHandler _errorHandler;
|
private readonly IErrorHandler _errorHandler;
|
||||||
private readonly DatabaseContext _database;
|
private readonly DatabaseContext _database;
|
||||||
|
@ -25,7 +25,7 @@ namespace Geekbot.Bot.Commands.Randomness
|
||||||
|
|
||||||
[Command("slap", RunMode = RunMode.Async)]
|
[Command("slap", RunMode = RunMode.Async)]
|
||||||
[Summary("slap someone")]
|
[Summary("slap someone")]
|
||||||
public async Task Slapper([Summary("@someone")] IUser user)
|
public async Task Slapper([Summary("@someone")] IGuildUser user)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -77,14 +77,10 @@ namespace Geekbot.Bot.Commands.Randomness
|
||||||
"teapot",
|
"teapot",
|
||||||
"candle",
|
"candle",
|
||||||
"dictionary",
|
"dictionary",
|
||||||
"powerless banhammer",
|
"powerless banhammer"
|
||||||
"piece of low fat mozzarella",
|
|
||||||
// For some reason it never picks the last one
|
|
||||||
// Adding this workaround, because i'm to lazy to actually fix it at the time of writing this
|
|
||||||
"padding"
|
|
||||||
};
|
};
|
||||||
|
|
||||||
await ReplyAsync($"{Context.User.Username} slapped {user.Username} with a {things[new Random().Next(0, things.Count - 1)]}");
|
await ReplyAsync($"{Context.GuildUser.Nickname} slapped {user.Nickname} with a {things[new Random().Next(things.Count - 1)]}");
|
||||||
|
|
||||||
await UpdateRecieved(user.Id);
|
await UpdateRecieved(user.Id);
|
||||||
await UpdateGiven(Context.User.Id);
|
await UpdateGiven(Context.User.Id);
|
||||||
|
@ -132,4 +128,4 @@ namespace Geekbot.Bot.Commands.Randomness
|
||||||
e.UserId.Equals(userId.AsLong()));
|
e.UserId.Equals(userId.AsLong()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,30 +3,29 @@ using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Geekbot.Bot.CommandPreconditions;
|
using Geekbot.net.Database;
|
||||||
using Geekbot.Core;
|
using Geekbot.net.Database.Models;
|
||||||
using Geekbot.Core.Database;
|
using Geekbot.net.Lib;
|
||||||
using Geekbot.Core.Database.Models;
|
using Geekbot.net.Lib.CommandPreconditions;
|
||||||
using Geekbot.Core.ErrorHandling;
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
using Geekbot.Core.Extensions;
|
using Geekbot.net.Lib.Extensions;
|
||||||
using Geekbot.Core.GuildSettingsManager;
|
using Geekbot.net.Lib.Localization;
|
||||||
using Geekbot.Core.RandomNumberGenerator;
|
using Geekbot.net.Lib.RandomNumberGenerator;
|
||||||
using Localization = Geekbot.Core.Localization;
|
|
||||||
|
|
||||||
namespace Geekbot.Bot.Commands.Rpg
|
namespace Geekbot.net.Commands.Rpg
|
||||||
{
|
{
|
||||||
[DisableInDirectMessage]
|
[DisableInDirectMessage]
|
||||||
[Group("cookies")]
|
[Group("cookies")]
|
||||||
[Alias("cookie")]
|
public class Cookies : GeekbotBase
|
||||||
public class Cookies : GeekbotCommandBase
|
|
||||||
{
|
{
|
||||||
private readonly DatabaseContext _database;
|
private readonly DatabaseContext _database;
|
||||||
|
private readonly IErrorHandler _errorHandler;
|
||||||
private readonly IRandomNumberGenerator _randomNumberGenerator;
|
private readonly IRandomNumberGenerator _randomNumberGenerator;
|
||||||
|
|
||||||
public Cookies(DatabaseContext database, IErrorHandler errorHandler, IRandomNumberGenerator randomNumberGenerator, IGuildSettingsManager guildSettingsManager)
|
public Cookies(DatabaseContext database, IErrorHandler errorHandler, IRandomNumberGenerator randomNumberGenerator)
|
||||||
: base(errorHandler, guildSettingsManager)
|
|
||||||
{
|
{
|
||||||
_database = database;
|
_database = database;
|
||||||
|
_errorHandler = errorHandler;
|
||||||
_randomNumberGenerator = randomNumberGenerator;
|
_randomNumberGenerator = randomNumberGenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,23 +36,21 @@ namespace Geekbot.Bot.Commands.Rpg
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var actor = await GetUser(Context.User.Id);
|
var actor = await GetUser(Context.User.Id);
|
||||||
var timeoutDays = 1;
|
if (actor.LastPayout.Value.AddHours(24) > DateTimeOffset.Now)
|
||||||
if (actor.LastPayout?.AddDays(timeoutDays) > DateTime.Now.ToUniversalTime())
|
|
||||||
{
|
{
|
||||||
var remaining = actor.LastPayout.Value.AddDays(timeoutDays) - DateTimeOffset.Now.ToUniversalTime();
|
var formatedWaitTime = Context.Translations.FormatDateTimeAsRemaining(actor.LastPayout.Value.AddHours(24));
|
||||||
var formattedWaitTime = DateLocalization.FormatDateTimeAsRemaining(remaining);
|
await ReplyAsync(Context.Translations.GetString("WaitForMoreCookies", formatedWaitTime));
|
||||||
await ReplyAsync(string.Format(Localization.Cookies.WaitForMoreCookies, formattedWaitTime));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
actor.Cookies += 10;
|
actor.Cookies += 10;
|
||||||
actor.LastPayout = DateTimeOffset.Now.ToUniversalTime();
|
actor.LastPayout = DateTimeOffset.Now;
|
||||||
await SetUser(actor);
|
await SetUser(actor);
|
||||||
await ReplyAsync(string.Format(Localization.Cookies.GetCookies, 10, actor.Cookies));
|
await ReplyAsync(Context.Translations.GetString("GetCookies", 10, actor.Cookies));
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
await ErrorHandler.HandleCommandException(e, Context);
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,11 +61,11 @@ namespace Geekbot.Bot.Commands.Rpg
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var actor = await GetUser(Context.User.Id);
|
var actor = await GetUser(Context.User.Id);
|
||||||
await ReplyAsync(string.Format(Localization.Cookies.InYourJar, actor.Cookies));
|
await ReplyAsync(Context.Translations.GetString("InYourJar", actor.Cookies));
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
await ErrorHandler.HandleCommandException(e, Context);
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,15 +77,9 @@ namespace Geekbot.Bot.Commands.Rpg
|
||||||
{
|
{
|
||||||
var giver = await GetUser(Context.User.Id);
|
var giver = await GetUser(Context.User.Id);
|
||||||
|
|
||||||
if (amount < 1)
|
|
||||||
{
|
|
||||||
await ReplyAsync(Localization.Cookies.CantTakeCookies);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (giver.Cookies < amount)
|
if (giver.Cookies < amount)
|
||||||
{
|
{
|
||||||
await ReplyAsync(Localization.Cookies.NotEnoughToGive);
|
await ReplyAsync(Context.Translations.GetString("NotEnoughToGive"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,11 +91,11 @@ namespace Geekbot.Bot.Commands.Rpg
|
||||||
await SetUser(giver);
|
await SetUser(giver);
|
||||||
await SetUser(taker);
|
await SetUser(taker);
|
||||||
|
|
||||||
await ReplyAsync(string.Format(Localization.Cookies.Given, amount, user.Username));
|
await ReplyAsync(Context.Translations.GetString("Given", amount, user.Username));
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
await ErrorHandler.HandleCommandException(e, Context);
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +109,7 @@ namespace Geekbot.Bot.Commands.Rpg
|
||||||
|
|
||||||
if (actor.Cookies < 5)
|
if (actor.Cookies < 5)
|
||||||
{
|
{
|
||||||
await ReplyAsync(Localization.Cookies.NotEnoughCookiesToEat);
|
await ReplyAsync(Context.Translations.GetString("NotEnoughCookiesToEat"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,14 +118,14 @@ namespace Geekbot.Bot.Commands.Rpg
|
||||||
|
|
||||||
await SetUser(actor);
|
await SetUser(actor);
|
||||||
|
|
||||||
await ReplyAsync(string.Format(Localization.Cookies.AteCookies, amount, actor.Cookies));
|
await ReplyAsync(Context.Translations.GetString("AteCookies", amount, actor.Cookies));
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
await ErrorHandler.HandleCommandException(e, Context);
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<CookiesModel> GetUser(ulong userId)
|
private async Task<CookiesModel> GetUser(ulong userId)
|
||||||
{
|
{
|
||||||
var user = _database.Cookies.FirstOrDefault(u =>u.GuildId.Equals(Context.Guild.Id.AsLong()) && u.UserId.Equals(userId.AsLong())) ?? await CreateNewRow(userId);
|
var user = _database.Cookies.FirstOrDefault(u =>u.GuildId.Equals(Context.Guild.Id.AsLong()) && u.UserId.Equals(userId.AsLong())) ?? await CreateNewRow(userId);
|
||||||
|
@ -154,7 +145,7 @@ namespace Geekbot.Bot.Commands.Rpg
|
||||||
GuildId = Context.Guild.Id.AsLong(),
|
GuildId = Context.Guild.Id.AsLong(),
|
||||||
UserId = userId.AsLong(),
|
UserId = userId.AsLong(),
|
||||||
Cookies = 0,
|
Cookies = 0,
|
||||||
LastPayout = DateTimeOffset.MinValue.ToUniversalTime()
|
LastPayout = DateTimeOffset.MinValue
|
||||||
};
|
};
|
||||||
var newUser = _database.Cookies.Add(user).Entity;
|
var newUser = _database.Cookies.Add(user).Entity;
|
||||||
await _database.SaveChangesAsync();
|
await _database.SaveChangesAsync();
|
|
@ -3,16 +3,16 @@ using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Geekbot.Bot.CommandPreconditions;
|
using Geekbot.net.Database;
|
||||||
using Geekbot.Core;
|
using Geekbot.net.Lib;
|
||||||
using Geekbot.Core.Database;
|
using Geekbot.net.Lib.CommandPreconditions;
|
||||||
using Geekbot.Core.ErrorHandling;
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
using Geekbot.Core.Extensions;
|
using Geekbot.net.Lib.Extensions;
|
||||||
using Geekbot.Core.Levels;
|
using Geekbot.net.Lib.Levels;
|
||||||
|
|
||||||
namespace Geekbot.Bot.Commands.User
|
namespace Geekbot.net.Commands.User
|
||||||
{
|
{
|
||||||
public class GuildInfo : TransactionModuleBase
|
public class GuildInfo : GeekbotBase
|
||||||
{
|
{
|
||||||
private readonly IErrorHandler _errorHandler;
|
private readonly IErrorHandler _errorHandler;
|
||||||
private readonly DatabaseContext _database;
|
private readonly DatabaseContext _database;
|
149
Geekbot.net/Commands/User/Karma.cs
Normal file
149
Geekbot.net/Commands/User/Karma.cs
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Discord;
|
||||||
|
using Discord.Commands;
|
||||||
|
using Geekbot.net.Database;
|
||||||
|
using Geekbot.net.Database.Models;
|
||||||
|
using Geekbot.net.Lib;
|
||||||
|
using Geekbot.net.Lib.CommandPreconditions;
|
||||||
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
|
using Geekbot.net.Lib.Extensions;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Commands.User
|
||||||
|
{
|
||||||
|
[DisableInDirectMessage]
|
||||||
|
public class Karma : GeekbotBase
|
||||||
|
{
|
||||||
|
private readonly IErrorHandler _errorHandler;
|
||||||
|
private readonly DatabaseContext _database;
|
||||||
|
|
||||||
|
public Karma(DatabaseContext database, IErrorHandler errorHandler)
|
||||||
|
{
|
||||||
|
_database = database;
|
||||||
|
_errorHandler = errorHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("good", RunMode = RunMode.Async)]
|
||||||
|
[Summary("Increase Someones Karma")]
|
||||||
|
public async Task Good([Summary("@someone")] IUser user)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var actor = await GetUser(Context.User.Id);
|
||||||
|
if (user.Id == Context.User.Id)
|
||||||
|
{
|
||||||
|
await ReplyAsync(Context.Translations.GetString("CannotChangeOwn", Context.User.Username));
|
||||||
|
}
|
||||||
|
else if (TimeoutFinished(actor.TimeOut))
|
||||||
|
{
|
||||||
|
var formatedWaitTime = Context.Translations.FormatDateTimeAsRemaining(actor.TimeOut.AddMinutes(3));
|
||||||
|
await ReplyAsync(Context.Translations.GetString("WaitUntill", Context.User.Username, formatedWaitTime));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var target = await GetUser(user.Id);
|
||||||
|
target.Karma = target.Karma + 1;
|
||||||
|
SetUser(target);
|
||||||
|
|
||||||
|
actor.TimeOut = DateTimeOffset.Now;
|
||||||
|
SetUser(actor);
|
||||||
|
|
||||||
|
await _database.SaveChangesAsync();
|
||||||
|
|
||||||
|
var eb = new EmbedBuilder();
|
||||||
|
eb.WithAuthor(new EmbedAuthorBuilder()
|
||||||
|
.WithIconUrl(user.GetAvatarUrl())
|
||||||
|
.WithName(user.Username));
|
||||||
|
|
||||||
|
eb.WithColor(new Color(138, 219, 146));
|
||||||
|
eb.Title = Context.Translations.GetString("Increased");
|
||||||
|
eb.AddInlineField(Context.Translations.GetString("By"), Context.User.Username);
|
||||||
|
eb.AddInlineField(Context.Translations.GetString("Amount"), "+1");
|
||||||
|
eb.AddInlineField(Context.Translations.GetString("Current"), target.Karma);
|
||||||
|
await ReplyAsync("", false, eb.Build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("bad", RunMode = RunMode.Async)]
|
||||||
|
[Summary("Decrease Someones Karma")]
|
||||||
|
public async Task Bad([Summary("@someone")] IUser user)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var actor = await GetUser(Context.User.Id);
|
||||||
|
if (user.Id == Context.User.Id)
|
||||||
|
{
|
||||||
|
await ReplyAsync(Context.Translations.GetString("CannotChangeOwn", Context.User.Username));
|
||||||
|
}
|
||||||
|
else if (TimeoutFinished(actor.TimeOut))
|
||||||
|
{
|
||||||
|
var formatedWaitTime = Context.Translations.FormatDateTimeAsRemaining(actor.TimeOut.AddMinutes(3));
|
||||||
|
await ReplyAsync(Context.Translations.GetString("WaitUntill", Context.User.Username, formatedWaitTime));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var target = await GetUser(user.Id);
|
||||||
|
target.Karma = target.Karma - 1;
|
||||||
|
SetUser(target);
|
||||||
|
|
||||||
|
actor.TimeOut = DateTimeOffset.Now;
|
||||||
|
SetUser(actor);
|
||||||
|
|
||||||
|
await _database.SaveChangesAsync();
|
||||||
|
|
||||||
|
var eb = new EmbedBuilder();
|
||||||
|
eb.WithAuthor(new EmbedAuthorBuilder()
|
||||||
|
.WithIconUrl(user.GetAvatarUrl())
|
||||||
|
.WithName(user.Username));
|
||||||
|
|
||||||
|
eb.WithColor(new Color(138, 219, 146));
|
||||||
|
eb.Title = Context.Translations.GetString("Decreased");
|
||||||
|
eb.AddInlineField(Context.Translations.GetString("By"), Context.User.Username);
|
||||||
|
eb.AddInlineField(Context.Translations.GetString("Amount"), "-1");
|
||||||
|
eb.AddInlineField(Context.Translations.GetString("Current"), target.Karma);
|
||||||
|
await ReplyAsync("", false, eb.Build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TimeoutFinished(DateTimeOffset lastKarma)
|
||||||
|
{
|
||||||
|
return lastKarma.AddMinutes(3) > DateTimeOffset.Now;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<KarmaModel> GetUser(ulong userId)
|
||||||
|
{
|
||||||
|
var user = _database.Karma.FirstOrDefault(u =>u.GuildId.Equals(Context.Guild.Id.AsLong()) && u.UserId.Equals(userId.AsLong())) ?? await CreateNewRow(userId);
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetUser(KarmaModel user)
|
||||||
|
{
|
||||||
|
_database.Karma.Update(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<KarmaModel> CreateNewRow(ulong userId)
|
||||||
|
{
|
||||||
|
var user = new KarmaModel()
|
||||||
|
{
|
||||||
|
GuildId = Context.Guild.Id.AsLong(),
|
||||||
|
UserId = userId.AsLong(),
|
||||||
|
Karma = 0,
|
||||||
|
TimeOut = DateTimeOffset.MinValue
|
||||||
|
};
|
||||||
|
var newUser = _database.Karma.Add(user).Entity;
|
||||||
|
await _database.SaveChangesAsync();
|
||||||
|
return newUser;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
111
Geekbot.net/Commands/User/Ranking/Rank.cs
Normal file
111
Geekbot.net/Commands/User/Ranking/Rank.cs
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Discord.Commands;
|
||||||
|
using Geekbot.net.Database;
|
||||||
|
using Geekbot.net.Lib;
|
||||||
|
using Geekbot.net.Lib.CommandPreconditions;
|
||||||
|
using Geekbot.net.Lib.Converters;
|
||||||
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
|
using Geekbot.net.Lib.Extensions;
|
||||||
|
using Geekbot.net.Lib.Highscores;
|
||||||
|
using Geekbot.net.Lib.Localization;
|
||||||
|
using Geekbot.net.Lib.UserRepository;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Commands.User.Ranking
|
||||||
|
{
|
||||||
|
public class Rank : GeekbotBase
|
||||||
|
{
|
||||||
|
private readonly IEmojiConverter _emojiConverter;
|
||||||
|
private readonly IHighscoreManager _highscoreManager;
|
||||||
|
private readonly IErrorHandler _errorHandler;
|
||||||
|
private readonly DatabaseContext _database;
|
||||||
|
|
||||||
|
public Rank(DatabaseContext database, IErrorHandler errorHandler, IEmojiConverter emojiConverter, IHighscoreManager highscoreManager)
|
||||||
|
{
|
||||||
|
_database = database;
|
||||||
|
_errorHandler = errorHandler;
|
||||||
|
_emojiConverter = emojiConverter;
|
||||||
|
_highscoreManager = highscoreManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("rank", RunMode = RunMode.Async)]
|
||||||
|
[Summary("get user top 10 in messages or karma")]
|
||||||
|
[DisableInDirectMessage]
|
||||||
|
public async Task RankCmd([Summary("type")] string typeUnformated = "messages", [Summary("amount")] int amount = 10)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
HighscoreTypes type;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
type = Enum.Parse<HighscoreTypes>(typeUnformated, true);
|
||||||
|
if (!Enum.IsDefined(typeof(HighscoreTypes), type)) throw new Exception();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
await ReplyAsync(Context.Translations.GetString("InvalidType"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var replyBuilder = new StringBuilder();
|
||||||
|
if (amount > 20)
|
||||||
|
{
|
||||||
|
await ReplyAsync(Context.Translations.GetString("LimitingTo20Warning"));
|
||||||
|
amount = 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
var guildId = Context.Guild.Id;
|
||||||
|
Dictionary<HighscoreUserDto, int> highscoreUsers;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
highscoreUsers = _highscoreManager.GetHighscoresWithUserData(type, guildId, amount);
|
||||||
|
}
|
||||||
|
catch (HighscoreListEmptyException)
|
||||||
|
{
|
||||||
|
await ReplyAsync(Context.Translations.GetString("NoTypeFoundForServer", type));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int guildMessages = 0;
|
||||||
|
if (type == HighscoreTypes.messages)
|
||||||
|
{
|
||||||
|
guildMessages = _database.Messages
|
||||||
|
.Where(e => e.GuildId.Equals(Context.Guild.Id.AsLong()))
|
||||||
|
.Select(e => e.MessageCount)
|
||||||
|
.Sum();
|
||||||
|
}
|
||||||
|
|
||||||
|
var failedToRetrieveUser = highscoreUsers.Any(e => string.IsNullOrEmpty(e.Key.Username));
|
||||||
|
|
||||||
|
if (failedToRetrieveUser) replyBuilder.AppendLine(Context.Translations.GetString("FailedToResolveAllUsernames"));
|
||||||
|
replyBuilder.AppendLine(Context.Translations.GetString("HighscoresFor", type.ToString().CapitalizeFirst(), Context.Guild.Name));
|
||||||
|
var highscorePlace = 1;
|
||||||
|
foreach (var user in highscoreUsers)
|
||||||
|
{
|
||||||
|
replyBuilder.Append(highscorePlace < 11
|
||||||
|
? $"{_emojiConverter.NumberToEmoji(highscorePlace)} "
|
||||||
|
: $"`{highscorePlace}.` ");
|
||||||
|
|
||||||
|
replyBuilder.Append(user.Key.Username != null
|
||||||
|
? $"**{user.Key.Username}#{user.Key.Discriminator}**"
|
||||||
|
: $"**{user.Key.Id}**");
|
||||||
|
|
||||||
|
replyBuilder.Append(type == HighscoreTypes.messages
|
||||||
|
? $" - {user.Value} {type} - {Math.Round((double) (100 * user.Value) / guildMessages, digits: 2)}%\n"
|
||||||
|
: $" - {user.Value} {type}\n");
|
||||||
|
|
||||||
|
highscorePlace++;
|
||||||
|
}
|
||||||
|
|
||||||
|
await ReplyAsync(replyBuilder.ToString());
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,25 +3,28 @@ using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Geekbot.Bot.CommandPreconditions;
|
using Geekbot.net.Database;
|
||||||
using Geekbot.Core;
|
using Geekbot.net.Lib;
|
||||||
using Geekbot.Core.Database;
|
using Geekbot.net.Lib.AlmostRedis;
|
||||||
using Geekbot.Core.ErrorHandling;
|
using Geekbot.net.Lib.CommandPreconditions;
|
||||||
using Geekbot.Core.Extensions;
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
using Geekbot.Core.GuildSettingsManager;
|
using Geekbot.net.Lib.Extensions;
|
||||||
using Geekbot.Core.Levels;
|
using Geekbot.net.Lib.Levels;
|
||||||
using Localization = Geekbot.Core.Localization;
|
|
||||||
|
|
||||||
namespace Geekbot.Bot.Commands.User
|
namespace Geekbot.net.Commands.User
|
||||||
{
|
{
|
||||||
public class Stats : GeekbotCommandBase
|
public class Stats : GeekbotBase
|
||||||
{
|
{
|
||||||
|
private readonly IErrorHandler _errorHandler;
|
||||||
private readonly ILevelCalc _levelCalc;
|
private readonly ILevelCalc _levelCalc;
|
||||||
|
private readonly IAlmostRedis _redis;
|
||||||
private readonly DatabaseContext _database;
|
private readonly DatabaseContext _database;
|
||||||
|
|
||||||
public Stats(DatabaseContext database, IErrorHandler errorHandler, ILevelCalc levelCalc, IGuildSettingsManager guildSettingsManager) : base(errorHandler, guildSettingsManager)
|
public Stats(IAlmostRedis redis, DatabaseContext database, IErrorHandler errorHandler, ILevelCalc levelCalc)
|
||||||
{
|
{
|
||||||
|
_redis = redis;
|
||||||
_database = database;
|
_database = database;
|
||||||
|
_errorHandler = errorHandler;
|
||||||
_levelCalc = levelCalc;
|
_levelCalc = levelCalc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,14 +52,12 @@ namespace Geekbot.Bot.Commands.User
|
||||||
|
|
||||||
var level = _levelCalc.GetLevel(messages);
|
var level = _levelCalc.GetLevel(messages);
|
||||||
|
|
||||||
var percent = Math.Round((double) (100 * messages) / guildMessages, 2);
|
var percent = Math.Round((double) (100 * messages) / guildMessages, digits: 2);
|
||||||
|
|
||||||
var cookies = _database.Cookies
|
var cookies = _database.Cookies
|
||||||
?.FirstOrDefault(e => e.GuildId.Equals(Context.Guild.Id.AsLong()) && e.UserId.Equals(userInfo.Id.AsLong()))
|
?.FirstOrDefault(e => e.GuildId.Equals(Context.Guild.Id.AsLong()) && e.UserId.Equals(userInfo.Id.AsLong()))
|
||||||
?.Cookies ?? 0;
|
?.Cookies ?? 0;
|
||||||
|
|
||||||
var quotes = _database.Quotes.Count(e => e.GuildId.Equals(Context.Guild.Id.AsLong()) && e.UserId.Equals(userInfo.Id.AsLong()));
|
|
||||||
|
|
||||||
var eb = new EmbedBuilder();
|
var eb = new EmbedBuilder();
|
||||||
eb.WithAuthor(new EmbedAuthorBuilder()
|
eb.WithAuthor(new EmbedAuthorBuilder()
|
||||||
.WithIconUrl(userInfo.GetAvatarUrl())
|
.WithIconUrl(userInfo.GetAvatarUrl())
|
||||||
|
@ -70,24 +71,23 @@ namespace Geekbot.Bot.Commands.User
|
||||||
e.GuildId.Equals(Context.Guild.Id.AsLong()) &&
|
e.GuildId.Equals(Context.Guild.Id.AsLong()) &&
|
||||||
e.UserId.Equals(userInfo.Id.AsLong()));
|
e.UserId.Equals(userInfo.Id.AsLong()));
|
||||||
|
|
||||||
eb.AddInlineField(Localization.Stats.OnDiscordSince,
|
eb.AddInlineField("Discordian Since",
|
||||||
$"{createdAt.Day}.{createdAt.Month}.{createdAt.Year} ({age} {Localization.Stats.Days})")
|
$"{createdAt.Day}.{createdAt.Month}.{createdAt.Year} ({age} days)")
|
||||||
.AddInlineField(Localization.Stats.JoinedServer,
|
.AddInlineField("Joined Server",
|
||||||
$"{joinedAt.Day}.{joinedAt.Month}.{joinedAt.Year} ({joinedDayAgo} {Localization.Stats.Days})")
|
$"{joinedAt.Day}.{joinedAt.Month}.{joinedAt.Year} ({joinedDayAgo} days)")
|
||||||
.AddInlineField(Localization.Stats.Karma, karma?.Karma ?? 0)
|
.AddInlineField("Karma", karma?.Karma ?? 0)
|
||||||
.AddInlineField(Localization.Stats.Level, level)
|
.AddInlineField("Level", level)
|
||||||
.AddInlineField(Localization.Stats.MessagesSent, messages)
|
.AddInlineField("Messages Sent", messages)
|
||||||
.AddInlineField(Localization.Stats.ServerTotal, $"{percent}%");
|
.AddInlineField("Server Total", $"{percent}%");
|
||||||
|
|
||||||
if (correctRolls != null) eb.AddInlineField(Localization.Stats.GuessedRolls, correctRolls.Rolls);
|
if (correctRolls != null) eb.AddInlineField("Guessed Rolls", correctRolls.Rolls);
|
||||||
if (cookies > 0) eb.AddInlineField(Localization.Stats.Cookies, cookies);
|
if (cookies > 0) eb.AddInlineField("Cookies", cookies);
|
||||||
if (quotes > 0) eb.AddInlineField(Localization.Stats.Quotes, quotes);
|
|
||||||
|
|
||||||
await ReplyAsync("", false, eb.Build());
|
await ReplyAsync("", false, eb.Build());
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
await ErrorHandler.HandleCommandException(e, Context);
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,12 +2,12 @@
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Geekbot.Core;
|
using Geekbot.net.Lib;
|
||||||
using Geekbot.Core.ErrorHandling;
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
|
|
||||||
namespace Geekbot.Bot.Commands.Utils
|
namespace Geekbot.net.Commands.Utils
|
||||||
{
|
{
|
||||||
public class AvatarGetter : TransactionModuleBase
|
public class AvatarGetter : GeekbotBase
|
||||||
{
|
{
|
||||||
private readonly IErrorHandler _errorHandler;
|
private readonly IErrorHandler _errorHandler;
|
||||||
|
|
||||||
|
@ -22,8 +22,8 @@ namespace Geekbot.Bot.Commands.Utils
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
user ??= Context.User;
|
if (user == null) user = Context.User;
|
||||||
var url = user.GetAvatarUrl(ImageFormat.Auto, 1024);
|
var url = user.GetAvatarUrl().Replace("128", "1024");
|
||||||
await ReplyAsync(url);
|
await ReplyAsync(url);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
68
Geekbot.net/Commands/Utils/Changelog/Changelog.cs
Normal file
68
Geekbot.net/Commands/Utils/Changelog/Changelog.cs
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Discord;
|
||||||
|
using Discord.Commands;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using Geekbot.net.Lib;
|
||||||
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Commands.Utils.Changelog
|
||||||
|
{
|
||||||
|
public class Changelog : GeekbotBase
|
||||||
|
{
|
||||||
|
private readonly DiscordSocketClient _client;
|
||||||
|
private readonly IErrorHandler _errorHandler;
|
||||||
|
|
||||||
|
public Changelog(IErrorHandler errorHandler, DiscordSocketClient client)
|
||||||
|
{
|
||||||
|
_errorHandler = errorHandler;
|
||||||
|
_client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("changelog", RunMode = RunMode.Async)]
|
||||||
|
[Summary("Show the latest 10 updates")]
|
||||||
|
public async Task GetChangelog()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var client = new HttpClient())
|
||||||
|
{
|
||||||
|
client.BaseAddress = new Uri("https://api.github.com");
|
||||||
|
client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent",
|
||||||
|
"http://developer.github.com/v3/#user-agent-required");
|
||||||
|
var response = await client.GetAsync("/repos/pizzaandcoffee/geekbot.net/commits");
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
var stringResponse = await response.Content.ReadAsStringAsync();
|
||||||
|
var commits = JsonConvert.DeserializeObject<List<CommitDto>>(stringResponse);
|
||||||
|
var eb = new EmbedBuilder();
|
||||||
|
eb.WithColor(new Color(143, 165, 102));
|
||||||
|
eb.WithAuthor(new EmbedAuthorBuilder
|
||||||
|
{
|
||||||
|
IconUrl = _client.CurrentUser.GetAvatarUrl(),
|
||||||
|
Name = "Latest Updates",
|
||||||
|
Url = "https://geekbot.pizzaandcoffee.rocks/updates"
|
||||||
|
});
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
foreach (var commit in commits.Take(10))
|
||||||
|
sb.AppendLine($"- {commit.Commit.Message} ({commit.Commit.Author.Date:yyyy-MM-dd})");
|
||||||
|
eb.Description = sb.ToString();
|
||||||
|
eb.WithFooter(new EmbedFooterBuilder
|
||||||
|
{
|
||||||
|
Text = $"List generated from github commits on {DateTime.Now:yyyy-MM-dd}"
|
||||||
|
});
|
||||||
|
await ReplyAsync("", false, eb.Build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
Geekbot.net/Commands/Utils/Changelog/CommitAuthorDto.cs
Normal file
11
Geekbot.net/Commands/Utils/Changelog/CommitAuthorDto.cs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Commands.Utils.Changelog
|
||||||
|
{
|
||||||
|
public class CommitAuthorDto
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Email { get; set; }
|
||||||
|
public DateTimeOffset Date { get; set; }
|
||||||
|
}
|
||||||
|
}
|
7
Geekbot.net/Commands/Utils/Changelog/CommitDto.cs
Normal file
7
Geekbot.net/Commands/Utils/Changelog/CommitDto.cs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
namespace Geekbot.net.Commands.Utils.Changelog
|
||||||
|
{
|
||||||
|
public class CommitDto
|
||||||
|
{
|
||||||
|
public CommitInfoDto Commit { get; set; }
|
||||||
|
}
|
||||||
|
}
|
8
Geekbot.net/Commands/Utils/Changelog/CommitInfoDto.cs
Normal file
8
Geekbot.net/Commands/Utils/Changelog/CommitInfoDto.cs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
namespace Geekbot.net.Commands.Utils.Changelog
|
||||||
|
{
|
||||||
|
public class CommitInfoDto
|
||||||
|
{
|
||||||
|
public CommitAuthorDto Author { get; set; }
|
||||||
|
public string Message { get; set; }
|
||||||
|
}
|
||||||
|
}
|
36
Geekbot.net/Commands/Utils/Choose.cs
Normal file
36
Geekbot.net/Commands/Utils/Choose.cs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Discord.Commands;
|
||||||
|
using Geekbot.net.Lib;
|
||||||
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
|
using Geekbot.net.Lib.Localization;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Commands.Utils
|
||||||
|
{
|
||||||
|
public class Choose : GeekbotBase
|
||||||
|
{
|
||||||
|
private readonly IErrorHandler _errorHandler;
|
||||||
|
|
||||||
|
public Choose(IErrorHandler errorHandler)
|
||||||
|
{
|
||||||
|
_errorHandler = errorHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("choose", RunMode = RunMode.Async)]
|
||||||
|
[Summary("Let the bot choose for you, seperate options with a semicolon.")]
|
||||||
|
public async Task Command([Remainder] [Summary("option1;option2")]
|
||||||
|
string choices)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var choicesArray = choices.Split(';');
|
||||||
|
var choice = new Random().Next(choicesArray.Length);
|
||||||
|
await ReplyAsync(Context.Translations.GetString("Choice", choicesArray[choice].Trim()));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
122
Geekbot.net/Commands/Utils/Dice/Dice.cs
Normal file
122
Geekbot.net/Commands/Utils/Dice/Dice.cs
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Discord.Commands;
|
||||||
|
using Geekbot.net.Lib;
|
||||||
|
using Geekbot.net.Lib.RandomNumberGenerator;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Commands.Utils.Dice
|
||||||
|
{
|
||||||
|
public class Dice : GeekbotBase
|
||||||
|
{
|
||||||
|
private readonly IRandomNumberGenerator _randomNumberGenerator;
|
||||||
|
|
||||||
|
public Dice(IRandomNumberGenerator randomNumberGenerator)
|
||||||
|
{
|
||||||
|
_randomNumberGenerator = randomNumberGenerator;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("dice", RunMode = RunMode.Async)]
|
||||||
|
[Summary("Roll a dice.")]
|
||||||
|
public async Task RollCommand([Remainder] [Summary("dice-type")] string diceType = "1d20")
|
||||||
|
{
|
||||||
|
var splitedDices = diceType.Split("+");
|
||||||
|
var dices = new List<DiceTypeDto>();
|
||||||
|
var mod = 0;
|
||||||
|
foreach (var i in splitedDices)
|
||||||
|
{
|
||||||
|
var dice = ToDice(i);
|
||||||
|
if (dice.Sides != 0 && dice.Times != 0)
|
||||||
|
{
|
||||||
|
dices.Add(dice);
|
||||||
|
}
|
||||||
|
else if (dice.Mod != 0)
|
||||||
|
{
|
||||||
|
if (mod != 0)
|
||||||
|
{
|
||||||
|
await ReplyAsync("You can only have one mod");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mod = dice.Mod;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dices.Any())
|
||||||
|
{
|
||||||
|
await ReplyAsync(
|
||||||
|
"That is not a valid dice, examples are: 1d20, 1d6, 2d6, 1d6+2, 1d6+2d8+1d20+6, etc...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (dices.Any(d => d.Times > 20))
|
||||||
|
{
|
||||||
|
await ReplyAsync("You can't throw more than 20 dices");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dices.Any(d => d.Sides > 144))
|
||||||
|
{
|
||||||
|
await ReplyAsync("A dice can't have more than 144 sides");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var rep = new StringBuilder();
|
||||||
|
rep.AppendLine($":game_die: {Context.User.Mention}");
|
||||||
|
rep.Append("**Result:** ");
|
||||||
|
var resultStrings = new List<string>();
|
||||||
|
var total = 0;
|
||||||
|
var extraText = "";
|
||||||
|
foreach (var dice in dices)
|
||||||
|
{
|
||||||
|
var results = new List<int>();
|
||||||
|
for (var i = 0; i < dice.Times; i++)
|
||||||
|
{
|
||||||
|
var roll = _randomNumberGenerator.Next(1, dice.Sides);
|
||||||
|
total += roll;
|
||||||
|
results.Add(roll);
|
||||||
|
if (roll == dice.Sides) extraText = "**Critical Hit!**";
|
||||||
|
if (roll == 1) extraText = "**Critical Fail!**";
|
||||||
|
}
|
||||||
|
|
||||||
|
resultStrings.Add($"{dice.DiceType} ({string.Join(",", results)})");
|
||||||
|
}
|
||||||
|
|
||||||
|
rep.Append(string.Join(" + ", resultStrings));
|
||||||
|
if (mod != 0)
|
||||||
|
{
|
||||||
|
rep.Append($" + {mod}");
|
||||||
|
total += mod;
|
||||||
|
}
|
||||||
|
|
||||||
|
rep.AppendLine();
|
||||||
|
rep.AppendLine($"**Total:** {total}");
|
||||||
|
if (extraText != "") rep.AppendLine(extraText);
|
||||||
|
await ReplyAsync(rep.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private DiceTypeDto ToDice(string dice)
|
||||||
|
{
|
||||||
|
var diceParts = dice.Split('d');
|
||||||
|
if (diceParts.Length == 2
|
||||||
|
&& int.TryParse(diceParts[0], out var times)
|
||||||
|
&& int.TryParse(diceParts[1], out var max))
|
||||||
|
return new DiceTypeDto
|
||||||
|
{
|
||||||
|
DiceType = dice,
|
||||||
|
Times = times,
|
||||||
|
Sides = max
|
||||||
|
};
|
||||||
|
if (dice.Length == 1
|
||||||
|
&& int.TryParse(diceParts[0], out var mod))
|
||||||
|
return new DiceTypeDto
|
||||||
|
{
|
||||||
|
Mod = mod
|
||||||
|
};
|
||||||
|
return new DiceTypeDto();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
Geekbot.net/Commands/Utils/Dice/DiceTypeDto.cs
Normal file
10
Geekbot.net/Commands/Utils/Dice/DiceTypeDto.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
namespace Geekbot.net.Commands.Utils.Dice
|
||||||
|
{
|
||||||
|
internal class DiceTypeDto
|
||||||
|
{
|
||||||
|
public string DiceType { get; set; }
|
||||||
|
public int Times { get; set; }
|
||||||
|
public int Sides { get; set; }
|
||||||
|
public int Mod { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,17 +1,21 @@
|
||||||
using Discord.Commands;
|
using System;
|
||||||
using Geekbot.Core;
|
using System.Threading.Tasks;
|
||||||
using Geekbot.Core.Converters;
|
using Discord.Commands;
|
||||||
using Geekbot.Core.ErrorHandling;
|
using Geekbot.net.Lib;
|
||||||
|
using Geekbot.net.Lib.Converters;
|
||||||
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
|
|
||||||
namespace Geekbot.Bot.Commands.Utils
|
namespace Geekbot.net.Commands.Utils
|
||||||
{
|
{
|
||||||
public class Emojify : TransactionModuleBase
|
public class Emojify : GeekbotBase
|
||||||
{
|
{
|
||||||
|
private readonly IEmojiConverter _emojiConverter;
|
||||||
private readonly IErrorHandler _errorHandler;
|
private readonly IErrorHandler _errorHandler;
|
||||||
|
|
||||||
public Emojify(IErrorHandler errorHandler)
|
public Emojify(IErrorHandler errorHandler, IEmojiConverter emojiConverter)
|
||||||
{
|
{
|
||||||
_errorHandler = errorHandler;
|
_errorHandler = errorHandler;
|
||||||
|
_emojiConverter = emojiConverter;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Command("emojify", RunMode = RunMode.Async)]
|
[Command("emojify", RunMode = RunMode.Async)]
|
||||||
|
@ -20,7 +24,7 @@ namespace Geekbot.Bot.Commands.Utils
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var emojis = EmojiConverter.TextToEmoji(text);
|
var emojis = _emojiConverter.TextToEmoji(text);
|
||||||
if (emojis.Length > 1999)
|
if (emojis.Length > 1999)
|
||||||
{
|
{
|
||||||
await ReplyAsync("I can't take that much at once!");
|
await ReplyAsync("I can't take that much at once!");
|
||||||
|
@ -29,14 +33,6 @@ namespace Geekbot.Bot.Commands.Utils
|
||||||
|
|
||||||
await ReplyAsync($"{Context.User.Username}#{Context.User.Discriminator} said:");
|
await ReplyAsync($"{Context.User.Username}#{Context.User.Discriminator} said:");
|
||||||
await ReplyAsync(emojis);
|
await ReplyAsync(emojis);
|
||||||
try
|
|
||||||
{
|
|
||||||
await Context.Message.DeleteAsync();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// bot may not have enough permission, doesn't matter if it fails
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
|
@ -3,12 +3,12 @@ using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Geekbot.Core;
|
using Geekbot.net.Lib;
|
||||||
using Geekbot.Core.ErrorHandling;
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
|
|
||||||
namespace Geekbot.Bot.Commands.Utils
|
namespace Geekbot.net.Commands.Utils
|
||||||
{
|
{
|
||||||
public class Help : TransactionModuleBase
|
public class Help : GeekbotBase
|
||||||
{
|
{
|
||||||
private readonly IErrorHandler _errorHandler;
|
private readonly IErrorHandler _errorHandler;
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ namespace Geekbot.Bot.Commands.Utils
|
||||||
|
|
||||||
sb.AppendLine("For a list of all commands, please visit the following page");
|
sb.AppendLine("For a list of all commands, please visit the following page");
|
||||||
sb.AppendLine("https://geekbot.pizzaandcoffee.rocks/commands");
|
sb.AppendLine("https://geekbot.pizzaandcoffee.rocks/commands");
|
||||||
var dm = await Context.User.CreateDMChannelAsync(RequestOptions.Default);
|
var dm = await Context.User.GetOrCreateDMChannelAsync();
|
||||||
await dm.SendMessageAsync(sb.ToString());
|
await dm.SendMessageAsync(sb.ToString());
|
||||||
await Context.Message.AddReactionAsync(new Emoji("✅"));
|
await Context.Message.AddReactionAsync(new Emoji("✅"));
|
||||||
}
|
}
|
|
@ -5,13 +5,13 @@ using System.Threading.Tasks;
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using Geekbot.Core;
|
using Geekbot.net.Lib;
|
||||||
using Geekbot.Core.ErrorHandling;
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
using Geekbot.Core.Extensions;
|
using Geekbot.net.Lib.Extensions;
|
||||||
|
|
||||||
namespace Geekbot.Bot.Commands.Utils
|
namespace Geekbot.net.Commands.Utils
|
||||||
{
|
{
|
||||||
public class Info : TransactionModuleBase
|
public class Info : GeekbotBase
|
||||||
{
|
{
|
||||||
private readonly DiscordSocketClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly CommandService _commands;
|
private readonly CommandService _commands;
|
|
@ -1,10 +1,10 @@
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Geekbot.Core;
|
using Geekbot.net.Lib;
|
||||||
|
|
||||||
namespace Geekbot.Bot.Commands.Utils
|
namespace Geekbot.net.Commands.Utils
|
||||||
{
|
{
|
||||||
public class Ping : TransactionModuleBase
|
public class Ping : GeekbotBase
|
||||||
{
|
{
|
||||||
[Command("👀", RunMode = RunMode.Async)]
|
[Command("👀", RunMode = RunMode.Async)]
|
||||||
[Summary("Look at the bot.")]
|
[Summary("Look at the bot.")]
|
249
Geekbot.net/Commands/Utils/Quote/Quote.cs
Normal file
249
Geekbot.net/Commands/Utils/Quote/Quote.cs
Normal file
|
@ -0,0 +1,249 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Discord;
|
||||||
|
using Discord.Commands;
|
||||||
|
using Geekbot.net.Database;
|
||||||
|
using Geekbot.net.Database.Models;
|
||||||
|
using Geekbot.net.Lib;
|
||||||
|
using Geekbot.net.Lib.CommandPreconditions;
|
||||||
|
using Geekbot.net.Lib.ErrorHandling;
|
||||||
|
using Geekbot.net.Lib.Extensions;
|
||||||
|
using Geekbot.net.Lib.Localization;
|
||||||
|
using Geekbot.net.Lib.Polyfills;
|
||||||
|
using Geekbot.net.Lib.RandomNumberGenerator;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Commands.Utils.Quote
|
||||||
|
{
|
||||||
|
[Group("quote")]
|
||||||
|
[DisableInDirectMessage]
|
||||||
|
public class Quote : GeekbotBase
|
||||||
|
{
|
||||||
|
private readonly IErrorHandler _errorHandler;
|
||||||
|
private readonly DatabaseContext _database;
|
||||||
|
private readonly IRandomNumberGenerator _randomNumberGenerator;
|
||||||
|
|
||||||
|
public Quote(IErrorHandler errorHandler, DatabaseContext database, IRandomNumberGenerator randomNumberGenerator)
|
||||||
|
{
|
||||||
|
_errorHandler = errorHandler;
|
||||||
|
_database = database;
|
||||||
|
_randomNumberGenerator = randomNumberGenerator;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command]
|
||||||
|
[Summary("Return a random quoute from the database")]
|
||||||
|
public async Task GetRandomQuote()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var s = _database.Quotes.Where(e => e.GuildId.Equals(Context.Guild.Id.AsLong())).ToList();
|
||||||
|
|
||||||
|
if (!s.Any())
|
||||||
|
{
|
||||||
|
await ReplyAsync(Context.Translations.GetString("NoQuotesFound"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var random = _randomNumberGenerator.Next(0, s.Count());
|
||||||
|
var quote = s[random];
|
||||||
|
|
||||||
|
var embed = QuoteBuilder(quote);
|
||||||
|
await ReplyAsync("", false, embed.Build());
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context, "Whoops, seems like the quote was to edgy to return");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("save")]
|
||||||
|
[Summary("Save a quote from the last sent message by @user")]
|
||||||
|
public async Task SaveQuote([Summary("@someone")] IUser user)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (user.Id == Context.Message.Author.Id)
|
||||||
|
{
|
||||||
|
await ReplyAsync(Context.Translations.GetString("CannotSaveOwnQuotes"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user.IsBot)
|
||||||
|
{
|
||||||
|
await ReplyAsync(Context.Translations.GetString("CannotQuoteBots"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var lastMessage = await GetLastMessageByUser(user);
|
||||||
|
if (lastMessage == null) return;
|
||||||
|
|
||||||
|
var quote = CreateQuoteObject(lastMessage);
|
||||||
|
_database.Quotes.Add(quote);
|
||||||
|
await _database.SaveChangesAsync();
|
||||||
|
|
||||||
|
var embed = QuoteBuilder(quote);
|
||||||
|
await ReplyAsync(Context.Translations.GetString("QuoteAdded"), false, embed.Build());
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context,
|
||||||
|
"I counldn't find a quote from that user :disappointed:");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("save")]
|
||||||
|
[Summary("Save a quote from a message id")]
|
||||||
|
public async Task SaveQuote([Summary("message-ID")] ulong messageId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var message = await Context.Channel.GetMessageAsync(messageId);
|
||||||
|
if (message.Author.Id == Context.Message.Author.Id)
|
||||||
|
{
|
||||||
|
await ReplyAsync(Context.Translations.GetString("CannotSaveOwnQuotes"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message.Author.IsBot)
|
||||||
|
{
|
||||||
|
await ReplyAsync(Context.Translations.GetString("CannotQuoteBots"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var quote = CreateQuoteObject(message);
|
||||||
|
_database.Quotes.Add(quote);
|
||||||
|
await _database.SaveChangesAsync();
|
||||||
|
|
||||||
|
var embed = QuoteBuilder(quote);
|
||||||
|
await ReplyAsync(Context.Translations.GetString("QuoteAdded"), false, embed.Build());
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context,
|
||||||
|
"I couldn't find a message with that id :disappointed:");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("make")]
|
||||||
|
[Summary("Create a quote from the last sent message by @user")]
|
||||||
|
public async Task ReturnSpecifiedQuote([Summary("@someone")] IUser user)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var lastMessage = await GetLastMessageByUser(user);
|
||||||
|
if (lastMessage == null) return;
|
||||||
|
var quote = CreateQuoteObject(lastMessage);
|
||||||
|
var embed = QuoteBuilder(quote);
|
||||||
|
await ReplyAsync("", false, embed.Build());
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context,
|
||||||
|
"I counldn't find a quote from that user :disappointed:");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("make")]
|
||||||
|
[Summary("Create a quote from a message id")]
|
||||||
|
public async Task ReturnSpecifiedQuote([Summary("message-ID")] ulong messageId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var message = await Context.Channel.GetMessageAsync(messageId);
|
||||||
|
var quote = CreateQuoteObject(message);
|
||||||
|
var embed = QuoteBuilder(quote);
|
||||||
|
await ReplyAsync("", false, embed.Build());
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context,
|
||||||
|
"I couldn't find a message with that id :disappointed:");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("remove")]
|
||||||
|
[RequireUserPermission(GuildPermission.KickMembers)]
|
||||||
|
[RequireUserPermission(GuildPermission.ManageMessages)]
|
||||||
|
[RequireUserPermission(GuildPermission.ManageRoles)]
|
||||||
|
[Summary("Remove a quote (required mod permissions)")]
|
||||||
|
public async Task RemoveQuote([Summary("quote-ID")] int id)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var quote = _database.Quotes.Where(e => e.GuildId == Context.Guild.Id.AsLong() && e.InternalId == id)?.FirstOrDefault();
|
||||||
|
if (quote != null)
|
||||||
|
{
|
||||||
|
_database.Quotes.Remove(quote);
|
||||||
|
await _database.SaveChangesAsync();
|
||||||
|
var embed = QuoteBuilder(quote);
|
||||||
|
await ReplyAsync(Context.Translations.GetString("Removed", id), false, embed.Build());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await ReplyAsync(Context.Translations.GetString("NotFoundWithId"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _errorHandler.HandleCommandException(e, Context, "I couldn't find a quote with that id :disappointed:");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<IMessage> GetLastMessageByUser(IUser user)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var list = Context.Channel.GetMessagesAsync().Flatten();
|
||||||
|
return await list.FirstOrDefault(msg =>
|
||||||
|
msg.Author.Id == user.Id &&
|
||||||
|
msg.Embeds.Count == 0 &&
|
||||||
|
msg.Id != Context.Message.Id &&
|
||||||
|
!msg.Content.ToLower().StartsWith("!"));
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
await ReplyAsync($"No quoteable message have been sent by {user.Username} in this channel");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private EmbedBuilder QuoteBuilder(QuoteModel quote)
|
||||||
|
{
|
||||||
|
var user = Context.Client.GetUserAsync(quote.UserId.AsUlong()).Result ?? new UserPolyfillDto { Username = "Unknown User" };
|
||||||
|
var eb = new EmbedBuilder();
|
||||||
|
eb.WithColor(new Color(143, 167, 232));
|
||||||
|
eb.Title = $"#{quote.InternalId} | {user.Username} @ {quote.Time.Day}.{quote.Time.Month}.{quote.Time.Year}";
|
||||||
|
eb.Description = quote.Quote;
|
||||||
|
eb.ThumbnailUrl = user.GetAvatarUrl();
|
||||||
|
if (quote.Image != null) eb.ImageUrl = quote.Image;
|
||||||
|
return eb;
|
||||||
|
}
|
||||||
|
|
||||||
|
private QuoteModel CreateQuoteObject(IMessage message)
|
||||||
|
{
|
||||||
|
string image;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
image = message.Attachments.First().Url;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
image = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var last = _database.Quotes.Where(e => e.GuildId.Equals(Context.Guild.Id.AsLong()))
|
||||||
|
.OrderByDescending(e => e.InternalId).FirstOrDefault();
|
||||||
|
int internalId = 1;
|
||||||
|
if (last != null) internalId = last.InternalId + 1;
|
||||||
|
return new QuoteModel()
|
||||||
|
{
|
||||||
|
InternalId = internalId,
|
||||||
|
GuildId = Context.Guild.Id.AsLong(),
|
||||||
|
UserId = message.Author.Id.AsLong(),
|
||||||
|
Time = message.Timestamp.DateTime,
|
||||||
|
Quote = message.Content,
|
||||||
|
Image = image
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Geekbot.Bot.Commands.Utils.Quote
|
namespace Geekbot.net.Commands.Utils.Quote
|
||||||
{
|
{
|
||||||
internal class QuoteObjectDto
|
internal class QuoteObjectDto
|
||||||
{
|
{
|
|
@ -1,22 +1,22 @@
|
||||||
using Geekbot.Core.Database.Models;
|
using Geekbot.net.Database.Models;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace Geekbot.Core.Database
|
namespace Geekbot.net.Database
|
||||||
{
|
{
|
||||||
public class DatabaseContext : DbContext
|
public class DatabaseContext : DbContext
|
||||||
{
|
{
|
||||||
public DbSet<QuoteModel> Quotes { get; set; }
|
public DbSet<QuoteModel> Quotes { get; set; }
|
||||||
public DbSet<UserModel> Users { get; set; }
|
public DbSet<UserModel> Users { get; set; }
|
||||||
|
public DbSet<GuildsModel> Guilds { get; set; }
|
||||||
public DbSet<GuildSettingsModel> GuildSettings { get; set; }
|
public DbSet<GuildSettingsModel> GuildSettings { get; set; }
|
||||||
public DbSet<KarmaModel> Karma { get; set; }
|
public DbSet<KarmaModel> Karma { get; set; }
|
||||||
public DbSet<ShipsModel> Ships { get; set; }
|
public DbSet<ShipsModel> Ships { get; set; }
|
||||||
public DbSet<RollsModel> Rolls { get; set; }
|
public DbSet<RollsModel> Rolls { get; set; }
|
||||||
public DbSet<MessageSeasonsModel> MessagesSeasons { get; set; }
|
|
||||||
public DbSet<MessagesModel> Messages { get; set; }
|
public DbSet<MessagesModel> Messages { get; set; }
|
||||||
public DbSet<SlapsModel> Slaps { get; set; }
|
public DbSet<SlapsModel> Slaps { get; set; }
|
||||||
public DbSet<GlobalsModel> Globals { get; set; }
|
public DbSet<GlobalsModel> Globals { get; set; }
|
||||||
public DbSet<RoleSelfServiceModel> RoleSelfService { get; set; }
|
public DbSet<RoleSelfServiceModel> RoleSelfService { get; set; }
|
||||||
|
public DbSet<PollModel> Polls { get; set; }
|
||||||
public DbSet<CookiesModel> Cookies { get; set; }
|
public DbSet<CookiesModel> Cookies { get; set; }
|
||||||
public DbSet<ReactionListenerModel> ReactionListeners { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,9 +1,11 @@
|
||||||
using System;
|
using System;
|
||||||
using Geekbot.Core.Database.LoggingAdapter;
|
using Geekbot.net.Database.LoggingAdapter;
|
||||||
using Geekbot.Core.Logger;
|
using Geekbot.net.Lib;
|
||||||
|
using Geekbot.net.Lib.Logger;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Npgsql.Logging;
|
using Npgsql.Logging;
|
||||||
|
|
||||||
namespace Geekbot.Core.Database
|
namespace Geekbot.net.Database
|
||||||
{
|
{
|
||||||
public class DatabaseInitializer
|
public class DatabaseInitializer
|
||||||
{
|
{
|
||||||
|
@ -34,10 +36,7 @@ namespace Geekbot.Core.Database
|
||||||
Port = _runParameters.DbPort,
|
Port = _runParameters.DbPort,
|
||||||
Database = _runParameters.DbDatabase,
|
Database = _runParameters.DbDatabase,
|
||||||
Username = _runParameters.DbUser,
|
Username = _runParameters.DbUser,
|
||||||
Password = _runParameters.DbPassword,
|
Password = _runParameters.DbPassword
|
||||||
RequireSsl = _runParameters.DbSsl,
|
|
||||||
TrustServerCertificate = _runParameters.DbTrustCert,
|
|
||||||
RedshiftCompatibility = _runParameters.DbRedshiftCompatibility
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace Geekbot.Core.Database
|
namespace Geekbot.net.Database
|
||||||
{
|
{
|
||||||
public class InMemoryDatabase : DatabaseContext
|
public class InMemoryDatabase : DatabaseContext
|
||||||
{
|
{
|
|
@ -1,9 +1,10 @@
|
||||||
using System;
|
using System;
|
||||||
using Geekbot.Core.Logger;
|
using Geekbot.net.Lib;
|
||||||
|
using Geekbot.net.Lib.Logger;
|
||||||
using Npgsql.Logging;
|
using Npgsql.Logging;
|
||||||
using LogLevel = NLog.LogLevel;
|
using LogLevel = NLog.LogLevel;
|
||||||
|
|
||||||
namespace Geekbot.Core.Database.LoggingAdapter
|
namespace Geekbot.net.Database.LoggingAdapter
|
||||||
{
|
{
|
||||||
public class NpgsqlLoggingAdapter : NpgsqlLogger
|
public class NpgsqlLoggingAdapter : NpgsqlLogger
|
||||||
{
|
{
|
||||||
|
@ -53,16 +54,23 @@ namespace Geekbot.Core.Database.LoggingAdapter
|
||||||
|
|
||||||
private static LogLevel ToGeekbotLogLevel(NpgsqlLogLevel level)
|
private static LogLevel ToGeekbotLogLevel(NpgsqlLogLevel level)
|
||||||
{
|
{
|
||||||
return level switch
|
switch (level)
|
||||||
{
|
{
|
||||||
NpgsqlLogLevel.Trace => LogLevel.Trace,
|
case NpgsqlLogLevel.Trace:
|
||||||
NpgsqlLogLevel.Debug => LogLevel.Debug,
|
return LogLevel.Trace;
|
||||||
NpgsqlLogLevel.Info => LogLevel.Info,
|
case NpgsqlLogLevel.Debug:
|
||||||
NpgsqlLogLevel.Warn => LogLevel.Warn,
|
return LogLevel.Debug;
|
||||||
NpgsqlLogLevel.Error => LogLevel.Error,
|
case NpgsqlLogLevel.Info:
|
||||||
NpgsqlLogLevel.Fatal => LogLevel.Fatal,
|
return LogLevel.Info;
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(level))
|
case NpgsqlLogLevel.Warn:
|
||||||
};
|
return LogLevel.Warn;
|
||||||
|
case NpgsqlLogLevel.Error:
|
||||||
|
return LogLevel.Error;
|
||||||
|
case NpgsqlLogLevel.Fatal:
|
||||||
|
return LogLevel.Fatal;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(level));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,8 @@
|
||||||
using Geekbot.Core.Logger;
|
using Geekbot.net.Lib;
|
||||||
|
using Geekbot.net.Lib.Logger;
|
||||||
using Npgsql.Logging;
|
using Npgsql.Logging;
|
||||||
|
|
||||||
namespace Geekbot.Core.Database.LoggingAdapter
|
namespace Geekbot.net.Database.LoggingAdapter
|
||||||
{
|
{
|
||||||
public class NpgsqlLoggingProviderAdapter : INpgsqlLoggingProvider
|
public class NpgsqlLoggingProviderAdapter : INpgsqlLoggingProvider
|
||||||
{
|
{
|
|
@ -1,7 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace Geekbot.Core.Database.Models
|
namespace Geekbot.net.Database.Models
|
||||||
{
|
{
|
||||||
public class CookiesModel
|
public class CookiesModel
|
||||||
{
|
{
|
|
@ -1,6 +1,6 @@
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace Geekbot.Core.Database.Models
|
namespace Geekbot.net.Database.Models
|
||||||
{
|
{
|
||||||
public class GlobalsModel
|
public class GlobalsModel
|
||||||
{
|
{
|
|
@ -1,6 +1,6 @@
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace Geekbot.Core.Database.Models
|
namespace Geekbot.net.Database.Models
|
||||||
{
|
{
|
||||||
public class GuildSettingsModel
|
public class GuildSettingsModel
|
||||||
{
|
{
|
24
Geekbot.net/Database/Models/GuildsModel.cs
Normal file
24
Geekbot.net/Database/Models/GuildsModel.cs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Database.Models
|
||||||
|
{
|
||||||
|
public class GuildsModel
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public long GuildId { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public long Owner { get; set; }
|
||||||
|
|
||||||
|
public string IconUrl { get; set; }
|
||||||
|
|
||||||
|
public DateTimeOffset CreatedAt { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace Geekbot.Core.Database.Models
|
namespace Geekbot.net.Database.Models
|
||||||
{
|
{
|
||||||
public class KarmaModel
|
public class KarmaModel
|
||||||
{
|
{
|
|
@ -1,6 +1,6 @@
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace Geekbot.Core.Database.Models
|
namespace Geekbot.net.Database.Models
|
||||||
{
|
{
|
||||||
public class MessagesModel
|
public class MessagesModel
|
||||||
{
|
{
|
27
Geekbot.net/Database/Models/PollModel.cs
Normal file
27
Geekbot.net/Database/Models/PollModel.cs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Database.Models
|
||||||
|
{
|
||||||
|
public class PollModel
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public long GuildId { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public long ChannelId { get; set; }
|
||||||
|
|
||||||
|
public string Question { get; set; }
|
||||||
|
|
||||||
|
public long Creator { get; set; }
|
||||||
|
|
||||||
|
public long MessageId { get; set; }
|
||||||
|
|
||||||
|
public List<PollQuestionModel> Options { get; set; }
|
||||||
|
|
||||||
|
public bool IsFinshed { get; set; }
|
||||||
|
}
|
||||||
|
}
|
16
Geekbot.net/Database/Models/PollQuestionModel.cs
Normal file
16
Geekbot.net/Database/Models/PollQuestionModel.cs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Database.Models
|
||||||
|
{
|
||||||
|
public class PollQuestionModel
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public int OptionId { get; set; }
|
||||||
|
|
||||||
|
public string OptionText { get; set; }
|
||||||
|
|
||||||
|
public int Votes { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace Geekbot.Core.Database.Models
|
namespace Geekbot.net.Database.Models
|
||||||
{
|
{
|
||||||
public class QuoteModel
|
public class QuoteModel
|
||||||
{
|
{
|
|
@ -1,6 +1,6 @@
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace Geekbot.Core.Database.Models
|
namespace Geekbot.net.Database.Models
|
||||||
{
|
{
|
||||||
public class RoleSelfServiceModel
|
public class RoleSelfServiceModel
|
||||||
{
|
{
|
|
@ -1,6 +1,6 @@
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace Geekbot.Core.Database.Models
|
namespace Geekbot.net.Database.Models
|
||||||
{
|
{
|
||||||
public class RollsModel
|
public class RollsModel
|
||||||
{
|
{
|
|
@ -1,6 +1,6 @@
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace Geekbot.Core.Database.Models
|
namespace Geekbot.net.Database.Models
|
||||||
{
|
{
|
||||||
public class ShipsModel
|
public class ShipsModel
|
||||||
{
|
{
|
|
@ -1,6 +1,6 @@
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace Geekbot.Core.Database.Models
|
namespace Geekbot.net.Database.Models
|
||||||
{
|
{
|
||||||
public class SlapsModel
|
public class SlapsModel
|
||||||
{
|
{
|
|
@ -1,7 +1,8 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace Geekbot.Core.Database.Models
|
namespace Geekbot.net.Database.Models
|
||||||
{
|
{
|
||||||
public class UserModel
|
public class UserModel
|
||||||
{
|
{
|
||||||
|
@ -23,5 +24,7 @@ namespace Geekbot.Core.Database.Models
|
||||||
public bool IsBot { get; set; }
|
public bool IsBot { get; set; }
|
||||||
|
|
||||||
public DateTimeOffset Joined { get; set; }
|
public DateTimeOffset Joined { get; set; }
|
||||||
|
|
||||||
|
public List<UserUsedNamesModel> UsedNames { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
15
Geekbot.net/Database/Models/UserUsedNamesModel.cs
Normal file
15
Geekbot.net/Database/Models/UserUsedNamesModel.cs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Database.Models
|
||||||
|
{
|
||||||
|
public class UserUsedNamesModel
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public DateTimeOffset FirstSeen { get; set; }
|
||||||
|
}
|
||||||
|
}
|
16
Geekbot.net/Database/SqlConnectionString.cs
Normal file
16
Geekbot.net/Database/SqlConnectionString.cs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
namespace Geekbot.net.Database
|
||||||
|
{
|
||||||
|
public class SqlConnectionString
|
||||||
|
{
|
||||||
|
public string Host { get; set; }
|
||||||
|
public string Port { get; set; }
|
||||||
|
public string Database { get; set; }
|
||||||
|
public string Username { get; set; }
|
||||||
|
public string Password { get; set; }
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"Server={Host};Port={Port};Database={Database};Uid={Username};Pwd={Password};";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace Geekbot.Core.Database
|
namespace Geekbot.net.Database
|
||||||
{
|
{
|
||||||
public class SqlDatabase : DatabaseContext
|
public class SqlDatabase : DatabaseContext
|
||||||
{
|
{
|
104
Geekbot.net/Geekbot.net.csproj
Executable file
104
Geekbot.net/Geekbot.net.csproj
Executable file
|
@ -0,0 +1,104 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||||
|
<RuntimeIdentifiers>win-x64;linux-x64</RuntimeIdentifiers>
|
||||||
|
<ApplicationIcon>derp.ico</ApplicationIcon>
|
||||||
|
<Version>4.1.0</Version>
|
||||||
|
<VersionSuffix>$(VersionSuffix)</VersionSuffix>
|
||||||
|
<Version Condition=" '$(VersionSuffix)' != '' ">$(Version)-$(VersionSuffix)</Version>
|
||||||
|
<Version Condition=" '$(VersionSuffix)' == '' ">$(Version)-DEV</Version>
|
||||||
|
<Company>Pizza and Coffee Studios</Company>
|
||||||
|
<Authors>Pizza and Coffee Studios</Authors>
|
||||||
|
<Description>A Discord bot</Description>
|
||||||
|
<RepositoryUrl>https://github.com/pizzaandcoffee/Geekbot.net</RepositoryUrl>
|
||||||
|
<NoWarn>NU1701</NoWarn>
|
||||||
|
<RepositoryType>git</RepositoryType>
|
||||||
|
<PackageProjectUrl>https://geekbot.pizzaandcoffee.rocks</PackageProjectUrl>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="CommandLineParser" Version="2.4.3" />
|
||||||
|
<PackageReference Include="Discord.Net">
|
||||||
|
<Version>2.1.0</Version>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Google.Apis.YouTube.v3" Version="1.38.0.1488" />
|
||||||
|
<PackageReference Include="HtmlAgilityPack" Version="1.9.1" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.DataProtection.Redis" Version="0.4.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.2.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.Cors" Version="2.2.0" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.2.2" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.2.2" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="2.2.2" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="2.2.2" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.2.2" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.2.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.2.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Options" Version="2.2.0" />
|
||||||
|
<PackageReference Include="MtgApiManager.Lib" Version="1.2.1" />
|
||||||
|
<PackageReference Include="MyAnimeListSharp" Version="1.3.4" />
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
|
||||||
|
<PackageReference Include="NLog" Version="4.5.11" />
|
||||||
|
<PackageReference Include="NLog.Config" Version="4.5.11" />
|
||||||
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="2.2.0" />
|
||||||
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.Design" Version="2.0.0-preview1" />
|
||||||
|
<PackageReference Include="PokeApi.NET" Version="1.1.1" />
|
||||||
|
<PackageReference Include="SharpRaven" Version="2.4.0" />
|
||||||
|
<PackageReference Include="SumoLogic.Logging.NLog" Version="1.0.1.1" />
|
||||||
|
<PackageReference Include="System.Net.Http" Version="4.3.4" />
|
||||||
|
<PackageReference Include="System.Runtime.Serialization.Formatters" Version="4.3.0" />
|
||||||
|
<PackageReference Include="System.Runtime.Serialization.Json">
|
||||||
|
<Version>4.3.0</Version>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="System.Runtime.Serialization.Primitives">
|
||||||
|
<Version>4.3.0</Version>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Utf8Json" Version="1.3.7" />
|
||||||
|
<PackageReference Include="YamlDotNet" Version="6.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="Storage\checkEmPics">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Storage\croissant">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Storage\fortunes">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Storage\pandas">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Storage\pumpkin">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Storage\squirrel">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Storage\turtles">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Storage\pinguins">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Storage\foxes">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Lib\Converters\MtgManaEmojis.json">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Storage\dab">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Lib\Localization\Translations.yml">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\WikipediaApi\WikipediaApi.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
268
Geekbot.net/Handlers.cs
Normal file
268
Geekbot.net/Handlers.cs
Normal file
|
@ -0,0 +1,268 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Discord;
|
||||||
|
using Discord.Commands;
|
||||||
|
using Discord.Rest;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using Geekbot.net.Database;
|
||||||
|
using Geekbot.net.Database.Models;
|
||||||
|
using Geekbot.net.Lib.AlmostRedis;
|
||||||
|
using Geekbot.net.Lib.Context;
|
||||||
|
using Geekbot.net.Lib.Extensions;
|
||||||
|
using Geekbot.net.Lib.Localization;
|
||||||
|
using Geekbot.net.Lib.Logger;
|
||||||
|
using Geekbot.net.Lib.ReactionListener;
|
||||||
|
using Geekbot.net.Lib.UserRepository;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Geekbot.net
|
||||||
|
{
|
||||||
|
public class Handlers
|
||||||
|
{
|
||||||
|
private readonly DatabaseContext _database;
|
||||||
|
private readonly IDiscordClient _client;
|
||||||
|
private readonly IGeekbotLogger _logger;
|
||||||
|
private readonly IAlmostRedis _redis;
|
||||||
|
private readonly IServiceProvider _servicesProvider;
|
||||||
|
private readonly CommandService _commands;
|
||||||
|
private readonly IUserRepository _userRepository;
|
||||||
|
private readonly IReactionListener _reactionListener;
|
||||||
|
private readonly ITranslationHandler _translationHandler;
|
||||||
|
private readonly DatabaseContext _messageCounterDatabaseContext;
|
||||||
|
|
||||||
|
public Handlers(DatabaseInitializer databaseInitializer, IDiscordClient client, IGeekbotLogger logger, IAlmostRedis redis,
|
||||||
|
IServiceProvider servicesProvider, CommandService commands, IUserRepository userRepository,
|
||||||
|
IReactionListener reactionListener, ITranslationHandler translationHandler)
|
||||||
|
{
|
||||||
|
_database = databaseInitializer.Initialize();
|
||||||
|
_messageCounterDatabaseContext = databaseInitializer.Initialize();
|
||||||
|
_client = client;
|
||||||
|
_logger = logger;
|
||||||
|
_redis = redis;
|
||||||
|
_servicesProvider = servicesProvider;
|
||||||
|
_commands = commands;
|
||||||
|
_userRepository = userRepository;
|
||||||
|
_reactionListener = reactionListener;
|
||||||
|
_translationHandler = translationHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Incoming Messages
|
||||||
|
//
|
||||||
|
|
||||||
|
public Task RunCommand(SocketMessage messageParam)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!(messageParam is SocketUserMessage message)) return Task.CompletedTask;
|
||||||
|
if (message.Author.IsBot) return Task.CompletedTask;
|
||||||
|
var argPos = 0;
|
||||||
|
|
||||||
|
var lowCaseMsg = message.ToString().ToLower();
|
||||||
|
if (lowCaseMsg.StartsWith("hui"))
|
||||||
|
{
|
||||||
|
var hasPing = _database.GuildSettings.FirstOrDefault(guild => guild.GuildId.Equals(((SocketGuildChannel) message.Channel).Guild.Id.AsLong()))?.Hui ?? false;
|
||||||
|
if (hasPing)
|
||||||
|
{
|
||||||
|
message.Channel.SendMessageAsync("hui!!!");
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lowCaseMsg.StartsWith("ping ") || lowCaseMsg.Equals("ping"))
|
||||||
|
{
|
||||||
|
var hasPing = _database.GuildSettings.FirstOrDefault(guild => guild.GuildId.Equals(((SocketGuildChannel) message.Channel).Guild.Id.AsLong()))?.Ping ?? false;
|
||||||
|
if (hasPing)
|
||||||
|
{
|
||||||
|
message.Channel.SendMessageAsync("pong");
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(message.HasCharPrefix('!', ref argPos) ||
|
||||||
|
message.HasMentionPrefix(_client.CurrentUser, ref argPos))) return Task.CompletedTask;
|
||||||
|
var context = new GeekbotContext(_client, message, _translationHandler);
|
||||||
|
var commandExec = _commands.ExecuteAsync(context, argPos, _servicesProvider);
|
||||||
|
_logger.Information(LogSource.Command,
|
||||||
|
context.Message.Content.Split(" ")[0].Replace("!", ""),
|
||||||
|
SimpleConextConverter.ConvertContext(context));
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.Error(LogSource.Geekbot, "Failed to Process Message", e);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task UpdateStats(SocketMessage message)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (message == null) return;
|
||||||
|
if (message.Channel.Name.StartsWith('@'))
|
||||||
|
{
|
||||||
|
_logger.Information(LogSource.Message, $"[DM-Channel] {message.Content}", SimpleConextConverter.ConvertSocketMessage(message, true));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var channel = (SocketGuildChannel) message.Channel;
|
||||||
|
|
||||||
|
// just testing, redis will remain the source of truth for now
|
||||||
|
var rowId = await _messageCounterDatabaseContext.Database.ExecuteSqlCommandAsync(
|
||||||
|
"UPDATE \"Messages\" SET \"MessageCount\" = \"MessageCount\" + 1 WHERE \"GuildId\" = {0} AND \"UserId\" = {1}",
|
||||||
|
channel.Guild.Id.AsLong(),
|
||||||
|
message.Author.Id.AsLong()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (rowId == 0)
|
||||||
|
{
|
||||||
|
_messageCounterDatabaseContext.Messages.Add(new MessagesModel
|
||||||
|
{
|
||||||
|
UserId = message.Author.Id.AsLong(),
|
||||||
|
GuildId = channel.Guild.Id.AsLong(),
|
||||||
|
MessageCount = 1
|
||||||
|
});
|
||||||
|
_messageCounterDatabaseContext.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
await _redis.Db.HashIncrementAsync($"{channel.Guild.Id}:Messages", message.Author.Id.ToString());
|
||||||
|
await _redis.Db.HashIncrementAsync($"{channel.Guild.Id}:Messages", 0.ToString());
|
||||||
|
|
||||||
|
if (message.Author.IsBot) return;
|
||||||
|
_logger.Information(LogSource.Message, message.Content, SimpleConextConverter.ConvertSocketMessage(message));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.Error(LogSource.Message, "Could not process message stats", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// User Stuff
|
||||||
|
//
|
||||||
|
|
||||||
|
public async Task UserJoined(SocketGuildUser user)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var userRepoUpdate = _userRepository.Update(user);
|
||||||
|
_logger.Information(LogSource.Geekbot, $"{user.Username} ({user.Id}) joined {user.Guild.Name} ({user.Guild.Id})");
|
||||||
|
|
||||||
|
if (!user.IsBot)
|
||||||
|
{
|
||||||
|
var guildSettings = _database.GuildSettings.FirstOrDefault(guild => guild.GuildId == user.Guild.Id.AsLong());
|
||||||
|
var message = guildSettings?.WelcomeMessage;
|
||||||
|
if (string.IsNullOrEmpty(message)) return;
|
||||||
|
message = message.Replace("$user", user.Mention);
|
||||||
|
|
||||||
|
var fallbackSender = new Func<Task<RestUserMessage>>(() => user.Guild.DefaultChannel.SendMessageAsync(message));
|
||||||
|
if (guildSettings.WelcomeChannel != 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var target = await _client.GetChannelAsync(guildSettings.WelcomeChannel.AsUlong());
|
||||||
|
var channel = target as ISocketMessageChannel;
|
||||||
|
await channel.SendMessageAsync(message);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.Error(LogSource.Geekbot, "Failed to send welcome message to user defined welcome channel", e);
|
||||||
|
await fallbackSender();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await fallbackSender();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await userRepoUpdate;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.Error(LogSource.Geekbot, "Failed to send welcome message", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task UserUpdated(SocketUser oldUser, SocketUser newUser)
|
||||||
|
{
|
||||||
|
await _userRepository.Update(newUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task UserLeft(SocketGuildUser user)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var guild = _database.GuildSettings.FirstOrDefault(g =>
|
||||||
|
g.GuildId.Equals(user.Guild.Id.AsLong()));
|
||||||
|
if (guild?.ShowLeave ?? false)
|
||||||
|
{
|
||||||
|
var modChannelSocket = (ISocketMessageChannel) await _client.GetChannelAsync(guild.ModChannel.AsUlong());
|
||||||
|
await modChannelSocket.SendMessageAsync($"{user.Username}#{user.Discriminator} left the server");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.Error(LogSource.Geekbot, "Failed to send leave message", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.Information(LogSource.Geekbot, $"{user.Username} ({user.Id}) joined {user.Guild.Name} ({user.Guild.Id})");
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Message Stuff
|
||||||
|
//
|
||||||
|
|
||||||
|
public async Task MessageDeleted(Cacheable<IMessage, ulong> message, ISocketMessageChannel channel)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var guildSocketData = ((IGuildChannel) channel).Guild;
|
||||||
|
var guild = _database.GuildSettings.FirstOrDefault(g => g.GuildId.Equals(guildSocketData.Id.AsLong()));
|
||||||
|
if ((guild?.ShowDelete ?? false) && guild?.ModChannel != 0)
|
||||||
|
{
|
||||||
|
var modChannelSocket = (ISocketMessageChannel) await _client.GetChannelAsync(guild.ModChannel.AsUlong());
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
if (message.Value != null)
|
||||||
|
{
|
||||||
|
sb.AppendLine($"The following message from {message.Value.Author.Username}#{message.Value.Author.Discriminator} was deleted in <#{channel.Id}>");
|
||||||
|
sb.AppendLine(message.Value.Content);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.AppendLine("Someone deleted a message, the message was not cached...");
|
||||||
|
}
|
||||||
|
|
||||||
|
await modChannelSocket.SendMessageAsync(sb.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.Error(LogSource.Geekbot, "Failed to send delete message...", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reactions
|
||||||
|
//
|
||||||
|
|
||||||
|
public Task ReactionAdded(Cacheable<IUserMessage, ulong> cacheable, ISocketMessageChannel socketMessageChannel, SocketReaction reaction)
|
||||||
|
{
|
||||||
|
if (reaction.User.Value.IsBot) return Task.CompletedTask;
|
||||||
|
if (!_reactionListener.IsListener(reaction.MessageId)) return Task.CompletedTask;
|
||||||
|
_reactionListener.GiveRole(socketMessageChannel, reaction);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task ReactionRemoved(Cacheable<IUserMessage, ulong> cacheable, ISocketMessageChannel socketMessageChannel, SocketReaction reaction)
|
||||||
|
{
|
||||||
|
if (reaction.User.Value.IsBot) return Task.CompletedTask;
|
||||||
|
if (!_reactionListener.IsListener(reaction.MessageId)) return Task.CompletedTask;
|
||||||
|
_reactionListener.RemoveRole(socketMessageChannel, reaction);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
35
Geekbot.net/Lib/AlmostRedis/AlmostRedis.cs
Normal file
35
Geekbot.net/Lib/AlmostRedis/AlmostRedis.cs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Geekbot.net.Lib.Logger;
|
||||||
|
using StackExchange.Redis;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Lib.AlmostRedis
|
||||||
|
{
|
||||||
|
// if anyone ever sees this, please come up with a better fucking name, i'd appriciate it
|
||||||
|
public class AlmostRedis : IAlmostRedis
|
||||||
|
{
|
||||||
|
private readonly GeekbotLogger _logger;
|
||||||
|
private readonly RunParameters _runParameters;
|
||||||
|
|
||||||
|
public AlmostRedis(GeekbotLogger logger, RunParameters runParameters)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_runParameters = runParameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Connect()
|
||||||
|
{
|
||||||
|
Connection = ConnectionMultiplexer.Connect($"{_runParameters.RedisHost}:{_runParameters.RedisPort}");
|
||||||
|
Db = Connection.GetDatabase(int.Parse(_runParameters.RedisDatabase));
|
||||||
|
_logger.Information(LogSource.Redis, $"Connected to Redis on {Connection.Configuration} at {Db.Database}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public IDatabase Db { get; private set; }
|
||||||
|
|
||||||
|
public ConnectionMultiplexer Connection { get; private set; }
|
||||||
|
|
||||||
|
public IEnumerable<RedisKey> GetAllKeys()
|
||||||
|
{
|
||||||
|
return Connection.GetServer($"{_runParameters.RedisHost}:{_runParameters.RedisPort}").Keys(int.Parse(_runParameters.RedisDatabase));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
Geekbot.net/Lib/AlmostRedis/IAlmostRedis.cs
Normal file
13
Geekbot.net/Lib/AlmostRedis/IAlmostRedis.cs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using StackExchange.Redis;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Lib.AlmostRedis
|
||||||
|
{
|
||||||
|
public interface IAlmostRedis
|
||||||
|
{
|
||||||
|
void Connect();
|
||||||
|
IDatabase Db { get; }
|
||||||
|
ConnectionMultiplexer Connection { get; }
|
||||||
|
IEnumerable<RedisKey> GetAllKeys();
|
||||||
|
}
|
||||||
|
}
|
12
Geekbot.net/Lib/Clients/IMalClient.cs
Normal file
12
Geekbot.net/Lib/Clients/IMalClient.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MyAnimeListSharp.Core;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Lib.Clients
|
||||||
|
{
|
||||||
|
public interface IMalClient
|
||||||
|
{
|
||||||
|
bool IsLoggedIn();
|
||||||
|
Task<AnimeEntry> GetAnime(string query);
|
||||||
|
Task<MangaEntry> GetManga(string query);
|
||||||
|
}
|
||||||
|
}
|
63
Geekbot.net/Lib/Clients/MalClient.cs
Normal file
63
Geekbot.net/Lib/Clients/MalClient.cs
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Geekbot.net.Lib.GlobalSettings;
|
||||||
|
using Geekbot.net.Lib.Logger;
|
||||||
|
using MyAnimeListSharp.Auth;
|
||||||
|
using MyAnimeListSharp.Core;
|
||||||
|
using MyAnimeListSharp.Facade.Async;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Lib.Clients
|
||||||
|
{
|
||||||
|
public class MalClient : IMalClient
|
||||||
|
{
|
||||||
|
private readonly IGlobalSettings _globalSettings;
|
||||||
|
private readonly IGeekbotLogger _logger;
|
||||||
|
private ICredentialContext _credentials;
|
||||||
|
private AnimeSearchMethodsAsync _animeSearch;
|
||||||
|
private MangaSearchMethodsAsync _mangaSearch;
|
||||||
|
|
||||||
|
public MalClient(IGlobalSettings globalSettings, IGeekbotLogger logger)
|
||||||
|
{
|
||||||
|
_globalSettings = globalSettings;
|
||||||
|
_logger = logger;
|
||||||
|
ReloadClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ReloadClient()
|
||||||
|
{
|
||||||
|
var malCredentials = _globalSettings.GetKey("MalCredentials");
|
||||||
|
if (!string.IsNullOrEmpty(malCredentials))
|
||||||
|
{
|
||||||
|
var credSplit = malCredentials.Split('|');
|
||||||
|
_credentials = new CredentialContext()
|
||||||
|
{
|
||||||
|
UserName = credSplit[0],
|
||||||
|
Password = credSplit[1]
|
||||||
|
};
|
||||||
|
_animeSearch = new AnimeSearchMethodsAsync(_credentials);
|
||||||
|
_mangaSearch = new MangaSearchMethodsAsync(_credentials);
|
||||||
|
_logger.Debug(LogSource.Geekbot, "Logged in to MAL");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
_logger.Debug(LogSource.Geekbot, "No MAL Credentials Set!");
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsLoggedIn()
|
||||||
|
{
|
||||||
|
return _credentials != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<AnimeEntry> GetAnime(string query)
|
||||||
|
{
|
||||||
|
var response = await _animeSearch.SearchDeserializedAsync(query);
|
||||||
|
return response.Entries.Count == 0 ? null : response.Entries[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<MangaEntry> GetManga(string query)
|
||||||
|
{
|
||||||
|
var response = await _mangaSearch.SearchDeserializedAsync(query);
|
||||||
|
return response.Entries.Count == 0 ? null : response.Entries[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,9 +2,9 @@ using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
|
|
||||||
namespace Geekbot.Bot.CommandPreconditions
|
namespace Geekbot.net.Lib.CommandPreconditions
|
||||||
{
|
{
|
||||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
|
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
|
||||||
public class DisableInDirectMessageAttribute : PreconditionAttribute
|
public class DisableInDirectMessageAttribute : PreconditionAttribute
|
||||||
{
|
{
|
||||||
public override Task<PreconditionResult> CheckPermissionsAsync(ICommandContext context, CommandInfo command, IServiceProvider services)
|
public override Task<PreconditionResult> CheckPermissionsAsync(ICommandContext context, CommandInfo command, IServiceProvider services)
|
|
@ -1,6 +1,6 @@
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace Geekbot.Core
|
namespace Geekbot.net.Lib
|
||||||
{
|
{
|
||||||
public static class Constants
|
public static class Constants
|
||||||
{
|
{
|
||||||
|
@ -8,7 +8,7 @@ namespace Geekbot.Core
|
||||||
|
|
||||||
public static string BotVersion()
|
public static string BotVersion()
|
||||||
{
|
{
|
||||||
return typeof(Constants).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion;
|
return typeof(Program).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string LibraryVersion()
|
public static string LibraryVersion()
|
56
Geekbot.net/Lib/Context/GeekbotContext.cs
Normal file
56
Geekbot.net/Lib/Context/GeekbotContext.cs
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
using Discord;
|
||||||
|
using Geekbot.net.Lib.Localization;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Lib.Context
|
||||||
|
{
|
||||||
|
/// <summary> The context of a command which may contain the client, user, guild, channel, and message. </summary>
|
||||||
|
public class GeekbotContext : IGeekbotContext
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IDiscordClient Client { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IGuild Guild { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IMessageChannel Channel { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IUser User { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IUserMessage Message { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IGuildUser GuildUser { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public TranslationGuildContext Translations { get; }
|
||||||
|
|
||||||
|
/// <summary> Indicates whether the channel that the command is executed in is a private channel. </summary>
|
||||||
|
public bool IsPrivate
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.Channel is IPrivateChannel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new <see cref="T:Discord.Commands.CommandContext" /> class with the provided client and message.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="client">The underlying client.</param>
|
||||||
|
/// <param name="msg">The underlying message.</param>
|
||||||
|
/// <param name="translationHandler">the translation handler</param>
|
||||||
|
public GeekbotContext(IDiscordClient client, IUserMessage msg, ITranslationHandler translationHandler)
|
||||||
|
{
|
||||||
|
this.Client = client;
|
||||||
|
this.Guild = (msg.Channel as IGuildChannel)?.Guild;
|
||||||
|
this.Channel = msg.Channel;
|
||||||
|
this.User = msg.Author;
|
||||||
|
this.GuildUser = msg.Author as IGuildUser;
|
||||||
|
this.Message = msg;
|
||||||
|
this.Translations = translationHandler.GetGuildContext(this.Guild, this.Message).Result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
Geekbot.net/Lib/Context/IGeekbotContext.cs
Normal file
19
Geekbot.net/Lib/Context/IGeekbotContext.cs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
using Discord;
|
||||||
|
using Discord.Commands;
|
||||||
|
using Geekbot.net.Lib.Localization;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Lib.Context
|
||||||
|
{
|
||||||
|
public interface IGeekbotContext : ICommandContext
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the <see cref="T:Discord:IGuildUser"/> who executed the command.
|
||||||
|
/// </summary>
|
||||||
|
IGuildUser GuildUser { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the <see cref="T:Geekbot:net:Lib:Localization:TranslationGuildContext"/> containing the necessary tools for command localization.
|
||||||
|
/// </summary>
|
||||||
|
TranslationGuildContext Translations { get; }
|
||||||
|
}
|
||||||
|
}
|
93
Geekbot.net/Lib/Converters/EmojiConverter.cs
Normal file
93
Geekbot.net/Lib/Converters/EmojiConverter.cs
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Lib.Converters
|
||||||
|
{
|
||||||
|
public class EmojiConverter : IEmojiConverter
|
||||||
|
{
|
||||||
|
public string NumberToEmoji(int number)
|
||||||
|
{
|
||||||
|
if (number == 10)
|
||||||
|
{
|
||||||
|
return "🔟";
|
||||||
|
}
|
||||||
|
var emojiMap = new[]
|
||||||
|
{
|
||||||
|
":zero:",
|
||||||
|
":one:",
|
||||||
|
":two:",
|
||||||
|
":three:",
|
||||||
|
":four:",
|
||||||
|
":five:",
|
||||||
|
":six:",
|
||||||
|
":seven:",
|
||||||
|
":eight:",
|
||||||
|
":nine:"
|
||||||
|
};
|
||||||
|
var numbers = number.ToString().ToCharArray();
|
||||||
|
var returnString = new StringBuilder();
|
||||||
|
foreach (var n in numbers)
|
||||||
|
{
|
||||||
|
returnString.Append(emojiMap[int.Parse(n.ToString())]);
|
||||||
|
}
|
||||||
|
return returnString.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string TextToEmoji(string text)
|
||||||
|
{
|
||||||
|
var emojiMap = new Hashtable
|
||||||
|
{
|
||||||
|
['A'] = ":regional_indicator_a: ",
|
||||||
|
['B'] = ":b: ",
|
||||||
|
['C'] = ":regional_indicator_c: ",
|
||||||
|
['D'] = ":regional_indicator_d: ",
|
||||||
|
['E'] = ":regional_indicator_e: ",
|
||||||
|
['F'] = ":regional_indicator_f: ",
|
||||||
|
['G'] = ":regional_indicator_g: ",
|
||||||
|
['H'] = ":regional_indicator_h: ",
|
||||||
|
['I'] = ":regional_indicator_i: ",
|
||||||
|
['J'] = ":regional_indicator_j: ",
|
||||||
|
['K'] = ":regional_indicator_k: ",
|
||||||
|
['L'] = ":regional_indicator_l: ",
|
||||||
|
['M'] = ":regional_indicator_m: ",
|
||||||
|
['N'] = ":regional_indicator_n: ",
|
||||||
|
['O'] = ":regional_indicator_o: ",
|
||||||
|
['P'] = ":regional_indicator_p: ",
|
||||||
|
['Q'] = ":regional_indicator_q: ",
|
||||||
|
['R'] = ":regional_indicator_r: ",
|
||||||
|
['S'] = ":regional_indicator_s: ",
|
||||||
|
['T'] = ":regional_indicator_t: ",
|
||||||
|
['U'] = ":regional_indicator_u: ",
|
||||||
|
['V'] = ":regional_indicator_v: ",
|
||||||
|
['W'] = ":regional_indicator_w: ",
|
||||||
|
['X'] = ":regional_indicator_x: ",
|
||||||
|
['Y'] = ":regional_indicator_y: ",
|
||||||
|
['Z'] = ":regional_indicator_z: ",
|
||||||
|
['!'] = ":exclamation: ",
|
||||||
|
['?'] = ":question: ",
|
||||||
|
['#'] = ":hash: ",
|
||||||
|
['*'] = ":star2: ",
|
||||||
|
['+'] = ":heavy_plus_sign: ",
|
||||||
|
['0'] = ":zero: ",
|
||||||
|
['1'] = ":one: ",
|
||||||
|
['2'] = ":two: ",
|
||||||
|
['3'] = ":three: ",
|
||||||
|
['4'] = ":four: ",
|
||||||
|
['5'] = ":five: ",
|
||||||
|
['6'] = ":six: ",
|
||||||
|
['7'] = ":seven: ",
|
||||||
|
['8'] = ":eight: ",
|
||||||
|
['9'] = ":nine: ",
|
||||||
|
[' '] = " "
|
||||||
|
};
|
||||||
|
var letters = text.ToUpper().ToCharArray();
|
||||||
|
var returnString = new StringBuilder();
|
||||||
|
foreach (var n in letters)
|
||||||
|
{
|
||||||
|
var emoji = emojiMap[n] ?? n;
|
||||||
|
returnString.Append(emoji);
|
||||||
|
}
|
||||||
|
return returnString.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
8
Geekbot.net/Lib/Converters/IEmojiConverter.cs
Normal file
8
Geekbot.net/Lib/Converters/IEmojiConverter.cs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
namespace Geekbot.net.Lib.Converters
|
||||||
|
{
|
||||||
|
public interface IEmojiConverter
|
||||||
|
{
|
||||||
|
string NumberToEmoji(int number);
|
||||||
|
string TextToEmoji(string text);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
namespace Geekbot.Core.Converters
|
namespace Geekbot.net.Lib.Converters
|
||||||
{
|
{
|
||||||
public interface IMtgManaConverter
|
public interface IMtgManaConverter
|
||||||
{
|
{
|
33
Geekbot.net/Lib/Converters/MtgManaConverter.cs
Normal file
33
Geekbot.net/Lib/Converters/MtgManaConverter.cs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using Utf8Json;
|
||||||
|
|
||||||
|
namespace Geekbot.net.Lib.Converters
|
||||||
|
{
|
||||||
|
public class MtgManaConverter : IMtgManaConverter
|
||||||
|
{
|
||||||
|
private Dictionary<string, string> _manaDict;
|
||||||
|
|
||||||
|
public MtgManaConverter()
|
||||||
|
{
|
||||||
|
// these emotes can be found at https://discord.gg/bz8HyA7
|
||||||
|
var mtgEmojis = File.ReadAllText(Path.GetFullPath("./Lib/Converters/MtgManaEmojis.json"));
|
||||||
|
_manaDict = JsonSerializer.Deserialize<Dictionary<string, string>>(mtgEmojis);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ConvertMana(string mana)
|
||||||
|
{
|
||||||
|
var rgx = Regex.Matches(mana, @"(\{(.*?)\})");
|
||||||
|
foreach (Match manaTypes in rgx)
|
||||||
|
{
|
||||||
|
var m = _manaDict.GetValueOrDefault(manaTypes.Value);
|
||||||
|
if (!string.IsNullOrEmpty(m))
|
||||||
|
{
|
||||||
|
mana = mana.Replace(manaTypes.Value, m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mana;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
50
Geekbot.net/Lib/Converters/MtgManaEmojis.json
Normal file
50
Geekbot.net/Lib/Converters/MtgManaEmojis.json
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
{
|
||||||
|
"{0}": "<:mtg_0:415216130043412482>",
|
||||||
|
"{1}": "<:mtg_1:415216130253389835>",
|
||||||
|
"{2}": "<:mtg_2:415216130031091713>",
|
||||||
|
"{3}": "<:mtg_3:415216130467037194>",
|
||||||
|
"{4}": "<:mtg_4:415216130026635295>",
|
||||||
|
"{5}": "<:mtg_5:415216130492203008>",
|
||||||
|
"{6}": "<:mtg_6:415216130458779658>",
|
||||||
|
"{7}": "<:mtg_7:415216130190475265>",
|
||||||
|
"{8}": "<:mtg_8:415216130517630986>",
|
||||||
|
"{9}": "<:mtg_9:415216130500722689>",
|
||||||
|
"{10": "<:mtg_10:415216130450391051>",
|
||||||
|
"{11}": "<:mtg_11:415216130811101185>",
|
||||||
|
"{12}": "<:mtg_12:415216130525888532>",
|
||||||
|
"{13}": "<:mtg_13:415216130517631000>",
|
||||||
|
"{14}": "<:mtg_14:415216130165178370>",
|
||||||
|
"{15}": "<:mtg_15:415216130576089108>",
|
||||||
|
"{16}": "<:mtg_16:415216130358247425>",
|
||||||
|
"{17}": "<:mtg_17:415216130601517056>",
|
||||||
|
"{18}": "<:mtg_18:415216130462842891>",
|
||||||
|
"{19}": "<:mtg_19:415216130614099988>",
|
||||||
|
"{20}": "<:mtg_20:415216130656043038>",
|
||||||
|
"{W}": "<:mtg_white:415216131515744256>",
|
||||||
|
"{U}": "<:mtg_blue:415216130521694209>",
|
||||||
|
"{B}": "<:mtg_black:415216130873884683>",
|
||||||
|
"{R}": "<:mtg_red:415216131322806272>",
|
||||||
|
"{G}": "<:mtg_green:415216131180331009>",
|
||||||
|
"{S}": "<:mtg_s:415216131293446144>",
|
||||||
|
"{T}": "<:mtg_tap:415258392727257088>",
|
||||||
|
"{C}": "<:mtg_colorless:415216130706374666>",
|
||||||
|
"{2/W}": "<:mtg_2w:415216130446065664>",
|
||||||
|
"{2/U}": "<:mtg_2u:415216130429550592>",
|
||||||
|
"{2/B}": "<:mtg_2b:415216130160984065>",
|
||||||
|
"{2/R}": "<:mtg_2r:415216130454716436>",
|
||||||
|
"{2/G}": "<:mtg_2g:415216130420899840>",
|
||||||
|
"{W/U}": "<:mtg_wu:415216130970484736>",
|
||||||
|
"{W/B}": "<:mtg_wb:415216131222011914>",
|
||||||
|
"{U/R}": "<:mtg_ur:415216130962096128>",
|
||||||
|
"{U/B}": "<:mtg_ub:415216130865758218>",
|
||||||
|
"{R/W}": "<:mtg_rw:415216130878210057>",
|
||||||
|
"{G/W}": "<:mtg_gw:415216130567962646>",
|
||||||
|
"{G/U}": "<:mtg_gu:415216130739666945>",
|
||||||
|
"{B/R}": "<:mtg_br:415216130580283394>",
|
||||||
|
"{B/G}": "<:mtg_bg:415216130781609994>",
|
||||||
|
"{U/P}": "<:mtg_up:415216130861432842>",
|
||||||
|
"{R/P}": "<:mtg_rp:415216130597322783>",
|
||||||
|
"{G/P}": "<:mtg_gp:415216130760769546>",
|
||||||
|
"{W/P}": "<:mtg_wp:415216131541041172>",
|
||||||
|
"{B/P}": "<:mtg_bp:415216130664169482>"
|
||||||
|
}
|
|
@ -1,32 +1,47 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Geekbot.Core.Logger;
|
using Discord.Net;
|
||||||
using Sentry;
|
using Geekbot.net.Lib.GlobalSettings;
|
||||||
|
using Geekbot.net.Lib.Localization;
|
||||||
|
using Geekbot.net.Lib.Logger;
|
||||||
|
using SharpRaven;
|
||||||
|
using SharpRaven.Data;
|
||||||
using Exception = System.Exception;
|
using Exception = System.Exception;
|
||||||
|
|
||||||
namespace Geekbot.Core.ErrorHandling
|
namespace Geekbot.net.Lib.ErrorHandling
|
||||||
{
|
{
|
||||||
public class ErrorHandler : IErrorHandler
|
public class ErrorHandler : IErrorHandler
|
||||||
{
|
{
|
||||||
private readonly IGeekbotLogger _logger;
|
private readonly IGeekbotLogger _logger;
|
||||||
private readonly Func<string> _getDefaultErrorText;
|
private readonly ITranslationHandler _translation;
|
||||||
|
private readonly IRavenClient _raven;
|
||||||
private readonly bool _errorsInChat;
|
private readonly bool _errorsInChat;
|
||||||
|
|
||||||
public ErrorHandler(IGeekbotLogger logger, RunParameters runParameters, Func<string> getDefaultErrorText)
|
public ErrorHandler(IGeekbotLogger logger, ITranslationHandler translation, IGlobalSettings globalSettings, bool errorsInChat)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_getDefaultErrorText = getDefaultErrorText;
|
_translation = translation;
|
||||||
_errorsInChat = runParameters.ExposeErrors;
|
_errorsInChat = errorsInChat;
|
||||||
|
|
||||||
|
var sentryDsn = Environment.GetEnvironmentVariable("SENTRY");
|
||||||
|
if (!string.IsNullOrEmpty(sentryDsn))
|
||||||
|
{
|
||||||
|
_raven = new RavenClient(sentryDsn) { Release = Constants.BotVersion(), Environment = "Production" };
|
||||||
|
_logger.Information(LogSource.Geekbot, $"Command Errors will be logged to Sentry: {sentryDsn}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_raven = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task HandleCommandException(Exception e, ICommandContext context, string errorMessage = "def")
|
public async Task HandleCommandException(Exception e, ICommandContext context, string errorMessage = "def")
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var errorString = errorMessage == "def"
|
var errorString = errorMessage == "def" ? await _translation.GetString(context.Guild?.Id ?? 0, "errorHandler", "SomethingWentWrong") : errorMessage;
|
||||||
? _getDefaultErrorText()
|
|
||||||
: errorMessage;
|
|
||||||
var errorObj = SimpleConextConverter.ConvertContext(context);
|
var errorObj = SimpleConextConverter.ConvertContext(context);
|
||||||
if (e.Message.Contains("50007")) return;
|
if (e.Message.Contains("50007")) return;
|
||||||
if (e.Message.Contains("50013")) return;
|
if (e.Message.Contains("50013")) return;
|
||||||
|
@ -57,32 +72,36 @@ namespace Geekbot.Core.ErrorHandling
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
try
|
await context.Channel.SendMessageAsync("Something went really really wrong here");
|
||||||
{
|
_logger.Error(LogSource.Geekbot, "Errorception", ex);
|
||||||
await context.Channel.SendMessageAsync("Something went really really wrong here");
|
}
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
{
|
public async Task HandleHttpException(HttpException e, ICommandContext context)
|
||||||
_logger.Error(LogSource.Geekbot, "Errorception", ex);
|
{
|
||||||
}
|
var errorStrings = await _translation.GetDict(context, "httpErrors");
|
||||||
|
switch(e.HttpCode)
|
||||||
|
{
|
||||||
|
case HttpStatusCode.Forbidden:
|
||||||
|
await context.Channel.SendMessageAsync(errorStrings["403"]);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReportExternal(Exception e, MessageDto errorObj)
|
private void ReportExternal(Exception e, MessageDto errorObj)
|
||||||
{
|
{
|
||||||
if (!SentrySdk.IsEnabled) return;
|
if (_raven == null) return;
|
||||||
|
|
||||||
var sentryEvent = new SentryEvent(e)
|
var sentryEvent = new SentryEvent(e)
|
||||||
{
|
{
|
||||||
|
Tags =
|
||||||
|
{
|
||||||
|
["discord_server"] = errorObj.Guild.Name,
|
||||||
|
["discord_user"] = errorObj.User.Name
|
||||||
|
},
|
||||||
Message = errorObj.Message.Content,
|
Message = errorObj.Message.Content,
|
||||||
|
Extra = errorObj
|
||||||
};
|
};
|
||||||
sentryEvent.SetTag("discord_server", errorObj.Guild.Name);
|
_raven.Capture(sentryEvent);
|
||||||
sentryEvent.SetExtra("Channel", errorObj.Channel);
|
|
||||||
sentryEvent.SetExtra("Guild", errorObj.Guild);
|
|
||||||
sentryEvent.SetExtra("Message", errorObj.Message);
|
|
||||||
sentryEvent.SetExtra("User", errorObj.User);
|
|
||||||
|
|
||||||
SentrySdk.CaptureEvent(sentryEvent);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,11 +1,13 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
|
using Discord.Net;
|
||||||
|
|
||||||
namespace Geekbot.Core.ErrorHandling
|
namespace Geekbot.net.Lib.ErrorHandling
|
||||||
{
|
{
|
||||||
public interface IErrorHandler
|
public interface IErrorHandler
|
||||||
{
|
{
|
||||||
Task HandleCommandException(Exception e, ICommandContext context, string errorMessage = "def");
|
Task HandleCommandException(Exception e, ICommandContext context, string errorMessage = "def");
|
||||||
|
Task HandleHttpException(HttpException e, ICommandContext context);
|
||||||
}
|
}
|
||||||
}
|
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue