diff --git a/.gitignore b/.gitignore
index fb37716..1aa3e36 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,484 +1,6 @@
-# Created by https://www.toptal.com/developers/gitignore/api/csharp,rider
-# Edit at https://www.toptal.com/developers/gitignore?templates=csharp,rider
-
-### Csharp ###
-## Ignore Visual Studio temporary files, build results, and
-## files generated by popular Visual Studio add-ons.
-##
-## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
-
-# User-specific files
-*.rsuser
-*.suo
-*.user
-*.userosscache
-*.sln.docstates
-
-# User-specific files (MonoDevelop/Xamarin Studio)
-*.userprefs
-
-# Mono auto generated files
-mono_crash.*
-
-# Build results
-[Dd]ebug/
-[Dd]ebugPublic/
-[Rr]elease/
-[Rr]eleases/
-x64/
-x86/
-[Ww][Ii][Nn]32/
-[Aa][Rr][Mm]/
-[Aa][Rr][Mm]64/
-bld/
-[Bb]in/
-[Oo]bj/
-[Ll]og/
-[Ll]ogs/
-
-# Visual Studio 2015/2017 cache/options directory
-.vs/
-# Uncomment if you have tasks that create the project's static files in wwwroot
-#wwwroot/
-
-# Visual Studio 2017 auto generated files
-Generated\ Files/
-
-# MSTest test Results
-[Tt]est[Rr]esult*/
-[Bb]uild[Ll]og.*
-
-# NUnit
-*.VisualState.xml
-TestResult.xml
-nunit-*.xml
-
-# Build Results of an ATL Project
-[Dd]ebugPS/
-[Rr]eleasePS/
-dlldata.c
-
-# Benchmark Results
-BenchmarkDotNet.Artifacts/
-
-# .NET Core
-project.lock.json
-project.fragment.lock.json
-artifacts/
-
-# ASP.NET Scaffolding
-ScaffoldingReadMe.txt
-
-# StyleCop
-StyleCopReport.xml
-
-# Files built by Visual Studio
-*_i.c
-*_p.c
-*_h.h
-*.ilk
-*.meta
-*.obj
-*.iobj
-*.pch
-*.pdb
-*.ipdb
-*.pgc
-*.pgd
-*.rsp
-*.sbr
-*.tlb
-*.tli
-*.tlh
-*.tmp
-*.tmp_proj
-*_wpftmp.csproj
-*.log
-*.tlog
-*.vspscc
-*.vssscc
-.builds
-*.pidb
-*.svclog
-*.scc
-
-# Chutzpah Test files
-_Chutzpah*
-
-# Visual C++ cache files
-ipch/
-*.aps
-*.ncb
-*.opendb
-*.opensdf
-*.sdf
-*.cachefile
-*.VC.db
-*.VC.VC.opendb
-
-# Visual Studio profiler
-*.psess
-*.vsp
-*.vspx
-*.sap
-
-# Visual Studio Trace Files
-*.e2e
-
-# TFS 2012 Local Workspace
-$tf/
-
-# Guidance Automation Toolkit
-*.gpState
-
-# ReSharper is a .NET coding add-in
-_ReSharper*/
-*.[Rr]e[Ss]harper
-*.DotSettings.user
-
-# TeamCity is a build add-in
-_TeamCity*
-
-# DotCover is a Code Coverage Tool
-*.dotCover
-
-# AxoCover is a Code Coverage Tool
-.axoCover/*
-!.axoCover/settings.json
-
-# Coverlet is a free, cross platform Code Coverage Tool
-coverage*.json
-coverage*.xml
-coverage*.info
-
-# Visual Studio code coverage results
-*.coverage
-*.coveragexml
-
-# NCrunch
-_NCrunch_*
-.*crunch*.local.xml
-nCrunchTemp_*
-
-# MightyMoose
-*.mm.*
-AutoTest.Net/
-
-# Web workbench (sass)
-.sass-cache/
-
-# Installshield output folder
-[Ee]xpress/
-
-# DocProject is a documentation generator add-in
-DocProject/buildhelp/
-DocProject/Help/*.HxT
-DocProject/Help/*.HxC
-DocProject/Help/*.hhc
-DocProject/Help/*.hhk
-DocProject/Help/*.hhp
-DocProject/Help/Html2
-DocProject/Help/html
-
-# Click-Once directory
-publish/
-
-# Publish Web Output
-*.[Pp]ublish.xml
-*.azurePubxml
-# Note: Comment the next line if you want to checkin your web deploy settings,
-# but database connection strings (with potential passwords) will be unencrypted
-*.pubxml
-*.publishproj
-
-# Microsoft Azure Web App publish settings. Comment the next line if you want to
-# checkin your Azure Web App publish settings, but sensitive information contained
-# in these scripts will be unencrypted
-PublishScripts/
-
-# NuGet Packages
-*.nupkg
-# NuGet Symbol Packages
-*.snupkg
-# The packages folder can be ignored because of Package Restore
-**/[Pp]ackages/*
-# except build/, which is used as an MSBuild target.
-!**/[Pp]ackages/build/
-# Uncomment if necessary however generally it will be regenerated when needed
-#!**/[Pp]ackages/repositories.config
-# NuGet v3's project.json files produces more ignorable files
-*.nuget.props
-*.nuget.targets
-
-# Microsoft Azure Build Output
-csx/
-*.build.csdef
-
-# Microsoft Azure Emulator
-ecf/
-rcf/
-
-# Windows Store app package directories and files
-AppPackages/
-BundleArtifacts/
-Package.StoreAssociation.xml
-_pkginfo.txt
-*.appx
-*.appxbundle
-*.appxupload
-
-# Visual Studio cache files
-# files ending in .cache can be ignored
-*.[Cc]ache
-# but keep track of directories ending in .cache
-!?*.[Cc]ache/
-
-# Others
-ClientBin/
-~$*
-*~
-*.dbmdl
-*.dbproj.schemaview
-*.jfm
-*.pfx
-*.publishsettings
-orleans.codegen.cs
-
-# Including strong name files can present a security risk
-# (https://github.com/github/gitignore/pull/2483#issue-259490424)
-#*.snk
-
-# Since there are multiple workflows, uncomment next line to ignore bower_components
-# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
-#bower_components/
-
-# RIA/Silverlight projects
-Generated_Code/
-
-# Backup & report files from converting an old project file
-# to a newer Visual Studio version. Backup files are not needed,
-# because we have git ;-)
-_UpgradeReport_Files/
-Backup*/
-UpgradeLog*.XML
-UpgradeLog*.htm
-ServiceFabricBackup/
-*.rptproj.bak
-
-# SQL Server files
-*.mdf
-*.ldf
-*.ndf
-
-# Business Intelligence projects
-*.rdl.data
-*.bim.layout
-*.bim_*.settings
-*.rptproj.rsuser
-*- [Bb]ackup.rdl
-*- [Bb]ackup ([0-9]).rdl
-*- [Bb]ackup ([0-9][0-9]).rdl
-
-# Microsoft Fakes
-FakesAssemblies/
-
-# GhostDoc plugin setting file
-*.GhostDoc.xml
-
-# Node.js Tools for Visual Studio
-.ntvs_analysis.dat
-node_modules/
-
-# Visual Studio 6 build log
-*.plg
-
-# Visual Studio 6 workspace options file
-*.opt
-
-# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
-*.vbw
-
-# Visual Studio 6 auto-generated project file (contains which files were open etc.)
-*.vbp
-
-# Visual Studio 6 workspace and project file (working project files containing files to include in project)
-*.dsw
-*.dsp
-
-# Visual Studio 6 technical files
-
-# Visual Studio LightSwitch build output
-**/*.HTMLClient/GeneratedArtifacts
-**/*.DesktopClient/GeneratedArtifacts
-**/*.DesktopClient/ModelManifest.xml
-**/*.Server/GeneratedArtifacts
-**/*.Server/ModelManifest.xml
-_Pvt_Extensions
-
-# Paket dependency manager
-.paket/paket.exe
-paket-files/
-
-# FAKE - F# Make
-.fake/
-
-# CodeRush personal settings
-.cr/personal
-
-# Python Tools for Visual Studio (PTVS)
-__pycache__/
-*.pyc
-
-# Cake - Uncomment if you are using it
-# tools/**
-# !tools/packages.config
-
-# Tabs Studio
-*.tss
-
-# Telerik's JustMock configuration file
-*.jmconfig
-
-# BizTalk build output
-*.btp.cs
-*.btm.cs
-*.odx.cs
-*.xsd.cs
-
-# OpenCover UI analysis results
-OpenCover/
-
-# Azure Stream Analytics local run output
-ASALocalRun/
-
-# MSBuild Binary and Structured Log
-*.binlog
-
-# NVidia Nsight GPU debugger configuration file
-*.nvuser
-
-# MFractors (Xamarin productivity tool) working folder
-.mfractor/
-
-# Local History for Visual Studio
-.localhistory/
-
-# Visual Studio History (VSHistory) files
-.vshistory/
-
-# BeatPulse healthcheck temp database
-healthchecksdb
-
-# Backup folder for Package Reference Convert tool in Visual Studio 2017
-MigrationBackup/
-
-# Ionide (cross platform F# VS Code tools) working folder
-.ionide/
-
-# Fody - auto-generated XML schema
-FodyWeavers.xsd
-
-# VS Code files for those working on multiple tools
-.vscode/*
-!.vscode/settings.json
-!.vscode/tasks.json
-!.vscode/launch.json
-!.vscode/extensions.json
-*.code-workspace
-
-# Local History for Visual Studio Code
-.history/
-
-# Windows Installer files from build outputs
-*.cab
-*.msi
-*.msix
-*.msm
-*.msp
-
-# JetBrains Rider
-*.sln.iml
-
-### Rider ###
-# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
-# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
-
-# User-specific stuff
-.idea/**/workspace.xml
-.idea/**/tasks.xml
-.idea/**/usage.statistics.xml
-.idea/**/dictionaries
-.idea/**/shelf
-
-# AWS User-specific
-.idea/**/aws.xml
-
-# Generated files
-.idea/**/contentModel.xml
-
-# Sensitive or high-churn files
-.idea/**/dataSources/
-.idea/**/dataSources.ids
-.idea/**/dataSources.local.xml
-.idea/**/sqlDataSources.xml
-.idea/**/dynamic.xml
-.idea/**/uiDesigner.xml
-.idea/**/dbnavigator.xml
-
-# Gradle
-.idea/**/gradle.xml
-.idea/**/libraries
-
-# Gradle and Maven with auto-import
-# When using Gradle or Maven with auto-import, you should exclude module files,
-# since they will be recreated, and may cause churn. Uncomment if using
-# auto-import.
-# .idea/artifacts
-# .idea/compiler.xml
-# .idea/jarRepositories.xml
-# .idea/modules.xml
-# .idea/*.iml
-# .idea/modules
-# *.iml
-# *.ipr
-
-# CMake
-cmake-build-*/
-
-# Mongo Explorer plugin
-.idea/**/mongoSettings.xml
-
-# File-based project format
-*.iws
-
-# IntelliJ
-out/
-
-# mpeltonen/sbt-idea plugin
-.idea_modules/
-
-# JIRA plugin
-atlassian-ide-plugin.xml
-
-# Cursive Clojure plugin
-.idea/replstate.xml
-
-# SonarLint plugin
-.idea/sonarlint/
-
-# Crashlytics plugin (for Android Studio and IntelliJ)
-com_crashlytics_export_strings.xml
-crashlytics.properties
-crashlytics-build.properties
-fabric.properties
-
-# Editor-based Rest Client
-.idea/httpRequests
-
-# Android studio 3.1+ serialized cache file
-.idea/caches/build_file_checksums.ser
-
-# Shit i add.
-.vscode
-.idea
-# End of https://www.toptal.com/developers/gitignore/api/csharp,rider
\ No newline at end of file
+.env
+bot.lua
+deps
+lit.exe
+luvi.exe
+luvit.exe
\ No newline at end of file
diff --git a/Assets/Chrobry(1).png b/Assets/Chrobry(1).png
deleted file mode 100644
index 2f68ff4..0000000
Binary files a/Assets/Chrobry(1).png and /dev/null differ
diff --git a/Chrobry.csproj b/Chrobry.csproj
deleted file mode 100644
index dded999..0000000
--- a/Chrobry.csproj
+++ /dev/null
@@ -1,66 +0,0 @@
-
-
-
- Exe
- net7.0
- enable
- enable
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Chrobry.sln b/Chrobry.sln
deleted file mode 100644
index 35efdb8..0000000
--- a/Chrobry.sln
+++ /dev/null
@@ -1,25 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.7.34031.279
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Chrobry", "Chrobry.csproj", "{5F72A41D-651C-45E0-A377-5F04BC7F0E4D}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {5F72A41D-651C-45E0-A377-5F04BC7F0E4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {5F72A41D-651C-45E0-A377-5F04BC7F0E4D}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {5F72A41D-651C-45E0-A377-5F04BC7F0E4D}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {5F72A41D-651C-45E0-A377-5F04BC7F0E4D}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {570C625E-26DC-4793-998A-10733E2600CD}
- EndGlobalSection
-EndGlobal
diff --git a/LICENSE b/LICENSE
index c650f5b..6ddc646 100644
--- a/LICENSE
+++ b/LICENSE
@@ -208,7 +208,7 @@ If you develop a new program, and you want it to be of the greatest possible use
To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found.
- Chrobry
+ Chrobry-Discord
Copyright (C) 2023 Purplebored
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
@@ -221,7 +221,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode:
- Chrobry Copyright (C) 2023 Purplebored
+ Chrobry-Discord Copyright (C) 2023 Purplebored
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details.
diff --git a/Program.cs b/Program.cs
deleted file mode 100644
index 45d0a67..0000000
--- a/Program.cs
+++ /dev/null
@@ -1,1073 +0,0 @@
-using System.Diagnostics;
-using Optionals;
-using RevoltSharp.Commands;
-using RevoltSharp;
-using System.Reflection;
-using Newtonsoft.Json.Linq;
-using System.Globalization;
-using Microsoft.Extensions.Configuration;
-
-class Program
-{
- public static RevoltClient Client;
-
- public static async Task Main(string[] args)
- {
- await StartAsync();
- }
-
- public static async Task StartAsync()
- {
- IConfiguration Configuration = new ConfigurationBuilder()
- .SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
- .AddJsonFile("config.json")
- .Build();
-
- string token = Configuration["RevoltConfig:Token"];
- string apiUrl = Configuration["RevoltConfig:ApiUrl"];
-
- Client = new RevoltClient(token, ClientMode.WebSocket, new ClientConfig
- {
- ApiUrl = apiUrl
- });
-
- await Client.StartAsync();
-
- // Modify user status
- await Client.CurrentUser.ModifySelfAsync(
- statusText: new Option("?help."),
- statusType: new Option(UserStatusType.Focus)
- );
-
- CommandHandler commandHandler = new CommandHandler(Client);
- commandHandler.LoadCommands();
-
- await Task.Delay(-1);
- }
-}
-// CommandHandler
-public class CommandHandler
-{
- private readonly RevoltClient _client;
- private readonly CommandService _service = new CommandService();
-
- // Here you can change the prefix. Default is "?"
- public const string Prefix = "?";
-
- public CommandHandler(RevoltClient client)
- {
- _client = client;
- _client.OnMessageRecieved += Client_OnMessageReceived;
- _service.OnCommandExecuted += Service_OnCommandExecuted;
- }
-
- public async Task LoadCommands()
- {
- // Load commands from the entry assembly
- await _service.AddModulesAsync(Assembly.GetEntryAssembly(), null);
- }
-
- private void Client_OnMessageReceived(Message msg)
- {
- if (msg is not UserMessage userMessage || userMessage.Author.IsBot)
- return;
-
- int argPos = 0;
- if (!(userMessage.HasCharPrefix('?', ref argPos) ||
- userMessage.HasMentionPrefix(_client.CurrentUser, ref argPos)))
- return;
-
- CommandContext context = new CommandContext(_client, userMessage);
- _service.ExecuteAsync(context, argPos, null);
- }
-
- private void Service_OnCommandExecuted(Optional commandInfo, CommandContext context, IResult result)
- {
- if (result.IsSuccess)
- {
- Console.WriteLine("Success command: " + commandInfo.Value.Name);
- }
- else
- {
- if (commandInfo.HasValue)
- {
- context.Channel.SendMessageAsync("Error: " + result.ErrorReason);
- }
- }
- }
-
- // Only god and the developer of RevoltSharp know what's going on here.
-}
-public class Commands : ModuleBase
-{
- // Help commands:
-
- // Help command.
- [Command("help")]
- public async Task Help()
- {
- var helpMessage =
- "#### List of available commands:\n\n" +
- "#### Practical Commands: \n" +
- "`?help` - Displays this command.\n" +
- "`?credits` - Displays bot's credit.\n" +
- "`?test` - Simple test command you say test bot will response.\n" +
- "`?invite` - Send a link to invite this bot to your server! \n" +
- "`?calculate` {num} {+, - , / , * } {num} - A very simple calculator. \n" +
- "`?mod-help` - Displays a list of available mod commands. \n " +
- "`?ping` - tests the bot ping. \n" +
- "`?nsfw-help` - Sends a list of all available nsfw commands. \n " +
- "#### Fun Commands: \n" +
- "`?dice` - Rolls a random number between 1 and 6.\n" +
- "`?say` - says what the user told it to say!. \n" +
- "`?dm` - Just DMs the user Hi :3. \n" +
- "`?rps {paper,rock,scissors}` - Simple Rock paper scissors game.\n" +
- "`?dogfact` - Gives a random dogfact using the Dogfact API!. \n" +
- "`?catfact` - Gives a random Catfact using cat fact API (Currently somewhat bugged with the []). \n" +
- "`?joke` - Very simple command just gives a joke using the Joke API. \n " +
- "`?coinflip` - a Command so easy a child could do it. \n " +
- "`?fact` - Gives a random useless fact. \n " +
- "`?urban + {word}` - uses the urban dictionary to search for the word. \n" +
- "`?shitpost` - Sends a random shitpost. (The shitpost API is broken.) \n " +
- "`?cat` - Cat :3 \n " +
- "`?neko` - Neko command \n " +
- "`?advice` - Gives the user a life Advice \n " +
- "`?quote` - Gives a random quote using yet another API. \n " +
- "`?gif {term}` - Allows the user to search for gifs using giphy (Beta) \n" +
- "`?avatar` - Sends the user Avatar (Beta) \n ";
- await ReplyAsync(helpMessage);
- }
- // End of the Help command.
-
- // Mod Help command
- [Command("mod-help")]
- public async Task ModHelp()
- {
- string helpMessage =
- "## List Of Available mod commands. \n" +
- "`?kick {Mention}` - Kicks the user \n" +
- "`?ban {mentions}` - Bans the User \n" +
- "`?unban {mention}` - Unbans the user. \n";
-
- await ReplyAsync(helpMessage);
- }
- // End of the mod-Help command
-
- // NSFW Help command:
- [Command("nsfw-help")]
- public async Task nsfwhelp()
- {
- await ReplyAsync("### Here are all the available NSFW commands: \n `?r34 {search}` - Searches rule34.xxx \n `?hentai` - Grabs a random hentai image \n ");
- }
- // End of the NSFW-HELP command
-
- // End of the help commands
-
- // Dm Commands (commands that dm the user in some way.):
-
- // Invite Command - Sends a invite in the DM
- [Command("invite")]
- public async Task Invite()
- {
- DMChannel DM = await Context.User.GetDMChannelAsync();
-
- if (DM == null)
- {
- await ReplyAsync("Could not open DM :(");
- return;
- }
-
- await DM.SendMessageAsync(
- "## Invite me! \n" +
- "If you're on app.haydar.dev, use this link: \n" +
- "https://app.haydar.dev/bot/01HA55V3K8B26T87TBKMZMWRKJ \n" +
- "But if you're on nightly.haydar.dev, use this link: \n" +
- "https://nightly.haydar.dev/bot/01HA55V3K8B26T87TBKMZMWRKJ \n" +
- "If you find any bugs, report them to the bot's creator. Thank you and bye!"
- );
- }
- // End of the Invite command
-
- // The Debug command.
- [Command("debug")]
- public async Task Debug()
- {
- DMChannel DM = await Context.User.GetDMChannelAsync();
-
- if (DM == null)
- {
- await ReplyAsync("Your code is so messed up that even DMs are broken :skull: wow");
- return;
- }
-
- try
- {
- // Send initial message
- await DM.SendMessageAsync("DMs work if you received this message.");
- await DM.SendMessageAsync("-----");
- await DM.SendMessageAsync("You should receive the ping of the bot and a shitpost");
-
- // Ping part
- var stopwatch = new Stopwatch();
- stopwatch.Start();
- await DM.SendMessageAsync("-----");
- stopwatch.Stop();
- var latency = stopwatch.ElapsedMilliseconds;
- await DM.SendMessageAsync($"The ping is: {latency}ms");
- await DM.SendMessageAsync("-----");
-
- // Shitpost part
- await SendRandomMeme(DM);
- await DM.SendMessageAsync("If you saw a Shitpost and the ping of the bot everything should work correctly.");
- }
- catch (Exception ex)
- {
- await DM.SendMessageAsync($"An error occurred: {ex.Message}");
- }
- }
-
- // The Shitpost Part.
- private async Task SendRandomMeme(DMChannel DM)
- {
- const string apiUrl = "https://api.thedailyshitpost.net/random";
-
- using (HttpClient client = new HttpClient())
- {
- try
- {
- HttpResponseMessage response = await client.GetAsync(apiUrl);
-
- if (response.IsSuccessStatusCode)
- {
- string memeJson = await response.Content.ReadAsStringAsync();
- dynamic memeObject = Newtonsoft.Json.JsonConvert.DeserializeObject(memeJson);
-
- string title = memeObject.title;
- string imageUrl = memeObject.url;
-
- await DM.SendMessageAsync($"{imageUrl}");
- }
- else
- {
- await DM.SendMessageAsync("Sorry, The Shitpost API is having issues again.");
- }
- }
- catch (Exception ex)
- {
- await DM.SendMessageAsync($"An error occurred while fetching a meme: {ex.Message}");
- }
- }
- }
-
- // End of the Debug command.
-
- // End of DM commands.
-
- // Debug commands.
-
- // Very Simple test Command
- [Command("test")]
- public async Task Test()
- {
- await ReplyAsync("Ig it works :tm:");
- }
-
- // Ping command.
- [Command("ping")]
- public async Task PingCommand()
- {
- var stopwatch = new Stopwatch();
- stopwatch.Start();
-
- await ReplyAsync("Ping...");
-
- stopwatch.Stop();
- var latency = stopwatch.ElapsedMilliseconds;
-
- await ReplyAsync($"Pong! (Latency: {latency}ms)");
- }
-
- // End of the Debug commands.
-
- // Fun commands:
-
- // Gif command
- [Command("gif")]
- public async Task GifCommand([Remainder] string keyword)
- {
- using (HttpClient client = new HttpClient())
- {
- IConfiguration Configuration = new ConfigurationBuilder()
- .SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
- .AddJsonFile("giphy.json")
- .Build();
-
- string apiKey = Configuration["GiphyApiKey"];
- string apiUrl = $"https://api.giphy.com/v1/gifs/search?api_key={apiKey}&q={keyword}&limit=1";
-
- HttpResponseMessage response = await client.GetAsync(apiUrl);
-
- if (response.IsSuccessStatusCode)
- {
- string gifJson = await response.Content.ReadAsStringAsync();
- JObject gifObject = JObject.Parse(gifJson);
-
- string gifUrl = gifObject["data"][0]["images"]["original"]["url"]?.ToString();
-
- if (!string.IsNullOrEmpty(gifUrl))
- {
- await Context.Channel.SendMessageAsync(gifUrl);
- }
- else
- {
- await Context.Channel.SendMessageAsync("Sorry, I couldn't find a GIF for that keyword.");
- }
- }
- else
- {
- await Context.Channel.SendMessageAsync("Sorry, I couldn't fetch a GIF at the moment. Please try again later.");
- }
- }
- }
- // End of the GIF commands
-
- // A Rock paper Scissors command.
- [Command("rps")]
- public async Task Rps([Remainder] string userChoice = null)
- {
- string[] options = { "rock", "paper", "scissors" };
- Random random = new Random();
- string botChoice = options[random.Next(options.Length)];
-
- if (userChoice == null)
- {
- await ReplyAsync("You need to provide a choice! Please choose from: rock, paper, scissors");
- return;
- }
-
- userChoice = userChoice.ToLower();
-
- if (options.Contains(userChoice))
- {
- if (userChoice == botChoice)
- {
- await ReplyAsync($"It's a tie! I chose {botChoice} too.");
- }
- else if ((userChoice == "rock" && botChoice == "scissors") ||
- (userChoice == "paper" && botChoice == "rock") ||
- (userChoice == "scissors" && botChoice == "paper"))
- {
- await ReplyAsync($"You win! I chose {botChoice}.");
- }
- else
- {
- await ReplyAsync($"You lose! I chose {botChoice}.");
- }
- }
- else
- {
- await ReplyAsync($"Invalid choice. Please choose from: {string.Join(", ", options)}");
- }
- }
- // End of the Rock paper scicors command
-
- // Dice command rolls a random number between 1 - 6 (Perfect for bets :troll")
- [Command("dice")]
- public async Task Dice()
- {
- var random = new Random();
- var result = random.Next(1, 7);
- await ReplyAsync($"You rolled a {result}!");
- }
- // End of the Dice command
-
- // Pick Command
- [Command("roll")]
- public async Task Roll([Remainder] string randnum = null)
- {
- if (randnum == null)
- {
- await ReplyAsync("Please specify a number to roll");
- }
- else if (int.TryParse(randnum, out int maxNumber) && maxNumber > 0)
- {
- try
- {
- var random = new Random();
- var result = random.Next(1, maxNumber + 1);
- await ReplyAsync($"You rolled a {result}!");
- }
- catch (Exception ex)
- {
- await ReplyAsync("An error occurred while rolling the dice.");
- }
- }
- else
- {
- await ReplyAsync("Please pick a valid number.");
- }
- }
- // End of the pick command
-
- // Very simple say command.
- private List blacklist = new List
-{
- "nigga", "nigger", "n i g g a", "fuck", "shit", "piss",
- "cunt", "dick", "fag", "faggot", "kys", "ky$",
-};
-
- [Command("say")]
- public async Task Say([Remainder] string text)
- {
- var user = Context.User.Username;
-
- foreach (var word in blacklist)
- {
- if (text.ToLower().Contains(word))
- {
- text = text.Replace(word, new string('*', word.Length));
- }
- }
-
- await ReplyAsync($"{user} said: {text}");
- }
- // End of the Say command
-
- // The coinflip command.
- [Command("coinflip")]
- public async Task Coinflip()
- {
- Random random = new Random();
- int result = random.Next(2);
-
- string side = (result == 0) ? "Heads" : "Tails";
-
- await ReplyAsync($"It's {side}!");
- }
- // End of the coinflip command.
-
- // End of the Fun commands.
-
- // Api commands
-
- // Advice command.
- [Command("advice")]
- public async Task Advice()
- {
- using (HttpClient client = new HttpClient())
- {
- try
- {
- string apiUrl = "https://api.adviceslip.com/advice";
- HttpResponseMessage response = await client.GetAsync(apiUrl);
-
- if (response.IsSuccessStatusCode)
- {
- string adviceJson = await response.Content.ReadAsStringAsync();
- JObject adviceObject = JObject.Parse(adviceJson);
-
- string advice = adviceObject["slip"]?["advice"]?.ToString();
-
- if (!string.IsNullOrEmpty(advice))
- {
- await ReplyAsync($"Advice: {advice}");
- }
- else
- {
- await ReplyAsync("Sorry, I couldn't fetch advice at the moment. Please try again later.");
- }
- }
- else
- {
- await ReplyAsync("Sorry, I couldn't fetch advice at the moment. Please try again later.");
- }
- }
- catch (Exception ex)
- {
- await ReplyAsync($"An error occurred: {ex.Message}");
- }
- }
- }
- // End of the Advice command
-
- // Dog fact command very simple very fun
- [Command("dogfact")]
- public async Task DogFact()
- {
- using (HttpClient client = new HttpClient())
- {
- try
- {
- string apiUrl = "http://dog-api.kinduff.com/api/facts";
- HttpResponseMessage response = await client.GetAsync(apiUrl);
-
- if (response.IsSuccessStatusCode)
- {
- string factsJson = await response.Content.ReadAsStringAsync();
- JObject factsObject = JObject.Parse(factsJson);
-
- if (factsObject["facts"] is JArray factsArray && factsArray.Count > 0)
- {
- Random random = new Random();
- int randomIndex = random.Next(factsArray.Count);
- string randomFact = factsArray[randomIndex].ToString();
-
- await ReplyAsync(randomFact);
- }
- else
- {
- await ReplyAsync("Sorry, I couldn't fetch a dog fact at the moment. Please try again later.");
- }
- }
- else
- {
- await ReplyAsync("Sorry, I couldn't fetch a dog fact at the moment. Please try again later.");
- }
- }
- catch (Exception ex)
- {
- await ReplyAsync($"An error occurred: {ex.Message}");
- }
- }
- }
- // End of the Dogfact command
-
- // Cat fact command very simple very fun
- [Command("catfact")]
- public async Task CatFact()
- {
- using (HttpClient client = new HttpClient())
- {
- try
- {
- string apiUrl = "http://meowfacts.herokuapp.com/";
- HttpResponseMessage response = await client.GetAsync(apiUrl);
-
- if (response.IsSuccessStatusCode)
- {
- string factJson = await response.Content.ReadAsStringAsync();
- JObject factObject = JObject.Parse(factJson);
-
- if (factObject["data"] != null)
- {
- string fact = factObject["data"].ToString();
- await ReplyAsync(fact);
- }
- else
- {
- await ReplyAsync("Sorry, I couldn't fetch a cat fact at the moment. Please try again later.");
- }
- }
- else
- {
- await ReplyAsync("Sorry, I couldn't fetch a cat fact at the moment. Please try again later.");
- }
- }
- catch (Exception ex)
- {
- await ReplyAsync($"An error occurred: {ex.Message}");
- }
- }
- }
- // End of the Cat fact command
-
- // Joke command
- [Command("joke")]
- public async Task Joke()
- {
- using (HttpClient client = new HttpClient())
- {
- try
- {
- string apiUrl = "https://v2.jokeapi.dev/joke/Any?type=twopart";
- HttpResponseMessage response = await client.GetAsync(apiUrl);
-
- if (response.IsSuccessStatusCode)
- {
- string jokeJson = await response.Content.ReadAsStringAsync();
- JObject jokeObject = JObject.Parse(jokeJson);
-
- string setup = jokeObject["setup"]?.ToString();
- string punchline = jokeObject["delivery"]?.ToString();
-
- if (!string.IsNullOrEmpty(setup) && !string.IsNullOrEmpty(punchline))
- {
- await ReplyAsync($"{setup}\n{punchline}");
- }
- else
- {
- await ReplyAsync("Sorry, I couldn't fetch a joke at the moment. Please try again later.");
- }
- }
- else
- {
- await ReplyAsync("Sorry, I couldn't fetch a joke at the moment. Please try again later.");
- }
- }
- catch (Exception ex)
- {
- await ReplyAsync($"An error occurred: {ex.Message}");
- }
- }
- }
- // End of the Joke command
-
- // Simple quote command
- [Command("quote")]
- public async Task Quote()
- {
- using (HttpClient client = new HttpClient())
- {
- try
- {
- string apiUrl = "https://api.quotable.io/random";
- HttpResponseMessage response = await client.GetAsync(apiUrl);
-
- if (response.IsSuccessStatusCode)
- {
- string quoteJson = await response.Content.ReadAsStringAsync();
- dynamic quoteObject = Newtonsoft.Json.JsonConvert.DeserializeObject(quoteJson);
-
- string content = quoteObject.content;
- string author = quoteObject.author;
-
- await ReplyAsync($"\"{content}\" - {author}");
- }
- else
- {
- await ReplyAsync("Sorry, I couldn't fetch a quote at the moment. Please try again later.");
- }
- }
- catch (Exception ex)
- {
- await ReplyAsync($"An error occurred: {ex.Message}");
- }
- }
- }
- // End of the qoute command
-
- // Fact command
- [Command("fact")]
- public async Task Fact()
- {
- using (HttpClient client = new HttpClient())
- {
- try
- {
- string apiUrl = "https://uselessfacts.jsph.pl/random.json?language=en";
- HttpResponseMessage response = await client.GetAsync(apiUrl);
-
- if (response.IsSuccessStatusCode)
- {
- string factJson = await response.Content.ReadAsStringAsync();
- dynamic factObject = Newtonsoft.Json.JsonConvert.DeserializeObject(factJson);
-
- string fact = factObject.text;
- await ReplyAsync(fact);
- }
- else
- {
- await ReplyAsync("Sorry, I couldn't fetch a fact at the moment. Please try again later.");
- }
- }
- catch (Exception ex)
- {
- await ReplyAsync($"An error occurred: {ex.Message}");
- }
- }
- }
- // End of the fact command
-
- // Urban command
- [Command("urban")]
- public async Task Urban([Remainder] string term)
- {
- using (HttpClient client = new HttpClient())
- {
- string apiUrl = $"https://api.urbandictionary.com/v0/define?term={term}";
- HttpResponseMessage response = await client.GetAsync(apiUrl);
-
- if (response.IsSuccessStatusCode)
- {
- string urbanJson = await response.Content.ReadAsStringAsync();
- dynamic urbanObject = Newtonsoft.Json.JsonConvert.DeserializeObject(urbanJson);
-
- if (urbanObject.list.Count > 0)
- {
- int maxDefinitions = 3;
-
- for (int i = 0; i < Math.Min(maxDefinitions, urbanObject.list.Count); i++)
- {
- string definition = urbanObject.list[i].definition;
- string formattedMessage = $"```\nTerm: {term}\nDefinition {i + 1}:\n{definition}\n```";
- await ReplyAsync(formattedMessage);
- }
- }
- else
- {
- await ReplyAsync("Sorry, I couldn't find a definition for that term.");
- }
- }
- else
- {
- await ReplyAsync("Sorry, I couldn't fetch a definition at the moment. Please try again later.");
- }
- }
- }
- // End of the Urban command
-
- // Shitpost command
- [Command("shitpost")]
- public async Task Shitpost()
- {
- using (HttpClient client = new HttpClient())
- {
- try
- {
- string apiUrl = "https://api.thedailyshitpost.net/random";
- HttpResponseMessage response = await client.GetAsync(apiUrl);
-
- if (response.IsSuccessStatusCode)
- {
- string memeJson = await response.Content.ReadAsStringAsync();
- dynamic memeObject = Newtonsoft.Json.JsonConvert.DeserializeObject(memeJson);
-
- string title = memeObject.title;
- string imageUrl = memeObject.url;
-
- await ReplyAsync(imageUrl);
- }
- else
- {
- await ReplyAsync("Sorry, I couldn't fetch a meme at the moment. Please try again later.");
- }
- }
- catch (Exception ex)
- {
- await ReplyAsync($"An error occurred: {ex.Message}");
- }
- }
- }
- // End of the shitpost command
-
- // Cat command.
- [Command("cat")]
- public async Task Cat()
- {
- using (HttpClient client = new HttpClient())
- {
- try
- {
- string apiUrl = "https://api.thecatapi.com/v1/images/search";
- HttpResponseMessage response = await client.GetAsync(apiUrl);
-
- if (response.IsSuccessStatusCode)
- {
- string catJson = await response.Content.ReadAsStringAsync();
- dynamic catObject = Newtonsoft.Json.JsonConvert.DeserializeObject(catJson);
-
- string imageUrl = catObject[0]?.url;
-
- if (!string.IsNullOrEmpty(imageUrl))
- {
- await ReplyAsync(imageUrl);
- }
- else
- {
- await ReplyAsync("Sorry, I couldn't fetch a cat image at the moment. Please try again later.");
- }
- }
- else
- {
- await ReplyAsync("Sorry, I couldn't fetch a cat image at the moment. Please try again later.");
- }
- }
- catch (Exception ex)
- {
- await ReplyAsync($"An error occurred: {ex.Message}");
- }
- }
- }
- // End of the cat command
-
- // Neko command
- [Command("neko")]
- public async Task Neko()
- {
- try
- {
- using (HttpClient client = new HttpClient())
- {
- string apiUrl = "https://nekos.life/api/v2/img/neko";
- HttpResponseMessage response = await client.GetAsync(apiUrl);
-
- if (response.IsSuccessStatusCode)
- {
- string nekoJson = await response.Content.ReadAsStringAsync();
- JObject nekoObject = JObject.Parse(nekoJson);
-
- string imageUrl = nekoObject["url"]?.ToString();
-
- if (!string.IsNullOrEmpty(imageUrl))
- {
- await ReplyAsync(imageUrl);
- }
- else
- {
- await ReplyAsync("Sorry, I couldn't fetch a neko at the moment. Please try again later.");
- }
- }
- else
- {
- await ReplyAsync("Sorry, I couldn't fetch a neko at the moment. Please try again later.");
- }
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine($"Error in Neko command: {ex.Message}");
- await ReplyAsync("An error occurred while fetching the neko. Please try again later.");
- }
- }
- // End of neko command
-
- // The End of the API commands.
-
- // Misc Commands:
-
- // Give the credits of the bot
- [Command("credits")]
- public async Task Credits()
- {
- await ReplyAsync("This bot is made using revoltsharp by Purplebored known as Kniaż Jarema on nightly");
- }
- // End of the Credits command
-
- // Avatar command
- [Command("avatar")]
- public async Task AvatarCommand()
- {
- var user = Context.Message.Author.GetAvatarUrl();
- var avatarUrl = $"{user}";
-
- await Context.Channel.SendMessageAsync($"Your avatar: {avatarUrl}");
- }
- // End of the Avatar command
-
- // Calculate command
- [Command("calculate")]
- public async Task Calculate(string num1String, string operation, string num2String)
- {
- if (!double.TryParse(num1String, NumberStyles.Any, CultureInfo.InvariantCulture, out double num1) ||
- !double.TryParse(num2String, NumberStyles.Any, CultureInfo.InvariantCulture, out double num2))
- {
- await ReplyAsync("Error: Invalid input. Please provide valid numbers.");
- return;
- }
-
- double result = 0;
-
- switch (operation)
- {
- case "+":
- result = num1 + num2;
- break;
- case "-":
- result = num1 - num2;
- break;
- case "*":
- result = num1 * num2;
- break;
- case "/":
- if (num2 != 0) // Check for division by zero
- {
- result = num1 / num2;
- }
- else
- {
- await ReplyAsync("Error: Division by zero is not allowed.");
- return;
- }
-
- break;
- default:
- await ReplyAsync("Invalid operation. Please use +, -, *, or /.");
- return;
- }
-
- await ReplyAsync($"Result: {result}");
- }
- // End of the Calculat command.
-
- // End of the misc commands
-
- // Mod Commands
-
- // Stuff needed to make these commands work.
- private string RemoveMention(string mention)
- {
- return mention.Replace("<@", "").Replace(">", "");
- }
-
- private RevoltClient Client;
-
- // Stats command
- [Command("stats")]
- public async Task GetStats()
- {
- try
- {
- IReadOnlyCollection result1 = await Context.Server.GetMembersAsync();
- int num2 = result1.Count;
- IReadOnlyCollection result2 = await Context.Server.GetMembersAsync(true);
- int num3 = result2.Count;
- await ReplyAsync($"### Stats:\n\n### Member count: {num2}\n### Online member count: {num3}\n");
- }
- catch (Exception ex)
- {
- await ReplyAsync($"An error occurred: {ex.Message}");
- }
- }
-
- // Ban Command
- [Command("ban")]
- public async Task BanUser([Remainder] string args)
- {
- try
- {
- string userId = RemoveMention(args);
- await Context.Server.BanMemberAsync(userId, "Banned via command.");
- await ReplyAsync("### Ban\nwhomp whomp.");
- }
- catch
- {
- await ReplyAsync("### ERROR\nInvalid Mention or Bot Permissions.");
- }
- }
-
- // Unban Command
- [Command("unban")]
- public async Task UnbanUser([Remainder] string args)
- {
- try
- {
- string userId = RemoveMention(args);
- await Context.Server.UnBanMemberAsync(userId);
- await ReplyAsync("### Unbanned\nVery sadly a mod had a change of heart.");
- }
- catch
- {
- await ReplyAsync("### ERROR\nInvalid Mention or Bot Permissions.");
- }
- }
-
- // Kick Command
- [Command("kick")]
- public async Task KickUser([Remainder] string args)
- {
- try
- {
- string userId = RemoveMention(args);
- await Context.Server.KickMemberAsync(userId);
- await ReplyAsync("### Kicked\nAnd he's gone.");
- }
- catch
- {
- await ReplyAsync("### ERROR\nInvalid Mention or Bot Permissions.");
- }
- }
-
- // End of mod commands
-
- // NSFW COMMANDS
-
- // R34 command.
- [Command("r34")]
- public async Task ExampleCommand([Remainder] string query = null)
- {
- try
- {
- if (string.IsNullOrWhiteSpace(query))
- {
- await Context.Channel.SendMessageAsync("Please provide a search query. Usage: ?r34 {searchquery}");
- return;
- }
-
- if (!(Context.Channel is TextChannel textChannel) || !textChannel.IsNsfw)
- {
- await Context.Channel.SendMessageAsync("This command is only allowed in NSFW channels. So go to a NSFW channel to get your NSFW smh");
- return;
- }
-
- using (HttpClient httpClient = new HttpClient())
- {
- string apiUrl = $"https://api.rule34.xxx/index.php?page=dapi&s=post&q=index&limit=1&json=1&tags={query}";
-
- HttpResponseMessage response = await httpClient.GetAsync(apiUrl);
-
- if (response.IsSuccessStatusCode)
- {
- string jsonResult = await response.Content.ReadAsStringAsync();
- dynamic data = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonResult);
-
- if (data != null && data.Count > 0 && data[0].file_url != null)
- {
- string imageUrl = data[0].file_url;
- await Context.Channel.SendMessageAsync(imageUrl);
- }
- else
- {
- await Context.Channel.SendMessageAsync("No images found.");
- }
- }
- else
- {
- await Context.Channel.SendMessageAsync("Sorry, I couldn't fetch an image at the moment. Please try again later.");
- }
- }
- }
- catch (Exception ex)
- {
- await Context.Channel.SendMessageAsync($"An error occurred: {ex.Message}");
- }
- }
-
- // Hentai command.
- [Command("hentai")]
- public async Task Hentai()
- {
- try
- {
- if (!(Context.Channel is TextChannel textChannel) || !textChannel.IsNsfw)
- {
- await Context.Channel.SendMessageAsync("This command is only allowed in NSFW channels. So go to a NSFW channel to get your NSFW smh");
- return;
- }
- using (HttpClient client = new HttpClient())
- {
- string apiUrl = "https://nekobot.xyz/api/image?type=hneko";
- HttpResponseMessage response = await client.GetAsync(apiUrl);
-
- if (response.IsSuccessStatusCode)
- {
- string nekoJson = await response.Content.ReadAsStringAsync();
- dynamic nekoObject = Newtonsoft.Json.JsonConvert.DeserializeObject(nekoJson);
-
- string imageUrl = nekoObject["message"];
-
- await ReplyAsync(imageUrl);
- }
- else
- {
- await ReplyAsync("Sorry, I couldn't fetch a neko image at the moment. Please try again later.");
- }
- }
- }
- catch (Exception ex)
- {
- await Context.Channel.SendMessageAsync($"An error occurred: {ex.Message}");
- }
- }
- // End of NSFW commands
- // End of the Bot
-}
\ No newline at end of file
diff --git a/README.md b/README.md
index 405b714..208e52c 100644
--- a/README.md
+++ b/README.md
@@ -1,33 +1,3 @@
-# Chrobry
+# Chrobry-Discord
-A king among revolt bots 👑
-
-.png)
-
-## Features
-
-- [x] Ban, Unban, Kick Command.
-
-- [x] Open source
-
-- [x] NSFW Commands
-
-- [x] Fun Commands
-
-## Features which gonna be added in the future.
-
-- [ ] Music Commands.
-
-- [ ] Better Mod commands
-
-- [ ] Warn system
-
-- [ ] Economy System.
-
-# License
-
-This project is licensed under the terms of the GPL 3.0 license.
-
-## Contributing
-
-Contributions to this project are welcome! Simply fork the repository and create a pull request with your proposed changes. preferably also create a issue on codeberg first.
+Truly a kind among Discord bots 👑
\ No newline at end of file
diff --git a/bot.rb b/bot.rb
new file mode 100644
index 0000000..9fd1150
--- /dev/null
+++ b/bot.rb
@@ -0,0 +1,174 @@
+require 'discordrb'
+require 'open-uri'
+require 'json'
+require 'dotenv/load'
+
+TOKEN = ENV['BOT_TOKEN']
+bot = Discordrb::Bot.new(token: TOKEN)
+
+# Help command
+bot.message(content: '!help') do |event|
+ embed = Discordrb::Webhooks::Embed.new(
+ title: 'Available Categories',
+ description: 'To get help for a specific category, use `!help-category_name`. (everything needs to be in lower case.)',
+ color: 800080
+ )
+ embed.add_field(name: 'help-fun', value: 'Fun commands')
+ embed.add_field(name: 'help-mod', value: 'Mod commands')
+ # Add more categories as needed
+
+ event.channel.send_embed('', embed)
+end
+
+# Fun help command
+bot.message(content:('!help-fun')) do |event|
+ # Provide help for fun commands in this category
+ event.respond("Here are the fun commands: !joke, !sploot, !roast, !dogfact, !rps, !shitpost")
+end
+
+# Mod help command
+bot.message(content:('!help-mod')) do |event|
+ # Provide help for mod commands in this category
+ event.respond("Here are the mod commands: !kick @user, !purge ")
+end
+# End of help command
+
+
+# Simple joke command.
+bot.message(content: '!joke') do |event|
+ begin
+ response = JSON.parse(open('https://v2.jokeapi.dev/joke/Any?type=twopart').read)
+ setup = response['setup']
+ punchline = response['delivery']
+ event.respond(setup)
+ event.respond(punchline)
+ rescue StandardError => e
+ event.respond("Sorry, I couldn't fetch a joke at the moment. Please try again later.")
+ puts "Error fetching joke: #{e.message}"
+ end
+end
+# End of Joke Command.
+
+# Sploot
+bot.message(content: '!sploot') do |event|
+ # You can replace this URL with any other source of sploot images.
+ sploot_image_url = 'https://cdn.discordapp.com/attachments/1030188681472000120/1152930346229301338/YUVfoERh3CiqXUdc9a9qwZ9paHWPf4GETsIslDBExFqsRVGds9pk9MicwErTq1N8sowFpUyO5Q9oVgs640-nd-v1.png'
+
+ event.respond(sploot_image_url)
+end
+# End of Sploot Command
+
+# Roast command.
+bot.message(content: '!roast') do |event|
+ roasts = [
+ "You must be a parking ticket, because you've got 'Fine' written all over you.",
+ "If you were any more inbred, you'd be a sandwich.",
+ "I'd say you're dumb as a rock, but at least a rock can serve a purpose.",
+ "Is your ass jealous of the amount of shit that comes out of your mouth?",
+ "You're not pretty enough to be this stupid."
+ ]
+ event.respond(roasts.sample)
+end
+
+# Kick Command
+bot.message(content: /^!kick\s<@(\d+)>$/) do |event|
+ user_id = event.content.match(/^!kick\s<@(\d+)>$/)[1].to_i
+
+ # Check if the user has the necessary permissions to kick members
+ if event.author.permission?(:kick_members)
+ begin
+ user_to_kick = event.server.member(user_id)
+ user_to_kick.kick
+ event.respond("Successfully kicked <@#{user_id}>.")
+ rescue StandardError => e
+ event.respond("Error: #{e.message}")
+ end
+ else
+ event.respond("You do not have permission to kick members.")
+ end
+end
+# End of the kick command
+
+# Ping Command
+bot.message(content: '!ping') do |event|
+ start_time = Time.now
+ msg = event.respond('Pong!')
+ end_time = Time.now
+
+ ping = ((end_time - start_time) * 1000).to_i
+ msg.edit("Pong! Latency is #{ping} ms.")
+end
+# End of ping command.
+
+# Purge Command.
+bot.message(content: /^!purge (\d{1,2})$/) do |event|
+ num_to_delete = event.message.content.match(/^!purge (\d{1,2})$/)[1].to_i
+
+ if num_to_delete >= 1 && num_to_delete <= 100
+ event.channel.prune(num_to_delete + 1) # Adding 1 to also delete the command message
+ else
+ event.respond("Please specify a number between 1 and 100.")
+ end
+end
+# End of Purge Command.
+
+# Dogfact Command.
+def fetch_dog_fact
+ url = URI.parse('https://dog-api.kinduff.com/api/facts')
+ response = Net::HTTP.get(url)
+ JSON.parse(response)['facts'].first
+end
+
+bot.message(content: /^!dogfact$/) do |event|
+ dog_fact = fetch_dog_fact
+ event.respond("#{dog_fact}")
+end
+# End of Dogfact
+
+# RPS Command.
+valid_choices = ['rock', 'paper', 'scissors']
+
+bot.message(content: /^!rps (rock|paper|scissors)$/) do |event|
+ user_choice = event.message.content.match(/^!rps (rock|paper|scissors)$/)[1]
+
+ if valid_choices.include?(user_choice)
+ bot_choice = valid_choices.sample
+
+ result = case [user_choice, bot_choice]
+ when ['rock', 'scissors'], ['paper', 'rock'], ['scissors', 'paper']
+ "You win!"
+ when ['scissors', 'rock'], ['rock', 'paper'], ['paper', 'scissors']
+ "I win!"
+ else
+ "It's a tie!"
+ end
+
+ event.respond("You chose #{user_choice}, I chose #{bot_choice}. #{result}")
+ else
+ event.respond("Please choose either rock, paper, or scissors!")
+ end
+end
+# End of RPS command
+
+# Begining of the Shitpost command.
+bot.message(content: '!shitpost') do |event|
+ begin
+ uri = URI.parse('https://api.thedailyshitpost.net/random')
+ response = Net::HTTP.get_response(uri)
+
+ if response.is_a?(Net::HTTPSuccess)
+ meme_json = JSON.parse(response.body)
+ title = meme_json['title']
+ image_url = meme_json['url']
+ event.respond("#{title}: #{image_url}")
+ else
+ event.respond("Sorry, I couldn't fetch a meme at the moment. 99% chance that ratelimit or Shitpost API dead.")
+ end
+ rescue StandardError => e
+ event.respond("An error occurred: #{e.message}")
+ end
+end
+# End of the Shitpost command.
+
+bot.run
+