diff --git a/.env-default b/.env-default
new file mode 100644
index 0000000..cc2f8fa
--- /dev/null
+++ b/.env-default
@@ -0,0 +1,4 @@
+DISCORD_BOT_TOKEN=bot_token_here
+DISCORD_BOT_ID=bot_id_here
+SSL_CERT_PATH=pfx_path_here
+SSL_CERT_PASS=pfx_passphase_here
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 1fe633e..6a7d6d8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,390 +1,130 @@
-## 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/master/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/
-[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/
-
-# 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
+# Logs
+logs
*.log
-*.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
-
-# 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/
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+lerna-debug.log*
+.pnpm-debug.log*
+
+# Diagnostic reports (https://nodejs.org/api/report.html)
+report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
+
+# Runtime data
+pids
+*.pid
+*.seed
+*.pid.lock
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
-# Visual Studio 6 build log
-*.plg
+# Coverage directory used by tools like istanbul
+coverage
+*.lcov
-# Visual Studio 6 workspace options file
-*.opt
+# nyc test coverage
+.nyc_output
-# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
-*.vbw
+# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
-# Visual Studio LightSwitch build output
-**/*.HTMLClient/GeneratedArtifacts
-**/*.DesktopClient/GeneratedArtifacts
-**/*.DesktopClient/ModelManifest.xml
-**/*.Server/GeneratedArtifacts
-**/*.Server/ModelManifest.xml
-_Pvt_Extensions
+# Bower dependency directory (https://bower.io/)
+bower_components
-# Paket dependency manager
-.paket/paket.exe
-paket-files/
+# node-waf configuration
+.lock-wscript
+
+# Compiled binary addons (https://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directories
+node_modules/
+jspm_packages/
-# FAKE - F# Make
-.fake/
+# Snowpack dependency directory (https://snowpack.dev/)
+web_modules/
-# CodeRush personal settings
-.cr/personal
+# TypeScript cache
+*.tsbuildinfo
-# Python Tools for Visual Studio (PTVS)
-__pycache__/
-*.pyc
+# Optional npm cache directory
+.npm
-# Cake - Uncomment if you are using it
-# tools/**
-# !tools/packages.config
+# Optional eslint cache
+.eslintcache
-# Tabs Studio
-*.tss
+# Optional stylelint cache
+.stylelintcache
-# Telerik's JustMock configuration file
-*.jmconfig
+# Microbundle cache
+.rpt2_cache/
+.rts2_cache_cjs/
+.rts2_cache_es/
+.rts2_cache_umd/
-# BizTalk build output
-*.btp.cs
-*.btm.cs
-*.odx.cs
-*.xsd.cs
+# Optional REPL history
+.node_repl_history
-# OpenCover UI analysis results
-OpenCover/
+# Output of 'npm pack'
+*.tgz
-# Azure Stream Analytics local run output
-ASALocalRun/
+# Yarn Integrity file
+.yarn-integrity
-# MSBuild Binary and Structured Log
-*.binlog
+# dotenv environment variable files
+.env
+.env.development.local
+.env.test.local
+.env.production.local
+.env.local
-# NVidia Nsight GPU debugger configuration file
-*.nvuser
+# parcel-bundler cache (https://parceljs.org/)
+.cache
+.parcel-cache
-# MFractors (Xamarin productivity tool) working folder
-.mfractor/
+# Next.js build output
+.next
+out
-# Local History for Visual Studio
-.localhistory/
+# Nuxt.js build / generate output
+.nuxt
+dist
-# BeatPulse healthcheck temp database
-healthchecksdb
+# Gatsby files
+.cache/
+# Comment in the public line in if your project uses Gatsby and not Next.js
+# https://nextjs.org/blog/next-9-1#public-directory-support
+# public
-# Backup folder for Package Reference Convert tool in Visual Studio 2017
-MigrationBackup/
+# vuepress build output
+.vuepress/dist
-# Ionide (cross platform F# VS Code tools) working folder
-.ionide/
+# vuepress v2.x temp and cache directory
+.temp
+.cache
-# Common IntelliJ Platform excludes
+# Docusaurus cache and generated files
+.docusaurus
-# User specific
-**/.idea/**/workspace.xml
-**/.idea/**/tasks.xml
-**/.idea/shelf/*
-**/.idea/dictionaries
-**/.idea/httpRequests/
+# Serverless directories
+.serverless/
-# Sensitive or high-churn files
-**/.idea/**/dataSources/
-**/.idea/**/dataSources.ids
-**/.idea/**/dataSources.xml
-**/.idea/**/dataSources.local.xml
-**/.idea/**/sqlDataSources.xml
-**/.idea/**/dynamic.xml
+# FuseBox cache
+.fusebox/
-# Rider
-# Rider auto-generates .iml files, and contentModel.xml
-**/.idea/**/*.iml
-**/.idea/**/contentModel.xml
-**/.idea/**/modules.xml
-.idea
+# DynamoDB Local files
+.dynamodb/
-*.suo
-*.user
-.vs/
-[Bb]in/
-[Oo]bj/
-_UpgradeReport_Files/
-[Pp]ackages/
-
-Thumbs.db
-Desktop.ini
-.DS_Store
+# TernJS port file
+.tern-port
+# Stores VSCode versions used for testing VSCode extensions
+.vscode-test
-# Custom ignores
-DiscordBot/config.json
\ No newline at end of file
+# yarn v2
+.yarn/cache
+.yarn/unplugged
+.yarn/build-state.yml
+.yarn/install-state.gz
+.pnp.*
\ No newline at end of file
diff --git a/Discord.Addons.Interactive.dll b/Discord.Addons.Interactive.dll
deleted file mode 100644
index 9a25c9f..0000000
Binary files a/Discord.Addons.Interactive.dll and /dev/null differ
diff --git a/DiscordBot.sln b/DiscordBot.sln
deleted file mode 100644
index afb6f67..0000000
--- a/DiscordBot.sln
+++ /dev/null
@@ -1,31 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.29721.120
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DiscordBot", "DiscordBot\DiscordBot.csproj", "{80385988-3A9A-010D-0F8C-0C7977AB44F8}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Debug|x86 = Debug|x86
- Release|Any CPU = Release|Any CPU
- Release|x86 = Release|x86
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {80385988-3A9A-010D-0F8C-0C7977AB44F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {80385988-3A9A-010D-0F8C-0C7977AB44F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {80385988-3A9A-010D-0F8C-0C7977AB44F8}.Debug|x86.ActiveCfg = Debug|x86
- {80385988-3A9A-010D-0F8C-0C7977AB44F8}.Debug|x86.Build.0 = Debug|x86
- {80385988-3A9A-010D-0F8C-0C7977AB44F8}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {80385988-3A9A-010D-0F8C-0C7977AB44F8}.Release|Any CPU.Build.0 = Release|Any CPU
- {80385988-3A9A-010D-0F8C-0C7977AB44F8}.Release|x86.ActiveCfg = Release|x86
- {80385988-3A9A-010D-0F8C-0C7977AB44F8}.Release|x86.Build.0 = Release|x86
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {C5E8BCC8-9716-424E-91CB-A33821D053DC}
- EndGlobalSection
-EndGlobal
diff --git a/DiscordBot/DiscordBot.csproj b/DiscordBot/DiscordBot.csproj
deleted file mode 100644
index 7f34c98..0000000
--- a/DiscordBot/DiscordBot.csproj
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
- Exe
- DiscordBot
- net5.0
- DiscordBot
- AnyCPU;x86
- DiscordBot.Program
- $(DefaultItemExcludes);$(ProjectDir)**\*.vb
- latest
-
-
-
-
-
-
-
-
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
-
-
-
-
-
- PreserveNewest
-
-
-
-
diff --git a/DiscordBot/Helper/ExtensionMethods.cs b/DiscordBot/Helper/ExtensionMethods.cs
deleted file mode 100644
index 7cd0403..0000000
--- a/DiscordBot/Helper/ExtensionMethods.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using Discord.Commands;
-namespace DiscordBot.Helper
-{
- public static class ExtensionMethods
- {
- public static int CustomPriority(this CommandInfo commandInfo)
- {
- return commandInfo.Name switch
- {
- "help" => 0,
- "auth" => 1,
- "unauth" => 2,
- "rec" => 3,
- "leave" => 4,
- "notify" => 5,
- "dnotify" => 6,
- "start" => 7,
- "stop" => 8,
- _ => 99
- };
- }
- }
-}
\ No newline at end of file
diff --git a/DiscordBot/Migrations/20210807145627_movingtoef.Designer.cs b/DiscordBot/Migrations/20210807145627_movingtoef.Designer.cs
deleted file mode 100644
index e25ed5b..0000000
--- a/DiscordBot/Migrations/20210807145627_movingtoef.Designer.cs
+++ /dev/null
@@ -1,102 +0,0 @@
-//
-using DiscordBot.Models;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-
-namespace DiscordBot.Migrations
-{
- [DbContext(typeof(DatabaseContext))]
- [Migration("20210807145627_movingtoef")]
- partial class movingtoef
- {
- protected override void BuildTargetModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder
- .HasAnnotation("ProductVersion", "5.0.8");
-
- modelBuilder.Entity("DiscordBot.Models.Auth", b =>
- {
- b.Property("ID")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("IP")
- .HasColumnType("TEXT");
-
- b.Property("Serverid")
- .HasColumnType("INTEGER");
-
- b.Property("Token")
- .HasColumnType("TEXT");
-
- b.HasKey("ID");
-
- b.ToTable("Auth");
- });
-
- modelBuilder.Entity("DiscordBot.Models.Notify", b =>
- {
- b.Property("ID")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("Channelid")
- .HasColumnType("INTEGER");
-
- b.Property("Serverid")
- .HasColumnType("INTEGER");
-
- b.HasKey("ID");
-
- b.ToTable("Notify");
- });
-
- modelBuilder.Entity("DiscordBot.Models.OnHold", b =>
- {
- b.Property("ID")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("IP")
- .HasColumnType("TEXT");
-
- b.Property("Token")
- .HasColumnType("TEXT");
-
- b.HasKey("ID");
-
- b.ToTable("OnHold");
- });
-
- modelBuilder.Entity("DiscordBot.Models.OnJoin", b =>
- {
- b.Property("ID")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("Channelid")
- .HasColumnType("INTEGER");
-
- b.Property("Messageid")
- .HasColumnType("INTEGER");
-
- b.Property("Roleid")
- .HasColumnType("INTEGER");
-
- b.Property("Serverid")
- .HasColumnType("INTEGER");
-
- b.Property("sevent")
- .HasColumnType("INTEGER");
-
- b.HasKey("ID");
-
- b.ToTable("OnJoin");
- });
-#pragma warning restore 612, 618
- }
- }
-}
diff --git a/DiscordBot/Migrations/20210807145627_movingtoef.cs b/DiscordBot/Migrations/20210807145627_movingtoef.cs
deleted file mode 100644
index 91b7de5..0000000
--- a/DiscordBot/Migrations/20210807145627_movingtoef.cs
+++ /dev/null
@@ -1,85 +0,0 @@
-using Microsoft.EntityFrameworkCore.Migrations;
-
-namespace DiscordBot.Migrations
-{
- public partial class movingtoef : Migration
- {
- protected override void Up(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.CreateTable(
- name: "Auth",
- columns: table => new
- {
- ID = table.Column(type: "INTEGER", nullable: false)
- .Annotation("Sqlite:Autoincrement", true),
- Serverid = table.Column(type: "INTEGER", nullable: false),
- Token = table.Column(type: "TEXT", nullable: true),
- IP = table.Column(type: "TEXT", nullable: true)
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_Auth", x => x.ID);
- });
-
- migrationBuilder.CreateTable(
- name: "Notify",
- columns: table => new
- {
- ID = table.Column(type: "INTEGER", nullable: false)
- .Annotation("Sqlite:Autoincrement", true),
- Serverid = table.Column(type: "INTEGER", nullable: false),
- Channelid = table.Column(type: "INTEGER", nullable: false)
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_Notify", x => x.ID);
- });
-
- migrationBuilder.CreateTable(
- name: "OnHold",
- columns: table => new
- {
- ID = table.Column(type: "INTEGER", nullable: false)
- .Annotation("Sqlite:Autoincrement", true),
- Token = table.Column(type: "TEXT", nullable: true),
- IP = table.Column(type: "TEXT", nullable: true)
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_OnHold", x => x.ID);
- });
-
- migrationBuilder.CreateTable(
- name: "OnJoin",
- columns: table => new
- {
- ID = table.Column(type: "INTEGER", nullable: false)
- .Annotation("Sqlite:Autoincrement", true),
- Serverid = table.Column(type: "INTEGER", nullable: false),
- Channelid = table.Column(type: "INTEGER", nullable: false),
- Roleid = table.Column(type: "INTEGER", nullable: false),
- sevent = table.Column(type: "INTEGER", nullable: false),
- Messageid = table.Column(type: "INTEGER", nullable: false)
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_OnJoin", x => x.ID);
- });
- }
-
- protected override void Down(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.DropTable(
- name: "Auth");
-
- migrationBuilder.DropTable(
- name: "Notify");
-
- migrationBuilder.DropTable(
- name: "OnHold");
-
- migrationBuilder.DropTable(
- name: "OnJoin");
- }
- }
-}
diff --git a/DiscordBot/Migrations/DatabaseContextModelSnapshot.cs b/DiscordBot/Migrations/DatabaseContextModelSnapshot.cs
deleted file mode 100644
index a2209fb..0000000
--- a/DiscordBot/Migrations/DatabaseContextModelSnapshot.cs
+++ /dev/null
@@ -1,100 +0,0 @@
-//
-using DiscordBot.Models;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-
-namespace DiscordBot.Migrations
-{
- [DbContext(typeof(DatabaseContext))]
- partial class DatabaseContextModelSnapshot : ModelSnapshot
- {
- protected override void BuildModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder
- .HasAnnotation("ProductVersion", "5.0.8");
-
- modelBuilder.Entity("DiscordBot.Models.Auth", b =>
- {
- b.Property("ID")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("IP")
- .HasColumnType("TEXT");
-
- b.Property("Serverid")
- .HasColumnType("INTEGER");
-
- b.Property("Token")
- .HasColumnType("TEXT");
-
- b.HasKey("ID");
-
- b.ToTable("Auth");
- });
-
- modelBuilder.Entity("DiscordBot.Models.Notify", b =>
- {
- b.Property("ID")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("Channelid")
- .HasColumnType("INTEGER");
-
- b.Property("Serverid")
- .HasColumnType("INTEGER");
-
- b.HasKey("ID");
-
- b.ToTable("Notify");
- });
-
- modelBuilder.Entity("DiscordBot.Models.OnHold", b =>
- {
- b.Property("ID")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("IP")
- .HasColumnType("TEXT");
-
- b.Property("Token")
- .HasColumnType("TEXT");
-
- b.HasKey("ID");
-
- b.ToTable("OnHold");
- });
-
- modelBuilder.Entity("DiscordBot.Models.OnJoin", b =>
- {
- b.Property("ID")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("Channelid")
- .HasColumnType("INTEGER");
-
- b.Property("Messageid")
- .HasColumnType("INTEGER");
-
- b.Property("Roleid")
- .HasColumnType("INTEGER");
-
- b.Property("Serverid")
- .HasColumnType("INTEGER");
-
- b.Property("sevent")
- .HasColumnType("INTEGER");
-
- b.HasKey("ID");
-
- b.ToTable("OnJoin");
- });
-#pragma warning restore 612, 618
- }
- }
-}
diff --git a/DiscordBot/Models/Database.cs b/DiscordBot/Models/Database.cs
deleted file mode 100644
index 6adf7a5..0000000
--- a/DiscordBot/Models/Database.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel.DataAnnotations;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace DiscordBot.Models
-{
- public class Auth
- {
- [Key]
- public int ID { get; set; }
- public ulong Serverid { get; set; }
- public string Token { get; set; }
- public string IP { get; set; }
- }
- public class Notify
- {
- [Key]
- public int ID { get; set; }
- public ulong Serverid { get; set; }
- public ulong Channelid { get; set; }
- }
- public class OnJoin
- {
- [Key]
- public int ID { get; set; }
- public ulong Serverid { get; set; }
- public ulong Channelid { get; set; }
- public ulong Roleid { get; set; }
- public int sevent { get; set; }
- public ulong Messageid { get; set; }
- }
- public class OnHold
- {
- [Key]
- public int ID { get; set; }
- public string Token { get; set; }
- public string IP { get; set; }
- }
-}
diff --git a/DiscordBot/Models/DatabaseContext.cs b/DiscordBot/Models/DatabaseContext.cs
deleted file mode 100644
index c4cff50..0000000
--- a/DiscordBot/Models/DatabaseContext.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using Microsoft.EntityFrameworkCore;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace DiscordBot.Models
-{
- public class DatabaseContext : DbContext
- {
-
- protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
- {
- optionsBuilder.UseSqlite($@"Data source= {AppDomain.CurrentDomain.BaseDirectory + "Fork.db"}");
- }
- public DbSet Auth { get; set; }
- public DbSet Notify { get; set; }
- public DbSet OnJoin { get; set; }
- public DbSet OnHold { get; set; }
- }
-}
diff --git a/DiscordBot/Modules/BotTools.cs b/DiscordBot/Modules/BotTools.cs
deleted file mode 100644
index d18ec68..0000000
--- a/DiscordBot/Modules/BotTools.cs
+++ /dev/null
@@ -1,797 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Discord;
-using Discord.Commands;
-using Discord.WebSocket;
-using DiscordBot.Helper;
-using DiscordBot.Models;
-using Interactivity;
-
-
-namespace DiscordBot
-{
- public class BotTools : ModuleBase
- {
- private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
- public InteractivityService Interactivity { get; set; }
- ///
- /// Int 0 is to modify the message, int 1 is to send a new message
- ///
- public static async Task NotificationControlAsync(ulong messageid, ulong channelid, string msg, int status,
- int num = 0)
- {
- try
- {
- if (num == 0)
- {
- IMessageChannel channel = (IMessageChannel)KKK.Client.GetChannel(channelid);
- IUserMessage themessage = (IUserMessage)await channel.GetMessageAsync(messageid);
-
- await themessage.ModifyAsync(msgProperty => { msgProperty.Embed = Embed(msg, status); });
- }
- else if (num == 1)
- {
- IMessageChannel channel = (IMessageChannel)KKK.Client.GetChannel(channelid);
-
- await channel.SendMessageAsync(null, false, Embed(msg, status));
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.ToString());
- }
- }
-
- public static Embed Embed(string msg, int status = 0)
- {
- var ebd = new EmbedBuilder();
- if (status == 0)
- {
- Color Colorr = new Color(21, 22, 34);
- ebd.Color = Colorr;
- }
- else if (status == 20 || status == 21)
- {
- ebd.Color = Color.Green;
- }
- else if (status == 40 || status == 44)
- {
- ebd.Color = Color.Red;
- }
-
- ebd.WithDescription($"{msg}");
-
- return ebd.Build();
- }
-
-
-
- ///
- /// By giving server id, it gets ip and token, and using timout is optional, its on 10 sec default
- ///
- public static async Task Sendmsg(ulong serverid, string msg, long timeout = 10000)
- {
- DatabaseContext context = new DatabaseContext();
-
- string token = context.Auth.AsQueryable().Where(a => a.Serverid == serverid).Single().Token;
- string ip = context.Auth.AsQueryable().Where(a => a.Serverid == serverid).Single().IP;
-
- if (CheckConnection(ip)) //check if its connected
- {
- Stopwatch sw = new Stopwatch();
- sw.Start();
- while (true)
- {
- if (sw.ElapsedMilliseconds > timeout)
- {
- Console.WriteLine($"Connection Timeout for {ip}");
- return 0;
- }
-
- try
- {
- var socket = Program.allSockets.Find(client => client.ConnectionInfo.ClientIpAddress == ip);
- await socket.Send(msg);
-#if DEBUG
- Console.WriteLine($"{msg} send to {socket.ConnectionInfo.ClientIpAddress}");
-#endif
- return 1;
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.ToString());
- return 0;
- }
- }
- }
-
- return 0;
- }
-
- [Command("rec", RunMode = RunMode.Async)]
- [Alias("rec")]
- [Summary("Recreates Fork related role and channel")]
- public async Task Rec()
- {
- await Task.Run(async () =>
- {
- try
- {
- DatabaseContext context = new DatabaseContext();
- if (context.OnJoin.FirstOrDefault(a => a.Serverid == Context.Guild.Id) != null)
- {
- context.Remove(context.OnJoin.Single(a => a.Serverid == Context.Guild.Id));
- context.SaveChanges();
- }
-
- string warning = null;
- try
- {
- if (Context.Guild.Roles.Any(x => x.Name.ToLower() == "Fork-Mods".ToLower()))
- {
- foreach (var Role in Context.Guild.Roles.Where(x => x.Name.ToLower() == "Fork-Mods".ToLower()))
- {
- await Role.DeleteAsync();
- }
- }
- }
- catch (Exception ex)
- {
- warning +=
- $"`Fork-Mods` role detected, please move my role to top roles then run `$rec` to clean it." +
- Environment.NewLine;
- }
-
- try
- {
- foreach (var channel in Context.Guild.Channels.Where(x =>
- string.Equals(x.Name, "Fork-Bot", StringComparison.CurrentCultureIgnoreCase)))
- {
- await channel.DeleteAsync();
- }
- }
- catch (Exception ex)
- {
- warning +=
- $"`Fork-Bot` channel detected, please move my role to top roles then run `$rec` to clean it." +
- Environment.NewLine;
- }
-
- if (warning == null)
- {
- ulong origin = (ulong)GuildPermission.Speak + (ulong)GuildPermission.SendTTSMessages +
- (ulong)GuildPermission.SendMessages + (ulong)GuildPermission.ViewChannel +
- (ulong)GuildPermission.EmbedLinks + (ulong)GuildPermission.Connect +
- (ulong)GuildPermission.AttachFiles + (ulong)GuildPermission.AddReactions;
- GuildPermissions perms = new GuildPermissions(origin);
- //Color Colorr = new Color(21, 22, 34);
- var roleee = await Context.Guild.CreateRoleAsync("Fork-Mods", perms, null, false, false, null);
- var vChan = await Context.Guild.CreateTextChannelAsync("Fork-Bot");
- await vChan.AddPermissionOverwriteAsync(roleee, CommandHandler.AdminPermissions());
- await vChan.AddPermissionOverwriteAsync(Context.Guild.EveryoneRole, CommandHandler.NoPermissions());
-
- var ebd = new EmbedBuilder();
- ebd.Color = Color.Green;
- ebd.WithCurrentTimestamp();
- ebd.WithAuthor($"Fork Server Management", Context.Guild.CurrentUser.GetAvatarUrl());
- ebd.WithDescription(
- "Hello there," +
- Environment.NewLine +
- "I'm Fork Bot if you don't know me, I can help you control your Fork Minecraft servers and display their status in Discord." +
- Environment.NewLine +
- "I made a private channel for you, please use `$auth [token]` to link this Discord server with your Fork app." +
- Environment.NewLine +
- "You can check for your token in Fork app settings.");
- //var ownerr = KKK.Client.GetGuild(guild.Id).OwnerId;
- await vChan.SendMessageAsync($"<@{Context.Guild.OwnerId}>", false, ebd.Build());
- var msgg = await vChan.SendMessageAsync(null, false,
- Embed(
- "Don't remove this message, this message will be updated continuously and display the status of you Fork servers.",
- 20));
- using (var contextt = new DatabaseContext())
- {
- OnJoin newset = new OnJoin();
- newset.Serverid = Context.Guild.Id;
- newset.Roleid = roleee.Id;
- newset.Channelid = vChan.Id;
- newset.Messageid = msgg.Id;
- contextt.Add(newset);
- contextt.SaveChanges();
- }
- }
- else
- {
- var ebd = new EmbedBuilder();
- ebd.Color = Color.Red;
- ebd.WithCurrentTimestamp();
- ebd.WithAuthor($"Error", Context.Guild.CurrentUser.GetAvatarUrl());
- ebd.WithDescription(warning);
- //var ownerr = KKK.Client.GetGuild(guild.Id).OwnerId;
- await Context.Guild.DefaultChannel.SendMessageAsync($"<@{Context.Guild.OwnerId}>", false,
- ebd.Build());
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.ToString());
- }
- });
- }
-
- [Command("stop", RunMode = RunMode.Async)]
- [Alias("stop")]
- [Summary("Stops a specific Minecraft server")]
- public async Task Stop([Remainder] string servername)
- {
- try
- {
- var msg = await ReplyAsync(Context.Message.Author.Mention, false,
- Embed("Alright give me few seconds please."));
- int result = await Sendmsg(Context.Guild.Id,
- $"stop|{servername}|{Context.User.Username}#{Context.User.Discriminator}|{Context.Channel.Id}|{msg.Id}");
- switch (result)
- {
- case 1:
- await msg.ModifyAsync(msgProperty =>
- {
- msgProperty.Content = $"{Context.Message.Author.Mention}";
- msgProperty.Embed = Embed("Command Executed.", 20);
- });
- break;
- case 0:
- await msg.ModifyAsync(msgProperty =>
- {
- msgProperty.Content = $"{Context.Message.Author.Mention}";
- msgProperty.Embed =
- Embed(
- "Oops. Looks like your fork app isn't online or connection timed out, please restart it.",
- 40);
- });
- break;
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.ToString());
- }
- }
-
- [Command("start", RunMode = RunMode.Async)]
- [Alias("start")]
- [Summary("Starts a specific Minecraft server")]
- public async Task Start([Remainder] string servername)
- {
- try
- {
- var msg = await ReplyAsync(Context.Message.Author.Mention, false,
- Embed("Alright give me few seconds please."));
- int result = await Sendmsg(Context.Guild.Id,
- $"start|{servername}|{Context.User.Username}#{Context.User.Discriminator}|{Context.Channel.Id}|{msg.Id}");
- switch (result)
- {
- case 1:
- await msg.ModifyAsync(msgProperty =>
- {
- msgProperty.Content = $"{Context.Message.Author.Mention}";
- msgProperty.Embed = Embed("Command Executed.", 20);
- });
- break;
- case 0:
- await msg.ModifyAsync(msgProperty =>
- {
- msgProperty.Content = $"{Context.Message.Author.Mention}";
- msgProperty.Embed =
- Embed(
- "Oops. Looks like your fork app isnt online or connection timed out, please restart it.",
- 40);
- });
- break;
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.ToString());
- }
- }
-
- [Command("notify", RunMode = RunMode.Async)]
- [Alias("notification")]
- [Summary("Subscribe to Player join/leave events")]
- public async Task Notify(SocketGuildChannel channel)
- {
- try
- {
- DatabaseContext context = new DatabaseContext();
- string token = context.Auth.AsQueryable().Where(a => a.Serverid == Context.Guild.Id).Single().Token;
- string ip = context.Auth.AsQueryable().Where(a => a.Serverid == Context.Guild.Id).Single().IP;
- var msg = await ReplyAsync(Context.Message.Author.Mention, false,
- Embed("Alright give me few seconds please."));
-
-
- if (context.Notify.Any(o => o.Serverid == Context.Guild.Id))
- {
- //await msgg.PinAsync();
- var server = context.Notify.First(a => a.Serverid == Context.Guild.Id);
- server.Channelid = channel.Id;
- context.SaveChanges();
-
- string warn = null;
- if (CheckConnection(ip))
- {
- await Sendmsg(Context.Guild.Id, $"subscribe|playerEvent");
- }
- else
- {
- warn = Environment.NewLine +
- "Couldn't connect to your Fork app but don't worry, I'll send you updates as soon as it's connected again.";
- }
-
- await msg.ModifyAsync(msgProperty =>
- {
- msgProperty.Content = $"{Context.Message.Author.Mention}";
- msgProperty.Embed = Embed($"Notification channel updated.{warn}", 20);
- });
- }
- else if ((context.Notify.Any(o => o.Serverid == Context.Guild.Id)))
- {
- //await msgg.PinAsync();
- using (var contexttt = new DatabaseContext())
- {
- Notify newnotify = new Notify();
- newnotify.Serverid = Context.Guild.Id;
- newnotify.Channelid = channel.Id;
- contexttt.Add(newnotify);
- contexttt.SaveChanges();
- }
- await msg.ModifyAsync(msgProperty =>
- {
- msgProperty.Content = $"{Context.Message.Author.Mention}";
- msgProperty.Embed = Embed("Notification channel submitted.", 20);
- });
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine("Exception occured: " + ex.Message);
- }
- }
-
- [Command("dnotify", RunMode = RunMode.Async)]
- [Alias("dnotification")]
- [Summary("Unsubscribes from Player join/leave events")]
- public async Task DNotify()
- {
- try
- {
- DatabaseContext context = new DatabaseContext();
- string token = context.Auth.AsQueryable().Where(a => a.Serverid == Context.Guild.Id).Single().Token;
- string ip = context.Auth.AsQueryable().Where(a => a.Serverid == Context.Guild.Id).Single().IP;
- var msg = await ReplyAsync(Context.Message.Author.Mention, false,
- Embed("Alright give me few seconds please."));
-
- if (context.Notify.Any(o => o.Serverid == Context.Guild.Id))
- {
- context.Remove(context.Notify.Single(a => a.Serverid == Context.Guild.Id));
- context.SaveChanges();
- if (CheckConnection(ip))
- {
- await Sendmsg(Context.Guild.Id, $"unsub|playerEvent");
- }
-
- await msg.ModifyAsync(msgProperty =>
- {
- msgProperty.Content = $"{Context.Message.Author.Mention}";
- msgProperty.Embed = Embed("Unsubscribed from player notifications successfully.", 20);
- });
- }
- else if (!(context.Notify.Any(o => o.Serverid == Context.Guild.Id)))
- {
- await msg.ModifyAsync(msgProperty =>
- {
- msgProperty.Content = $"{Context.Message.Author.Mention}";
- msgProperty.Embed = Embed("You are not subscribed to player notifications.", 40);
- });
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine("Exception occured: " + ex.Message);
- }
- }
-
- //[Command("sub", RunMode = RunMode.Async)]
- //[Alias("subscribe")]
- //[Summary("Subscribe to an event. usage: (prefix)sub")]
- public async Task Sub(bool check)
- {
- try
- {
- DatabaseContext context = new DatabaseContext();
- string token = context.Auth.AsQueryable().Where(a => a.Serverid == Context.Guild.Id).Single().Token;
- string ip = context.Auth.AsQueryable().Where(a => a.Serverid == Context.Guild.Id).Single().IP;
- int truefalse = check ? 1 : 0;
- var msg = await ReplyAsync(Context.Message.Author.Mention, false,
- Embed("Alright give me few seconds please."));
-
-
-
-
-
- if (context.OnJoin.Any(o => o.Serverid == Context.Guild.Id && o.sevent == 1))
- {
- if (check)
- {
- if (!(context.OnJoin.Any(o => o.Serverid == Context.Guild.Id && o.sevent == 1)))
- {
-
- IMessageChannel chan =
- (IMessageChannel)Context.Guild.GetChannel(context.OnJoin.AsQueryable().Where(a => a.Serverid == Context.Guild.Id).Single().Channelid);
- var msgg = await chan.SendMessageAsync(null, false,
- Embed(
- "Don't remove this message, this message will be updated continuously and display the status of you Fork servers.",
- 20));
-
- var server = context.OnJoin.First(a => a.Serverid == Context.Guild.Id);
- server.Messageid = msgg.Id;
- server.sevent = truefalse;
- context.SaveChanges();
- string warn = null;
- if (CheckConnection(ip))
- {
- await Sendmsg(Context.Guild.Id, $"subscribe|playerEvent");
- }
- else
- {
- warn = Environment.NewLine +
- "Couldn't connect to your Fork app but dont worry, I'll send updates as soon as it is connected again.";
- }
-
- await msg.ModifyAsync(msgProperty =>
- {
- msgProperty.Content = $"{Context.Message.Author.Mention}";
- msgProperty.Embed = Embed($"Enabled successfully.{warn}", 20);
- });
- }
- else
- {
- await msg.ModifyAsync(msgProperty =>
- {
- msgProperty.Content = $"{Context.Message.Author.Mention}";
- msgProperty.Embed = Embed($"Already enabled.", 40);
- });
- }
- }
- else if (!check)
- {
- if (context.OnJoin.Any(o => o.Serverid == Context.Guild.Id && o.sevent == 1))
- {
- var server = context.OnJoin.First(a => a.Serverid == Context.Guild.Id);
- server.Messageid = 0;
- server.sevent = truefalse;
- context.SaveChanges();
-
- if (CheckConnection(ip) == true)
- {
- await Sendmsg(Context.Guild.Id, $"unsub|serverListEvent");
- }
-
- await msg.ModifyAsync(msgProperty =>
- {
- msgProperty.Content = $"{Context.Message.Author.Mention}";
- msgProperty.Embed = Embed($"Disabled successfully.", 20);
- });
- }
- else
- {
- await msg.ModifyAsync(msgProperty =>
- {
- msgProperty.Content = $"{Context.Message.Author.Mention}";
- msgProperty.Embed = Embed($"Already disabled.", 40);
- });
- }
- }
- }
- else
- {
- await msg.ModifyAsync(msgProperty =>
- {
- msgProperty.Content = $"{Context.Message.Author.Mention}";
- msgProperty.Embed = Embed($"Please use $rec and retry", 40);
- });
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine("Exception occured: " + ex.Message);
- }
- }
-
- //[Command("ping", RunMode = RunMode.Async)]
- //[Alias("latency")]
- //[Summary("Shows the websocket connection's latency and time it takes to send a message. usage: (prefix)ping")]
- public async Task PingAsync()
- {
- try
- {
- var watch = Stopwatch.StartNew();
- var msg = await ReplyAsync("Pong");
- await msg.ModifyAsync(msgProperty => msgProperty.Content = $"🏓 {watch.ElapsedMilliseconds}ms");
- }
- catch (Exception ex)
- {
- Console.WriteLine("Exception occured: " + ex.Message);
- }
- }
-
- [Command("auth", RunMode = RunMode.Async)]
- [Alias("authorize")]
- [Summary("Links your Discord server to your Fork app")]
- public async Task Auth(string token)
- {
- try
- {
- DatabaseContext context = new DatabaseContext();
- await Context.Message.DeleteAsync();
- var msg = await ReplyAsync(Context.Message.Author.Mention, false,
- Embed("Alright give me few seconds please."));
-
- if (context.Auth.Any(o => o.Token == token))
- {
- await msg.ModifyAsync(msgProperty =>
- {
- msgProperty.Content = $"{Context.Message.Author.Mention}";
- msgProperty.Embed =
- Embed(
- "Couldn't connect to your Fork app. Either it is not running, Fork Bot is not enabled or your Fork app is already linked to another Discord server.",
- 40);
- });
- }
- else if (!context.Auth.Any(o => o.Token == token || o.Serverid == Context.Guild.Id) && context.OnHold.Any(o => o.Token == token))
- {
- //sorting the token goes here
- //After connection if server replies, then its ok
-
- string ip = context.OnHold.AsQueryable().Where(a => a.Token ==token).Single().IP;
- if (CheckConnection(ip)) //check if its connected
- {
- using (var ctx = new DatabaseContext())
- {
- Auth newauth = new Auth();
- newauth.Serverid = Context.Guild.Id;
- newauth.Token = token;
- newauth.IP = ip;
- ctx.Add(newauth);
- ctx.SaveChanges();
- }
- context.Remove(context.OnHold.Single(a => a.Token == token));
- context.SaveChanges();
- await Sendmsg(Context.Guild.Id, $"status|Linked|{Context.Guild.Name}");
- if (!context.OnJoin.Any(o => o.Serverid == Context.Guild.Id))
- {
- await Rec();
- }
- Program.AliveTokens.Add(token);
- await Sendmsg(Context.Guild.Id, $"subscribe|serverListEvent");
-
- await msg.ModifyAsync(msgProperty =>
- {
- msgProperty.Content = $"{Context.Message.Author.Mention}";
- msgProperty.Embed = Embed("Great, your discord server is now linked to your Fork app.",
- 20);
- });
- }
- else
- {
- await msg.ModifyAsync(msgProperty =>
- {
- msgProperty.Content = $"{Context.Message.Author.Mention}";
- msgProperty.Embed = Embed("Couldn't connect to your Fork app, make sure it's running.", 40);
- });
- }
- }
- else
- {
- await msg.ModifyAsync(msgProperty =>
- {
- msgProperty.Content = $"{Context.Message.Author.Mention}";
- msgProperty.Embed =
- Embed("Sorry, but this Discord server or the token is already authorized or invalid.", 40);
- });
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine("Exception occured: " + ex.Message);
- }
- }
-
- [Command("help", RunMode = RunMode.Async)]
- [Summary("Lists all available commands")]
- public async Task Help()
- {
- try
- {
- EmbedBuilder eb = new EmbedBuilder { Color = Color.Blue };
- bool onemod = false;
- List commands = new();
- foreach (ModuleInfo modulename in KKK.CommandService.Modules)
- {
- commands.AddRange(modulename.Commands);
- }
- commands.Sort((a, b) => a.CustomPriority().CompareTo(b.CustomPriority()));
- StringBuilder names = new();
- StringBuilder descriptions = new();
- foreach (CommandInfo command in commands)
- {
- string cmdName = command.Name;
- if (command.Parameters.Count > 0)
- {
- cmdName += " [";
- for (int i = 0; i < command.Parameters.Count; i++)
- {
- cmdName += command.Parameters[i];
- if (i < command.Parameters.Count - 1)
- {
- cmdName += " ";
- }
- }
- cmdName += "]";
- }
- names.Append($"${cmdName}{Environment.NewLine}");
- descriptions.Append(command.Summary + Environment.NewLine);
- }
-
- eb.AddField("Command", names.ToString(), true);
- eb.AddField("Description", descriptions.ToString(), true);
-
- eb.WithCurrentTimestamp();
- eb.WithAuthor("Command List", Context.Client.CurrentUser.GetAvatarUrl());
- eb.WithFooter("Requested by: " + Context.User.Username);
- await ReplyAsync(Context.Message.Author.Mention, false, eb.Build());
- }
- catch (Exception ex)
- {
- Console.WriteLine("Exception occured: " + ex.Message);
- }
- }
-
- [Command("leave", RunMode = RunMode.Async)]
- [Alias("leave")]
- [Summary("Bot will leave this Discord server")]
- public async Task Leave()
- {
- try
- {
- DatabaseContext context = new DatabaseContext();
- var msg = await ReplyAsync(Context.Message.Author.Mention, false,
- Embed(
- $"Please type `{Context.Guild.Name}` to confirm.{Environment.NewLine}Be aware this process cant be recovered.{Environment.NewLine}Type anything else to cancel."));
-
- var msgg = await Interactivity.NextMessageAsync(x => x.Author == Context.User);
-
- if (msgg.IsSuccess)
- {
-
- await ReplyAsync(Context.Message.Author.Mention, false,
- Embed($"Sad to see you go.., I'll leave shortly, good bye!", 20));
- if (msgg.Value.Content == Context.Guild.Name)
- {
- if (context.OnJoin.Any(o => o.Serverid == Context.Guild.Id))
- {
- var TheEntry = context.OnJoin.AsQueryable().Where(a => a.Serverid == Context.Guild.Id).Single();
- try
- {
- if (Context.Guild.GetChannel(TheEntry.Channelid) != null)
- {
- var channel =
- Context.Guild.GetChannel(TheEntry.Channelid);
- await channel.DeleteAsync();
- }
-
- if (Context.Guild.GetRole(TheEntry.Roleid) != null)
- {
- var Role = Context.Guild.GetRole(TheEntry.Roleid);
- await Role.DeleteAsync();
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine("Exception occured: " + ex.Message);
- }
- }
-
- await Sendmsg(Context.Guild.Id, $"rec");
- await Sendmsg(Context.Guild.Id, $"status|OnHold");
- await Sendmsg(Context.Guild.Id, $"unsub|serverListEvent");
- await Sendmsg(Context.Guild.Id, $"unsub|playerEvent");
- context.Remove(context.Auth.Single(a => a.Serverid == Context.Guild.Id));
- context.Remove(context.OnJoin.Single(a => a.Serverid == Context.Guild.Id));
- context.Remove(context.Notify.Single(a => a.Serverid == Context.Guild.Id));
- context.SaveChanges();
-
- string token = context.Auth.AsQueryable().Where(a => a.Serverid == Context.Guild.Id).Single().Token;
- Program.AliveTokens.Remove(token);
- try
- {
- await Context.Guild.LeaveAsync();
- }
- catch (Exception ex)
- {
- Console.WriteLine("Exception occured: " + ex.Message);
- }
- }
- else
- {
- await ReplyAsync(Context.Message.Author.Mention, false, Embed($"Canceled.", 20));
- }
- }
-
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.ToString());
- }
- }
-
- private static bool CheckConnection(string ip)
- {
- if (Program.allSockets.Any(client => client.ConnectionInfo.ClientIpAddress == ip))
- {
- var socket = Program.allSockets.Find(client => client.ConnectionInfo.ClientIpAddress == ip);
- return socket != null && socket.IsAvailable;
- }
-
- return false;
- }
-
- [Command("unauth", RunMode = RunMode.Async)]
- [Alias("unauthorize")]
- [Summary("Unlinks your Fork app from this Discord server")]
- public async Task UnAuth()
- {
- try
- {
- DatabaseContext context = new DatabaseContext();
- var msg = await ReplyAsync(Context.Message.Author.Mention, false,
- Embed("Alright give me few seconds please."));
-
- string token = context.Auth.AsQueryable().Where(a => a.Serverid == Context.Guild.Id).Single().Token;
-
- if (context.Auth.Any(o => o.Serverid == Context.Guild.Id || o.Token == token))
- {
-
- await Sendmsg(Context.Guild.Id, $"rec");
- await Sendmsg(Context.Guild.Id, $"status|OnHold");
- await Sendmsg(Context.Guild.Id, $"unsub|serverListEvent");
- await Sendmsg(Context.Guild.Id, $"unsub|playerEvent");
- context.Remove(context.Auth.Single(a => a.Serverid == Context.Guild.Id));
- context.Remove(context.OnJoin.Single(a => a.Serverid == Context.Guild.Id));
- context.Remove(context.Notify.Single(a => a.Serverid == Context.Guild.Id));
- context.SaveChanges();
- Program.AliveTokens.Remove(token);
- await msg.ModifyAsync(msgProperty =>
- {
- msgProperty.Content = $"{Context.Message.Author.Mention}";
- msgProperty.Embed = Embed("Your discord server got unlinked from your Fork app successfully.", 20);
- });
- }
- else
- {
- await msg.ModifyAsync(msgProperty =>
- {
- msgProperty.Content = $"{Context.Message.Author.Mention}";
- msgProperty.Embed = Embed("Your discord server isn't linked to a Fork app.", 40);
- });
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine("Exception occured: " + ex.Message);
- }
- }
- }
-}
\ No newline at end of file
diff --git a/DiscordBot/Program.cs b/DiscordBot/Program.cs
deleted file mode 100644
index 60b311e..0000000
--- a/DiscordBot/Program.cs
+++ /dev/null
@@ -1,599 +0,0 @@
-using Discord;
-using Discord.Commands;
-using Discord.WebSocket;
-using DiscordBot.Models;
-using Fleck;
-using Interactivity;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.DependencyInjection;
-using NLog;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace DiscordBot
-{
- class Program
- {
- private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
- public static List allSockets { get; set; } = new List();
- /// Connected Tokens
- ///
- public static List AliveTokens { get; set; } = new List();
-
- public static void Main()
- {
- ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
- Console.ForegroundColor = ConsoleColor.Green;
-
- Console.WriteLine(@"
-███████╗░█████╗░██████╗░██╗░░██╗ ██████╗░░█████╗░████████╗
-██╔════╝██╔══██╗██╔══██╗██║░██╔╝ ██╔══██╗██╔══██╗╚══██╔══╝
-█████╗░░██║░░██║██████╔╝█████═╝░ ██████╦╝██║░░██║░░░██║░░░
-██╔══╝░░██║░░██║██╔══██╗██╔═██╗░ ██╔══██╗██║░░██║░░░██║░░░
-██║░░░░░╚█████╔╝██║░░██║██║░╚██╗ ██████╦╝╚█████╔╝░░░██║░░░
-╚═╝░░░░░░╚════╝░╚═╝░░╚═╝╚═╝░░╚═╝ ╚═════╝░░╚════╝░░░░╚═╝░░░
----------------------------------------------------------------");
- Console.WriteLine("- Checking if database exists ..");
- if (File.Exists(@"Fork.db"))
- {
- Console.WriteLine("- Exists.");
- }
- else
- {
- using (var context = new DatabaseContext())
- {
- context.Database.EnsureCreated();
- }
- Console.WriteLine("- Created.");
- }
- Console.WriteLine("- Migrating Database");
- using (var context = new DatabaseContext())
- {
- context.Database.Migrate();
- }
-
- try
- {
- if (File.Exists(@"logs.log"))
- {
- File.Delete(@"Logs.log");
- }
- }
- catch (Exception xxxx)
- {
-
- }
-
- var config = new NLog.Config.LoggingConfiguration();
- var logfile = new NLog.Targets.FileTarget("logfile") { FileName = "nlogs.txt" };
- var logconsole = new NLog.Targets.ConsoleTarget("logconsole");
- config.AddRule(NLog.LogLevel.Info, NLog.LogLevel.Fatal, logconsole);
- config.AddRule(NLog.LogLevel.Debug, NLog.LogLevel.Fatal, logfile);
- NLog.LogManager.Configuration = config;
-
- Console.WriteLine("- Done.");
- new Program().MainAsync().GetAwaiter().GetResult();
- }
- private IConfiguration BuildConfig()
- {
- return new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("config.json").Build();
- }
- public async Task MainAsync()
- {
- var config = BuildConfig();
- using (var services = ConfigureServices())
- {
- var client = services.GetRequiredService();
- services.GetRequiredService();
-
- await client.LoginAsync(TokenType.Bot, config["token"]);
- await client.StartAsync();
- await services.GetRequiredService().InitializeAsync();
- await Task.Run(async () => await GetReadyWS());
- await Task.Delay(Timeout.Infinite);
- }
- }
- private async Task GetReadyWS()
- {
-
-
- if (KKK.IsClientReady != true)
- {
- Console.WriteLine("Waiting for client to be ready..."); //Dont start events until discord api is ready
- }
-
- do
- {
- // nothing, just pauses the tasks until discord is ready
- } while (KKK.IsClientReady != true);
-
- Console.WriteLine("It's ready, lets start, shall we?");
- DatabaseContext context = new DatabaseContext();
-#if RELEASE
- var server = new WebSocketServer("wss://0.0.0.0:8181");
- var config = BuildConfig();
- server.Certificate = new X509Certificate2(config["certPath"], config["certPassword"]);
-#elif DEBUG
- var server = new WebSocketServer("ws://0.0.0.0:8181");
-#endif
- server.Start(socket =>
- {
- socket.OnOpen = () =>
- {
- if (allSockets.Any(client =>
- client.ConnectionInfo.ClientIpAddress == socket.ConnectionInfo.ClientIpAddress))
- {
- var socket2 = allSockets.Find(client =>
- client.ConnectionInfo.ClientIpAddress == socket.ConnectionInfo.ClientIpAddress);
- try
- {
- allSockets.Remove(socket2);
- }
- catch (Exception ex)
- {
- logger.Warn(ex.ToString(), "An error occured.");
- } //Little security, dont let same ip to connect twice
-
- allSockets.Add(socket);
- }
- else
- {
- try
- {
- allSockets.Remove(socket);
- }
- catch (Exception ex)
- {
- logger.Warn(ex.ToString(), "An error occured.");
- }
-
- allSockets.Add(socket);
- }
- };
- socket.OnClose = () =>
- {
- Console.WriteLine("Closed connection: " + socket.ConnectionInfo.ClientIpAddress);
- allSockets.Remove(socket);
- if (context.Auth.Any(o => o.IP == socket.ConnectionInfo.ClientIpAddress))
- {
- string token = context.Auth.AsQueryable().Where(a => a.IP == socket.ConnectionInfo.ClientIpAddress).Single().Token;
- if (AliveTokens.Contains(token))
- {
- AliveTokens.Remove(token);
- logger.Info($"{socket.ConnectionInfo.ClientIpAddress} Removed from alive tokens list");
- }
- }
-
- };
- socket.OnMessage = message =>
- {
- Task.Run(async () =>
- {
- try
- {
-#if DEBUG
- Console.WriteLine($"Message Received: {message}");
-#endif
- string[] codes = message.Split('|');
- switch (codes[0])
- {
- case "login":
- string token = codes[1];
- if (context.Auth.Any(o => o.Token == token))
- {
-
- if (!AliveTokens.Contains(context.Auth.AsQueryable().Where(a => a.IP == socket.ConnectionInfo.ClientIpAddress).Single().Token))
- {
- try
- {
- AliveTokens.Add(token);
- Console.WriteLine(
- $"{socket.ConnectionInfo.ClientIpAddress}:{token} Added to alive tokens list");
-#if DEBUG
- Console.WriteLine("Here is Serverid: " +
- context.Auth.AsQueryable().Where(a => a.Token == token).Single().Serverid);
-#endif
- if (KKK.Client.GetGuild(context.Auth.AsQueryable().Where(a => a.Token == token).Single().Serverid) != null)
- {
- var guild = KKK.Client.GetGuild(
- context.Auth.AsQueryable().Where(a => a.Token == token).Single().Serverid);
- await socket.Send($"status|Linked|{guild.Name}");
- }
- else
- {
- await socket.Send($"status|Linked|null");
- }
- if (context.Notify.Any(o => o.Serverid == context.Auth.AsQueryable().Where(a => a.Token == token).Single().Serverid))
- {
- await socket.Send($"subscribe|playerEvent");
- }
- if (context.OnJoin.Any(o => (o.Serverid == context.Auth.AsQueryable().Where(a => a.Token == token).Single().Serverid) && o.sevent == 1))
- {
- await socket.Send($"subscribe|serverListEvent");
- }
- }
- catch (Exception ex)
- {
- logger.Warn(ex.ToString(), "An error occured.");
- }
- }
- }
- else if (!(context.Auth.Any(o => o.Token == token)))
- {
- if (!(context.OnHold.Any(o => o.IP == socket.ConnectionInfo.ClientIpAddress)))
- {
- using (var contextt = new DatabaseContext())
- {
- OnHold newonhold = new OnHold();
- newonhold.IP = socket.ConnectionInfo.ClientIpAddress;
- newonhold.Token = token;
- contextt.Add(newonhold);
- contextt.SaveChanges();
- }
- } else if ((context.OnHold.Any(o => o.IP == socket.ConnectionInfo.ClientIpAddress)))
- {
- var onhold = context.OnHold.First(a => a.IP == socket.ConnectionInfo.ClientIpAddress);
- onhold.Token = token;
- context.SaveChanges();
- }
- Console.WriteLine("Token: " + token +
- $" IP: {socket.ConnectionInfo.ClientIpAddress} Added to onhold list");
- await socket.Send("status|OnHold");
- }
-
- break;
- case "notify":
-
- if (AliveTokens.Contains(context.Auth.AsQueryable().Where(a => a.IP == socket.ConnectionInfo.ClientIpAddress).Single().Token))
- {
- await Task.Run(async () =>
- {
- try
- {
- string servername = codes[1];
- string discordname = codes[2];
- string channelid = codes[3];
- string messageid = codes[4];
- string eventt = codes[5];
- string result = codes[6];
-
- switch (eventt)
- {
- case "stop":
-
- switch (result)
- {
- //notify|{servername}|{discordname}|{channelid}|{messageid}|{eventt}|400|this is a test
- case "20": //ok
- await BotTools.NotificationControlAsync(
- ulong.Parse(messageid), ulong.Parse(channelid),
- $"Your `{servername}` stopped successfully, command was executed by `{discordname}`",
- int.Parse(result));
- break;
-
- case "40": //its stopped already
- await BotTools.NotificationControlAsync(
- ulong.Parse(messageid), ulong.Parse(channelid),
- $"Your `{servername}` is stopped already, command was executed by `{discordname}`",
- int.Parse(result));
- break;
-
- case "44": //server not found
- await BotTools.NotificationControlAsync(
- ulong.Parse(messageid), ulong.Parse(channelid),
- $"I couldnt find your `{servername}` server, please make sure you typed the right name, command was executed by `{discordname}`",
- int.Parse(result));
- break;
- }
-
- break;
-
- case "start":
-
- switch (result)
- {
- //notify|{servername}|{discordname}|{channelid}|{messageid}|{eventt}|400|this is a test
- case "20": //ok
- await BotTools.NotificationControlAsync(
- ulong.Parse(messageid), ulong.Parse(channelid),
- $"Your `{servername}` server is starting.. , command was executed by `{discordname}`",
- int.Parse(result));
- break;
- case "21": //ok
- await BotTools.NotificationControlAsync(
- ulong.Parse(messageid), ulong.Parse(channelid),
- $"Your `{servername}` started successfully, command was executed by `{discordname}`",
- int.Parse(result));
- break;
- case "40": //its stopped already
- await BotTools.NotificationControlAsync(
- ulong.Parse(messageid), ulong.Parse(channelid),
- $"Your `{servername}` is running already, command was executed by `{discordname}`",
- int.Parse(result));
- break;
-
- case "44": //server not found
- await BotTools.NotificationControlAsync(
- ulong.Parse(messageid), ulong.Parse(channelid),
- $"I couldnt find your `{servername}` server, please make sure you typed the right name, command was executed by `{discordname}`",
- int.Parse(result));
- break;
- }
-
- break;
- }
- }
- catch (Exception ex)
- {
- logger.Warn($"Couldn't process request: {ex.Message}");
- }
- });
- }
-
- break;
- case "event":
- await Task.Run(async () =>
- {
- string eventname = codes[1];
- string servername = codes[2];
- string playername = codes[3];
- try
- {
- string token = context.Auth.AsQueryable().Where(a => a.IP == socket.ConnectionInfo.ClientIpAddress).Single().Token;
- if (AliveTokens.Contains(token))
- {
- if (KKK.Client.GetGuild(context.Auth.AsQueryable().Where(a => a.Token == token).Single().Serverid) != null)
- {
- if (eventname.StartsWith("p")
- && context.Notify.AsQueryable().Any(x => x.Serverid == context.Auth.AsQueryable().Where(a => a.Token == token).Single().Serverid)
- && KKK.Client.GetGuild(context.Auth.AsQueryable().Where(a => a.Token == token).Single().Serverid)
- .GetChannel(
- context.Notify.AsQueryable().Where(a => a.Serverid == context.Auth.AsQueryable().Where(a => a.Token == token).Single().Serverid).Single().Channelid) != null)
- {
- switch (eventname)
- {
- case "pjoin":
- await BotTools.NotificationControlAsync(0,
- context.Notify.AsQueryable().Where(a => a.Serverid == context.Auth.AsQueryable().Where(a => a.Token == token).Single().Serverid).Single().Channelid,
- $"***{playername}*** Just joined ***{servername}***", 0,
- 1);
- break;
- case "pleave":
- await BotTools.NotificationControlAsync(0,
- context.Notify.AsQueryable().Where(a => a.Serverid == context.Auth.AsQueryable().Where(a => a.Token == token).Single().Serverid).Single().Channelid,
- $"***{playername}*** Just left ***{servername}***", 0,
- 1);
- break;
- }
- }
- else if (eventname.StartsWith("serverList") &&
- context.OnJoin.Any(o => (o.Serverid == context.Auth.AsQueryable().Where(a => a.Token == token).Single().Serverid) && o.sevent == 1)
- && KKK.Client
- .GetGuild(context.Auth.AsQueryable().Where(a => a.Token == token).Single().Serverid)
- .GetChannel(
- context.OnJoin.AsQueryable().Where(a => a.Serverid == context.Auth.AsQueryable().Where(a => a.Token == token).Single().Serverid).Single().Channelid) !=
- null)
- {
- await Task.Run(async () =>
- {
- try
- {
- if (AliveTokens.Contains(token) &&
- (context.OnJoin.Any(o => (o.Serverid == context.Auth.AsQueryable().Where(a => a.Token == token).Single().Serverid) && o.sevent == 1)))
- {
- ulong guild = context.Auth.AsQueryable().Where(a => a.Token == token).Single().Serverid;
- if (KKK.Client.GetGuild(guild)
- .GetChannel(
- context.OnJoin.AsQueryable().Where(a => a.Serverid == context.Auth.AsQueryable().Where(a => a.Token == token).Single().Serverid).Single().Channelid) != null)
- {
- if (context.OnJoin.AsQueryable().Where(a => a.Serverid == context.Auth.AsQueryable().Where(a => a.Token == token).Single().Serverid).Single().Messageid != 0)
- {
- IMessageChannel chan =
- (IMessageChannel)KKK.Client.GetChannel(context.OnJoin.AsQueryable().Where(a => a.Serverid == context.Auth.AsQueryable().Where(a => a.Token == token).Single().Serverid).Single().Channelid);
- IUserMessage msg =
- (IUserMessage)await chan.GetMessageAsync(context.OnJoin.AsQueryable().Where(a => a.Serverid == context.Auth.AsQueryable().Where(a => a.Token == token).Single().Serverid).Single().Messageid);
- if (msg != null)
- {
- await msg.ModifyAsync(msgProperty =>
- {
- msgProperty.Embed =
- BuildServerListEmbed(message);
- });
- }
- else
- {
- var msgg = await chan.SendMessageAsync(null,
- false,
- BotTools.Embed(
- "Dont remove this message, this message will be updated continuously",
- 20));
- var server = context.OnJoin.First(a => a.Serverid == guild);
- server.Messageid = msgg.Id;
- server.sevent = 1;
- context.SaveChanges();
- await msgg.ModifyAsync(msgProperty =>
- {
- msgProperty.Embed =
- BuildServerListEmbed(message);
- });
- }
- }
- }
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine("Exception occured: " + ex.ToString());
- }
- });
- }
- }
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine("Exception occured: " + ex.ToString());
- }
- });
-
- break;
-
- default:
- // ban ip in case gets to x requests To-DO
- Console.WriteLine($"Someone is trying to troll here, invalid packet: {message}");
- break;
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.ToString());
- }
- });
-
-
- //Console.WriteLine(message);
-
- //allSockets.ToList().ForEach(s => s.Send(message));
- };
- });
- var input = Console.ReadLine();
- while (input != "exit")
- {
- //foreach (var socket in allSockets.ToList())
- //{
- // await socket.Send(input);
- //}
- //input = Console.ReadLine();
- }
- }
- private static Embed BuildServerListEmbed(string msg)
- {
- string[] split = msg.Split('|');
-
- //List serverList = new List();
- string serverrr = null;
- int i = 2;
- while (i < split.Length - 5)
- {
- string serverName = split[i];
- string serverType = split[i + 1];
- string serverVersion = split[i + 2];
- string serverStatus = split[i + 3];
- string playerCount = split[i + 4];
- string maxPlayers = split[i + 5];
- //TODO replace these with custom cool looking emojis
- Emote statusEmote;
- if (serverStatus.ToLower().Equals("running"))
- {
- if (!Emote.TryParse("<:Online:800460070709362739>", out statusEmote))
- {
- statusEmote = Emote.Parse(":green_circle:");
- }
- }
- else if (serverStatus.ToLower().Equals("stopped"))
- {
- if (!Emote.TryParse("<:Offline:800460061255663646>", out statusEmote))
- {
- statusEmote = Emote.Parse(":red_circle:");
- }
- }
- else if (serverStatus.ToLower().Equals("starting"))
- {
- if (!Emote.TryParse("<:Starting:800460572268953670>", out statusEmote))
- {
- statusEmote = Emote.Parse(":yellow_circle:");
- }
- }
- else
- {
- statusEmote = Emote.Parse(":black_circle:");
- }
-
- string typeEmote;
- if (serverType.ToLower().Equals("vanilla"))
- {
- if (Emote.TryParse("<:Vanilla:800457564403400724>", out _))
- {
- typeEmote = "<:Vanilla:800457564403400724>";
- }
- else
- {
- typeEmote = "Vanilla";
- }
- }
- else if (serverType.ToLower().Equals("paper"))
- {
- if (Emote.TryParse("<:Paper:800457547907596359>", out _))
- {
- typeEmote = "<:Paper:800457547907596359>";
- }
- else
- {
- typeEmote = "Paper";
- }
- }
- else if (serverType.ToLower().Equals("spigot"))
- {
- if (Emote.TryParse("<:Spigot:800458118857228298>", out _))
- {
- typeEmote = "<:Spigot:800458118857228298>";
- }
- else
- {
- typeEmote = "Spigot";
- }
- }
- else if (serverType.ToLower().Equals("waterfall"))
- {
- if (Emote.TryParse("<:Waterfall:800457575590002708>", out _))
- {
- typeEmote = "<:Waterfall:800457575590002708>";
- }
- else
- {
- typeEmote = "Waterfall";
- }
- }
- else
- {
- typeEmote = "Unknown";
- }
-
- //Build server string
- string server = $"{statusEmote} {serverName} ({typeEmote} {serverVersion}) {playerCount}/{maxPlayers}" +
- Environment.NewLine;
- serverrr += server;
- i = i + 6;
- }
-
- var ebd = new EmbedBuilder();
- Color Colorr = new Color(21, 22, 34);
- ebd.WithTitle("Your current servers");
- ebd.WithDescription($"{serverrr}");
- ebd.WithCurrentTimestamp();
- return ebd.Build();
- }
- private ServiceProvider ConfigureServices()
- {
- return new ServiceCollection()
- .AddSingleton(new DiscordSocketClient(new DiscordSocketConfig() { MessageCacheSize = 20, AlwaysDownloadUsers = true, LogLevel = LogSeverity.Verbose,
- GatewayIntents= GatewayIntents.DirectMessageReactions | GatewayIntents.DirectMessages |
- GatewayIntents.GuildBans | GatewayIntents.GuildInvites | GatewayIntents.GuildMembers |
- GatewayIntents.GuildMessageReactions | GatewayIntents.GuildMessages |
- GatewayIntents.Guilds | GatewayIntents.GuildIntegrations
- })) //, .TotalShards = 3}))
- .AddSingleton(new CommandService(new CommandServiceConfig() { LogLevel = LogSeverity.Verbose, DefaultRunMode = RunMode.Async }))
- .AddSingleton()
- .AddSingleton()
- .AddSingleton()
- .AddSingleton(new InteractivityConfig { DefaultTimeout = TimeSpan.FromSeconds(40) }) // You can optionally add a custom config
- .BuildServiceProvider();
- }
- }
-}
\ No newline at end of file
diff --git a/DiscordBot/Services/CommandHandler.cs b/DiscordBot/Services/CommandHandler.cs
deleted file mode 100644
index 9d30dd5..0000000
--- a/DiscordBot/Services/CommandHandler.cs
+++ /dev/null
@@ -1,291 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Net.Sockets;
-using System.Reflection;
-using System.Threading;
-using System.Threading.Tasks;
-using Discord;
-using Discord.Commands;
-using Discord.WebSocket;
-using DiscordBot.Models;
-using NLog;
-
-namespace DiscordBot
-{
-
- static class KKK
- {
- public static string prefix = "$";
- public static CommandService CommandService;
- public static DiscordSocketClient Client;
- public static bool IsClientReady = false;
- }
-
- public class CommandHandler
- {
- private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
- private readonly IServiceProvider Services;
-
- public CommandHandler(DiscordSocketClient client, CommandService commandService, IServiceProvider services)
- {
- KKK.Client = client;
- KKK.CommandService = commandService;
- Services = services;
- }
-
- public async Task InitializeAsync()
- {
- await KKK.CommandService.AddModulesAsync(Assembly.GetEntryAssembly(), Services);
- KKK.Client.Ready += OnClientReady;
- KKK.Client.UserJoined += welcome;
- KKK.Client.MessageReceived += HandleCommandAsync;
- KKK.Client.JoinedGuild += OnGuildJoin;
- KKK.Client.LeftGuild += OnGuildLeave;
- KKK.Client.Disconnected += OnClientDisconnect;
- }
-
- public static OverwritePermissions AdminPermissions()
- {
- return new(PermValue.Deny, PermValue.Deny, PermValue.Deny, PermValue.Allow,
- PermValue.Allow, PermValue.Deny, PermValue.Allow, PermValue.Deny, PermValue.Deny, PermValue.Allow,
- PermValue.Deny, PermValue.Deny, PermValue.Deny, PermValue.Deny, PermValue.Deny, PermValue.Deny,
- PermValue.Deny, PermValue.Deny, PermValue.Deny, PermValue.Deny, PermValue.Deny, PermValue.Deny);
- }
-
- public static OverwritePermissions NoPermissions()
- {
- return new(PermValue.Deny, PermValue.Deny, PermValue.Deny,
- PermValue.Deny, PermValue.Deny, PermValue.Deny, PermValue.Deny,
- PermValue.Deny, PermValue.Deny, PermValue.Deny, PermValue.Deny,
- PermValue.Deny, PermValue.Deny, PermValue.Deny, PermValue.Deny,
- PermValue.Deny, PermValue.Deny, PermValue.Deny, PermValue.Deny,
- PermValue.Deny);
- }
-
- private async Task OnGuildJoin(SocketGuild guild)
- {
- await Task.Run(async () =>
- {
- try
- {
- DatabaseContext context = new DatabaseContext();
-
-
- if (!(context.Auth.Any(o => o.Serverid == guild.Id) && (!(context.OnJoin.Any(o => o.Serverid == guild.Id)))))
- {
- string warning = null;
- try
- {
- if (guild.Roles.Any(x => x.Name == "Fork-Mods"))
- {
- foreach (var Role in guild.Roles.Where(x => x.Name == "Fork-Mods"))
- {
- await Role.DeleteAsync();
- }
- }
- }
- catch (Exception ex)
- {
- warning +=
- $"`Fork-Mods` role detected, please move my role above the `Fork-Mods` role and authenticate using `$auth [token]` then run `$rec` to clean it." +
- Environment.NewLine;
- }
-
- try
- {
- if (guild.TextChannels.Any(x => x.Name == "Fork-Bot"))
- {
- foreach (var Chan in guild.Channels.Where(x => x.Name == "Fork-Bot"))
- {
- await Chan.DeleteAsync();
- }
- }
- }
- catch (Exception ex)
- {
- warning +=
- $"`Fork-Bot` channel detected, please move my role above the `Fork-Mods` role and authenticate using `$auth [token]` then run `$rec` to clean it." +
- Environment.NewLine;
- }
-
- if (warning == null)
- {
- ulong origin = (ulong)GuildPermission.Speak + (ulong)GuildPermission.SendTTSMessages +
- (ulong)GuildPermission.SendMessages + (ulong)GuildPermission.ViewChannel +
- (ulong)GuildPermission.EmbedLinks + (ulong)GuildPermission.Connect +
- (ulong)GuildPermission.AttachFiles + (ulong)GuildPermission.AddReactions;
- GuildPermissions perms = new GuildPermissions(origin);
- //Color Colorr = new Color(21, 22, 34);
- var roleee = await guild.CreateRoleAsync("Fork-Mods", perms, null, false, false, null);
- var vChan = await guild.CreateTextChannelAsync("Fork-Bot");
- await vChan.AddPermissionOverwriteAsync(roleee, AdminPermissions());
- await vChan.AddPermissionOverwriteAsync(guild.EveryoneRole, NoPermissions());
-
- var ebd = new EmbedBuilder();
- ebd.Color = Color.Green;
- ebd.WithCurrentTimestamp();
- ebd.WithAuthor($"Fork Server Management", guild.CurrentUser.GetAvatarUrl());
- ebd.WithDescription(
- "Hello there," +
- Environment.NewLine +
- "I'm Fork Bot if you don't know me, I can help you control your Fork Minecraft servers and display their status in Discord." +
- Environment.NewLine +
- "I made a private channel for you, please use `$auth [token]` to link this Discord server with your Fork app." +
- Environment.NewLine +
- "You can check for your token in Fork app settings.");
- //var ownerr = KKK.Client.GetGuild(guild.Id).OwnerId;
- await vChan.SendMessageAsync($"<@{guild.OwnerId}>", false, ebd.Build());
- var msgg = await vChan.SendMessageAsync(null, false,
- BotTools.Embed("Don't remove this message, this message will be updated continuously and display the status of you Fork servers.", 20));
- using (var contextt = new DatabaseContext())
- {
- OnJoin newset = new OnJoin();
- newset.Serverid = guild.Id;
- newset.Roleid = roleee.Id;
- newset.Channelid = vChan.Id;
- newset.Messageid = msgg.Id;
- contextt.Add(newset);
- contextt.SaveChanges();
- }
-
- }
- else
- {
- var ebd = new EmbedBuilder();
- ebd.Color = Color.Red;
- ebd.WithCurrentTimestamp();
- ebd.WithAuthor($"Error", guild.CurrentUser.GetAvatarUrl());
- ebd.WithDescription(warning);
- //var ownerr = KKK.Client.GetGuild(guild.Id).OwnerId;
- await guild.DefaultChannel.SendMessageAsync($"<@{guild.OwnerId}>", false, ebd.Build());
- }
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.ToString());
- }
- });
- }
-
- private async Task OnGuildLeave(SocketGuild guild)
- {
- await Task.Run(async () =>
- {
- try
- {
- DatabaseContext context = new DatabaseContext();
- if ((context.Auth.Any(o => o.Serverid == guild.Id) || ((context.OnJoin.Any(o => o.Serverid == guild.Id)))))
-
- {
- try
- {
- string token = context.Auth.AsQueryable().Where(a => a.Serverid == guild.Id).Single().Token;
- await BotTools.Sendmsg(guild.Id, $"status|OnHold");
- await BotTools.Sendmsg(guild.Id, $"rec");
- await BotTools.Sendmsg(guild.Id, $"unsub|serverListEvent");
- await BotTools.Sendmsg(guild.Id, $"unsub|playerEvent");
- Program.AliveTokens.Remove(token);
- }
- catch (Exception ex)
- {
- logger.Warn($"Exception occured: {ex.ToString()}");
- }
- context.Remove(context.Auth.Single(a => a.Serverid == guild.Id));
- context.Remove(context.Notify.Single(a => a.Serverid == guild.Id));
- context.Remove(context.OnJoin.Single(a => a.Serverid == guild.Id));
- context.SaveChanges();
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.ToString());
- }
- });
- }
-
-
-
- private async Task OnClientDisconnect(Exception k)
- {
- KKK.IsClientReady = false;
- }
-
- private async Task OnClientReady()
- {
- KKK.IsClientReady = true;
- try
- {
- await KKK.Client.SetGameAsync($"your Minecraft servers", null, ActivityType.Watching);
- }
- catch (Exception ex)
- {
- logger.Warn($"Exception occured: {ex.ToString()}");
- }
- }
-
- private async Task welcome(SocketGuildUser user)
- {
- }
-
- private async Task HandleCommandAsync(SocketMessage message)
- {
- _ = Task.Run(async () =>
- {
-
- SocketUserMessage userMessage = message as SocketUserMessage;
- if (userMessage is null || userMessage.Author.IsBot || userMessage.Author.IsWebhook)
- return;
- int argPos = 0;
- var context = new SocketCommandContext(KKK.Client, userMessage);
- try
- {
- if (message.Channel.GetType().ToString() != "Discord.WebSocket.SocketDMChannel")
- {
- if (!userMessage.HasMentionPrefix(KKK.Client.CurrentUser, ref argPos) &&
- !userMessage.HasStringPrefix(KKK.prefix, ref argPos, StringComparison.OrdinalIgnoreCase))
- {
- return;
- }
- DatabaseContext contextt = new DatabaseContext();
-
- var authorr = context.Guild.GetUser(context.Message.Author.Id);
- var thisss = context.Message.Author as SocketGuildUser;
- ulong roleeid = (contextt.OnJoin.AsQueryable().Where(a => a.Serverid == context.Guild.Id).FirstOrDefault() ==null) ? 0 : contextt.OnJoin.AsQueryable().Where(a => a.Serverid == context.Guild.Id).FirstOrDefault().Roleid;
-
-
-
- if (authorr.Roles.Any(r => r.Id == roleeid) || thisss.GuildPermissions.ManageGuild)
- {
- if (userMessage.Content.ToLower().StartsWith($"{KKK.prefix}auth") ||
- userMessage.Content.ToLower().StartsWith($"{KKK.prefix}leave")
- ) //if its for authentication let the command to be executed
- {
- string command = userMessage.Content.Substring(argPos).Trim();
- var result = await KKK.CommandService.ExecuteAsync(context, command, Services);
-
- if (!result.IsSuccess)
- {
- if ((int?)result.Error != (int?)CommandError.UnknownCommand)
- {
- Console.WriteLine(result.ErrorReason);
- }
- }
- }
- }
- }
- else
- {
- await context.Channel.SendMessageAsync($"Im Not Working yet", false, null);
- }
- }
- catch (Exception ex)
- {
- logger.Warn($"Exception occured: {ex.ToString()}");
- }
- });
-
- }
- }
-}
\ No newline at end of file
diff --git a/DiscordBot/Services/LogService.cs b/DiscordBot/Services/LogService.cs
deleted file mode 100644
index 5a89b4c..0000000
--- a/DiscordBot/Services/LogService.cs
+++ /dev/null
@@ -1,108 +0,0 @@
-using System;
-using System.Threading.Tasks;
-using Discord;
-using Discord.Commands;
-using Discord.WebSocket;
-using Microsoft.VisualBasic;
-namespace DiscordBot
-{
-
- public class LogService
- {
- public LogService(DiscordSocketClient client, CommandService commands)
- {
- client.Log += ClientLog;
- commands.CommandExecuted += CommandLog;
- }
-
- public static Task ClientLog(LogMessage message)
- {
-
- Console.WriteLine(message.ToString());
- writetolog(message.ToString());
- return Task.CompletedTask;
-
- }
-
- public static void writetolog(string text)
- {
- string location = AppDomain.CurrentDomain.BaseDirectory;
- string fullpath = System.IO.Path.Combine(location, "logs.log");
- try
- {
- System.IO.File.AppendAllText(System.IO.Path.Combine(location, "logs.log"), DateTime.Now + " | " + text + Constants.vbNewLine);
- }
- catch (Exception ex)
- {
- }
- }
-
- private Task CommandLog(Optional info, ICommandContext context, IResult result)
- {
- if (result.IsSuccess)
- return Task.CompletedTask;
- switch (result.Error.Value)
- {
- case CommandError.UnknownCommand:
- {
- return Task.CompletedTask;
- }
-
- case CommandError.ParseFailed:
- {
- Console.WriteLine(context.Guild.Name + " | " + result.ToString());
- break;
- }
-
- case CommandError.BadArgCount:
- {
- Console.ForegroundColor = ConsoleColor.Yellow;
- Console.WriteLine(context.Guild.Name + " | " + result.ToString());
- Console.ForegroundColor = ConsoleColor.Green;
- break;
- }
-
- case CommandError.ObjectNotFound:
- {
- Console.ForegroundColor = ConsoleColor.Yellow;
- Console.WriteLine(context.Guild.Name + " | " + result.ToString());
- Console.ForegroundColor = ConsoleColor.Green;
- break;
- }
-
- case CommandError.MultipleMatches:
- {
- Console.ForegroundColor = ConsoleColor.Red;
- Console.WriteLine(context.Guild.Name + " | " + result.ToString());
- Console.ForegroundColor = ConsoleColor.Green;
- break;
- }
-
- case CommandError.UnmetPrecondition:
- {
- Console.WriteLine(context.Guild.Name + " | " + result.ToString());
- break;
- }
-
- case CommandError.Exception:
- {
- Console.WriteLine(context.Guild.Name + " | " + result.ToString());
- break;
- }
-
- case CommandError.Unsuccessful:
- {
- Console.WriteLine(context.Guild.Name + " | " + result.ToString());
- break;
- }
-
- default:
- {
- break;
- }
- }
-
- return Task.CompletedTask;
- }
- }
-}
\ No newline at end of file
diff --git a/README.md b/README.md
deleted file mode 100644
index 4da5e63..0000000
--- a/README.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# Fork DiscordBot
-
-This Discord Bot is used to connect a Fork instance to a Discord server for remote controlling and event updates.
-
-## How to use
-This bot is hosted on a public server and is used by every Fork user, if `Enable Discord Bot` is enabled in the Fork settings.
-
-If you run Fork in `DEBUG` mode it will look for this running locally.
-
-## Building and Running
-To build and run this code please follow these steps:
- 1. Clone/fork this repository
- 2. Add Discord.NET beta to nuget package sources: https://www.myget.org/F/discord-net/api/v3/index.json
- 3. Add a copy of the [config.json](https://github.com/ForkGG/DiscordBot/blob/main/config.json) to the `DiscordBot` directory and add the token of a Discord bot created [here](https://discord.com/developers/applications)
- 4. The project should now be able to build and run. To test it you should also run the [Fork project](https://github.com/ForkGG/Fork) in `DEBUG` mode on the same machine
-
- ## Credits
- - Thanks to [Alpha-c0d3r | Illusion](https://github.com/EN1GMA4) for coding most of this project
- - Thanks to the [Patrons](https://www.patreon.com/forkgg) helping to cover the hosting costs for this Bot
diff --git a/config.json b/config.json
index bcab658..740baa7 100644
--- a/config.json
+++ b/config.json
@@ -1,5 +1 @@
-{
- "token": "",
- "certPath": "cert.pfx",
- "certPassword": ""
-}
\ No newline at end of file
+{"guilds":{"1022867142275776552":"dxjUaTJnmBpexsQBN4ngUgkeytQ8778/9OkLGSR14XY="}}
\ No newline at end of file
diff --git a/nodemon.json b/nodemon.json
new file mode 100644
index 0000000..4f68445
--- /dev/null
+++ b/nodemon.json
@@ -0,0 +1,3 @@
+{
+ "ignore": ["*.json"]
+}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..edb4985
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,284 @@
+{
+ "name": "tests",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "tests",
+ "version": "1.0.0",
+ "license": "ISC",
+ "dependencies": {
+ "discord.js": "^14.14.1",
+ "dotenv": "^16.3.1"
+ }
+ },
+ "node_modules/@discordjs/builders": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.7.0.tgz",
+ "integrity": "sha512-GDtbKMkg433cOZur8Dv6c25EHxduNIBsxeHrsRoIM8+AwmEZ8r0tEpckx/sHwTLwQPOF3e2JWloZh9ofCaMfAw==",
+ "dependencies": {
+ "@discordjs/formatters": "^0.3.3",
+ "@discordjs/util": "^1.0.2",
+ "@sapphire/shapeshift": "^3.9.3",
+ "discord-api-types": "0.37.61",
+ "fast-deep-equal": "^3.1.3",
+ "ts-mixer": "^6.0.3",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=16.11.0"
+ }
+ },
+ "node_modules/@discordjs/collection": {
+ "version": "1.5.3",
+ "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.5.3.tgz",
+ "integrity": "sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ==",
+ "engines": {
+ "node": ">=16.11.0"
+ }
+ },
+ "node_modules/@discordjs/formatters": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.3.3.tgz",
+ "integrity": "sha512-wTcI1Q5cps1eSGhl6+6AzzZkBBlVrBdc9IUhJbijRgVjCNIIIZPgqnUj3ntFODsHrdbGU8BEG9XmDQmgEEYn3w==",
+ "dependencies": {
+ "discord-api-types": "0.37.61"
+ },
+ "engines": {
+ "node": ">=16.11.0"
+ }
+ },
+ "node_modules/@discordjs/rest": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.2.0.tgz",
+ "integrity": "sha512-nXm9wT8oqrYFRMEqTXQx9DUTeEtXUDMmnUKIhZn6O2EeDY9VCdwj23XCPq7fkqMPKdF7ldAfeVKyxxFdbZl59A==",
+ "dependencies": {
+ "@discordjs/collection": "^2.0.0",
+ "@discordjs/util": "^1.0.2",
+ "@sapphire/async-queue": "^1.5.0",
+ "@sapphire/snowflake": "^3.5.1",
+ "@vladfrangu/async_event_emitter": "^2.2.2",
+ "discord-api-types": "0.37.61",
+ "magic-bytes.js": "^1.5.0",
+ "tslib": "^2.6.2",
+ "undici": "5.27.2"
+ },
+ "engines": {
+ "node": ">=16.11.0"
+ }
+ },
+ "node_modules/@discordjs/rest/node_modules/@discordjs/collection": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.0.0.tgz",
+ "integrity": "sha512-YTWIXLrf5FsrLMycpMM9Q6vnZoR/lN2AWX23/Cuo8uOOtS8eHB2dyQaaGnaF8aZPYnttf2bkLMcXn/j6JUOi3w==",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@discordjs/util": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.0.2.tgz",
+ "integrity": "sha512-IRNbimrmfb75GMNEjyznqM1tkI7HrZOf14njX7tCAAUetyZM1Pr8hX/EK2lxBCOgWDRmigbp24fD1hdMfQK5lw==",
+ "engines": {
+ "node": ">=16.11.0"
+ }
+ },
+ "node_modules/@discordjs/ws": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.0.2.tgz",
+ "integrity": "sha512-+XI82Rm2hKnFwAySXEep4A7Kfoowt6weO6381jgW+wVdTpMS/56qCvoXyFRY0slcv7c/U8My2PwIB2/wEaAh7Q==",
+ "dependencies": {
+ "@discordjs/collection": "^2.0.0",
+ "@discordjs/rest": "^2.1.0",
+ "@discordjs/util": "^1.0.2",
+ "@sapphire/async-queue": "^1.5.0",
+ "@types/ws": "^8.5.9",
+ "@vladfrangu/async_event_emitter": "^2.2.2",
+ "discord-api-types": "0.37.61",
+ "tslib": "^2.6.2",
+ "ws": "^8.14.2"
+ },
+ "engines": {
+ "node": ">=16.11.0"
+ }
+ },
+ "node_modules/@discordjs/ws/node_modules/@discordjs/collection": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.0.0.tgz",
+ "integrity": "sha512-YTWIXLrf5FsrLMycpMM9Q6vnZoR/lN2AWX23/Cuo8uOOtS8eHB2dyQaaGnaF8aZPYnttf2bkLMcXn/j6JUOi3w==",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@fastify/busboy": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.0.tgz",
+ "integrity": "sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA==",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@sapphire/async-queue": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.1.tgz",
+ "integrity": "sha512-1RdpsmDQR/aWfp8oJzPtn4dNQrbpqSL5PIA0uAB/XwerPXUf994Ug1au1e7uGcD7ei8/F63UDjr5GWps1g/HxQ==",
+ "engines": {
+ "node": ">=v14.0.0",
+ "npm": ">=7.0.0"
+ }
+ },
+ "node_modules/@sapphire/shapeshift": {
+ "version": "3.9.5",
+ "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.9.5.tgz",
+ "integrity": "sha512-AGdHe+51gF7D3W8hBfuSFLBocURDCXVQczScTHXDS3RpNjNgrktIx/amlz5y8nHhm8SAdFt/X8EF8ZSfjJ0tnA==",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "lodash": "^4.17.21"
+ },
+ "engines": {
+ "node": ">=v18"
+ }
+ },
+ "node_modules/@sapphire/snowflake": {
+ "version": "3.5.1",
+ "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.5.1.tgz",
+ "integrity": "sha512-BxcYGzgEsdlG0dKAyOm0ehLGm2CafIrfQTZGWgkfKYbj+pNNsorZ7EotuZukc2MT70E0UbppVbtpBrqpzVzjNA==",
+ "engines": {
+ "node": ">=v14.0.0",
+ "npm": ">=7.0.0"
+ }
+ },
+ "node_modules/@types/node": {
+ "version": "20.10.6",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.6.tgz",
+ "integrity": "sha512-Vac8H+NlRNNlAmDfGUP7b5h/KA+AtWIzuXy0E6OyP8f1tCLYAtPvKRRDJjAPqhpCb0t6U2j7/xqAuLEebW2kiw==",
+ "dependencies": {
+ "undici-types": "~5.26.4"
+ }
+ },
+ "node_modules/@types/ws": {
+ "version": "8.5.9",
+ "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.9.tgz",
+ "integrity": "sha512-jbdrY0a8lxfdTp/+r7Z4CkycbOFN8WX+IOchLJr3juT/xzbJ8URyTVSJ/hvNdadTgM1mnedb47n+Y31GsFnQlg==",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@vladfrangu/async_event_emitter": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/@vladfrangu/async_event_emitter/-/async_event_emitter-2.2.4.tgz",
+ "integrity": "sha512-ButUPz9E9cXMLgvAW8aLAKKJJsPu1dY1/l/E8xzLFuysowXygs6GBcyunK9rnGC4zTsnIc2mQo71rGw9U+Ykug==",
+ "engines": {
+ "node": ">=v14.0.0",
+ "npm": ">=7.0.0"
+ }
+ },
+ "node_modules/discord-api-types": {
+ "version": "0.37.61",
+ "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.61.tgz",
+ "integrity": "sha512-o/dXNFfhBpYHpQFdT6FWzeO7pKc838QeeZ9d91CfVAtpr5XLK4B/zYxQbYgPdoMiTDvJfzcsLW5naXgmHGDNXw=="
+ },
+ "node_modules/discord.js": {
+ "version": "14.14.1",
+ "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.14.1.tgz",
+ "integrity": "sha512-/hUVzkIerxKHyRKopJy5xejp4MYKDPTszAnpYxzVVv4qJYf+Tkt+jnT2N29PIPschicaEEpXwF2ARrTYHYwQ5w==",
+ "dependencies": {
+ "@discordjs/builders": "^1.7.0",
+ "@discordjs/collection": "1.5.3",
+ "@discordjs/formatters": "^0.3.3",
+ "@discordjs/rest": "^2.1.0",
+ "@discordjs/util": "^1.0.2",
+ "@discordjs/ws": "^1.0.2",
+ "@sapphire/snowflake": "3.5.1",
+ "@types/ws": "8.5.9",
+ "discord-api-types": "0.37.61",
+ "fast-deep-equal": "3.1.3",
+ "lodash.snakecase": "4.1.1",
+ "tslib": "2.6.2",
+ "undici": "5.27.2",
+ "ws": "8.14.2"
+ },
+ "engines": {
+ "node": ">=16.11.0"
+ }
+ },
+ "node_modules/dotenv": {
+ "version": "16.3.1",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz",
+ "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/motdotla/dotenv?sponsor=1"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
+ },
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ },
+ "node_modules/lodash.snakecase": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz",
+ "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw=="
+ },
+ "node_modules/magic-bytes.js": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.7.0.tgz",
+ "integrity": "sha512-YzVU2+/hrjwx8xcgAw+ffNq3jkactpj+f1iSL4LonrFKhvnwDzHSqtFdk/MMRP53y9ScouJ7cKEnqYsJwsHoYA=="
+ },
+ "node_modules/ts-mixer": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.3.tgz",
+ "integrity": "sha512-k43M7uCG1AkTyxgnmI5MPwKoUvS/bRvLvUb7+Pgpdlmok8AoqmUaZxUUw8zKM5B1lqZrt41GjYgnvAi0fppqgQ=="
+ },
+ "node_modules/tslib": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
+ },
+ "node_modules/undici": {
+ "version": "5.27.2",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-5.27.2.tgz",
+ "integrity": "sha512-iS857PdOEy/y3wlM3yRp+6SNQQ6xU0mmZcwRSriqk+et/cwWAtwmIGf6WkoDN2EK/AMdCO/dfXzIwi+rFMrjjQ==",
+ "dependencies": {
+ "@fastify/busboy": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=14.0"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "5.26.5",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
+ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
+ },
+ "node_modules/ws": {
+ "version": "8.14.2",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz",
+ "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==",
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..7e1b655
--- /dev/null
+++ b/package.json
@@ -0,0 +1,15 @@
+{
+ "name": "tests",
+ "version": "1.0.0",
+ "description": "",
+ "main": "src/index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "author": "",
+ "license": "ISC",
+ "dependencies": {
+ "discord.js": "^14.14.1",
+ "dotenv": "^16.3.1"
+ }
+}
diff --git a/src/commands/StartServerCommand.js b/src/commands/StartServerCommand.js
new file mode 100644
index 0000000..4639c2e
--- /dev/null
+++ b/src/commands/StartServerCommand.js
@@ -0,0 +1,54 @@
+const { SlashCommandBuilder, EmbedBuilder } = require('discord.js')
+const fs = require('fs');
+
+class StartServerCommand {
+
+ data = new SlashCommandBuilder()
+ .setName('start')
+ .setDescription('Starts the minecraft server with the given name')
+ .addStringOption((opt) => opt
+ .setName('name')
+ .setDescription('Name of the server to start')
+ .setRequired(true));
+
+ async execute (interaction, syncs, iterations) {
+ const server = interaction.options.getString('name', true);
+ const issuer = interaction.user;
+
+ let data = fs.readFileSync('config.json', 'utf8');
+ data = JSON.parse(data);
+ let token = data.guilds[interaction.guildId];
+ let ws;
+ if (token) {
+ ws = syncs.get(token);
+ }
+
+ if (!ws || ws == null) {
+ var embed = new EmbedBuilder()
+ .setColor('#be2230')
+ .setTitle('Not connected')
+ .setAuthor({
+ name: 'Fork'
+ })
+ .setDescription(`Failed to start server ${server}. We are not connected to any Fork instance`);
+
+ await interaction.reply({ embeds: [embed], ephemeral: true });
+ return;
+ }
+
+ var embed = new EmbedBuilder()
+ .setColor('#d3902d')
+ .setTitle('Starting server')
+ .setAuthor({
+ name: 'Fork'
+ })
+ .setDescription(`Trying to start ${server}. Please wait`);
+
+ const response = await interaction.reply({ embeds: [embed], ephemeral: true, fetchReply: true });
+ iterations.set(response.id, interaction);
+
+ ws.send(`start|${server}|${response.id}`);
+ }
+}
+
+module.exports = StartServerCommand;
\ No newline at end of file
diff --git a/src/commands/StopServerCommand.js b/src/commands/StopServerCommand.js
new file mode 100644
index 0000000..a522a19
--- /dev/null
+++ b/src/commands/StopServerCommand.js
@@ -0,0 +1,54 @@
+const { SlashCommandBuilder, EmbedBuilder } = require('discord.js')
+const fs = require('fs');
+
+class StopServerCommand {
+
+ data = new SlashCommandBuilder()
+ .setName('stop')
+ .setDescription('Stops the minecraft server with the given name')
+ .addStringOption((opt) => opt
+ .setName('name')
+ .setDescription('Name of the server to stop')
+ .setRequired(true));
+
+ async execute (interaction, syncs, iterations) {
+ const server = interaction.options.getString('name', true);
+ const issuer = interaction.user;
+
+ let data = fs.readFileSync('config.json', 'utf8');
+ data = JSON.parse(data);
+ let token = data.guilds[interaction.guildId];
+ let ws;
+ if (token) {
+ ws = syncs.get(token);
+ }
+
+ if (!ws || ws == null) {
+ var embed = new EmbedBuilder()
+ .setColor('#be2230')
+ .setTitle('Not connected')
+ .setAuthor({
+ name: 'Fork'
+ })
+ .setDescription(`Failed to stop server ${server}. We are not connected to any Fork instance`);
+
+ await interaction.reply({ embeds: [embed], ephemeral: true });
+ return;
+ }
+
+ var embed = new EmbedBuilder()
+ .setColor('#d3902d')
+ .setTitle('Stopping server')
+ .setAuthor({
+ name: 'Fork'
+ })
+ .setDescription(`Trying to stop ${server}. Please wait`);
+
+ const response = await interaction.reply({ embeds: [embed], ephemeral: true, fetchReply: true });
+ iterations.set(response.id, interaction);
+
+ ws.send(`stop|${server}|${response.id}`);
+ }
+}
+
+module.exports = StopServerCommand;
\ No newline at end of file
diff --git a/src/commands/SyncServerCommand.js b/src/commands/SyncServerCommand.js
new file mode 100644
index 0000000..a92638b
--- /dev/null
+++ b/src/commands/SyncServerCommand.js
@@ -0,0 +1,65 @@
+const { SlashCommandBuilder, EmbedBuilder, PermissionFlagsBits } = require('discord.js');
+const fs = require('fs');
+
+class SyncServerCommand {
+
+ data = new SlashCommandBuilder()
+ .setName('sync')
+ .setDescription('Synchronizes the server with the fork instance')
+ .addStringOption((opt) => opt
+ .setName('token')
+ .setDescription('The fork generated token')
+ .setRequired(true))
+ .setDefaultMemberPermissions(PermissionFlagsBits.Administrator);
+
+ async execute (interaction, syncs, iterations, sockets) {
+ const token = interaction.options.getString('token', true);
+ const issuer = interaction.user;
+
+ if (syncs.get(token)) {
+ embed = new EmbedBuilder()
+ .setColor('#be2230')
+ .setTitle('Already synchronized')
+ .setAuthor({
+ name: 'Fork'
+ })
+ .setDescription('We are already synchronized with Fork');
+ return;
+ }
+
+ let data = fs.readFileSync('config.json', 'utf8');
+ let embed;
+ try {
+ let json = JSON.parse(data);
+ json.guilds[interaction.guildId] = token;
+
+ fs.writeFileSync('config.json', JSON.stringify(json));
+ embed = new EmbedBuilder()
+ .setColor('#72cc72')
+ .setTitle('Synchronized')
+ .setAuthor({
+ name: 'Fork'
+ })
+ .setDescription('Success! Your discord server and your fork instance are now connected. Thanks for using Fork');
+
+ let ws = sockets.get(token);
+ if (ws) {
+ console.info('Noticing websocket about connection...')
+ ws.send(`status|linked|${interaction.guild.name}`)
+ syncs.set(token, ws);
+ }
+ } catch (error) {
+ embed = new EmbedBuilder()
+ .setColor('#be2230')
+ .setTitle('Not synchronized')
+ .setAuthor({
+ name: 'Fork'
+ })
+ .setDescription('There was a problem while synchronizing your server and your fork instance');
+ }
+
+ await interaction.reply({ embeds: [embed], ephemeral: true });
+ }
+}
+
+module.exports = SyncServerCommand;
\ No newline at end of file
diff --git a/src/index.js b/src/index.js
new file mode 100644
index 0000000..5b6b6f8
--- /dev/null
+++ b/src/index.js
@@ -0,0 +1,250 @@
+require('dotenv').config();
+
+
+const { Client, REST, Routes, Events, ActivityType, IntentsBitField, Collection, EmbedBuilder } = require('discord.js');
+const WebSocket = require('ws');
+const https = require('https');
+const http = require('http');
+const fs = require('fs');
+const path = require('path');
+
+const token = process.env.DISCORD_BOT_TOKEN;
+const sockets = new Map();
+const syncs = new Map();
+const iterations = new Map();
+
+const client = new Client({
+ intents: [
+ IntentsBitField.Flags.Guilds,
+ IntentsBitField.Flags.GuildMessages,
+ IntentsBitField.Flags.GuildMessageReactions,
+ IntentsBitField.Flags.GuildMembers
+ ]
+});
+const rest = new REST({
+ version: 9
+}).setToken(token);
+
+const certPath = process.env.SSL_CERT_PATH;
+let server;
+if (fs.existsSync(certPath)) {
+ server = https.createServer({
+ pfx: fs.readFileSync(process.env.SSL_CERT_PATH),
+ passphrase: process.env.SSL_CERT_PASS
+ });
+} else {
+ server = http.createServer();
+}
+
+const ws = new WebSocket.Server({server});
+
+
+client.once(Events.ClientReady, function(c) {
+ console.log('Fork - Bot Loaded - ', c.user.tag);
+
+ client.user.setPresence({
+ activities: [
+ {
+ name: "Fork",
+ type: ActivityType.Playing
+ }
+ ],
+ status: 'online',
+ });
+
+ ws.on('connection', (connection) => {
+ connection.on('message', async(message) => {
+ if (!message) return;
+
+ message = Buffer.from(message).toString('utf8');
+ if (!message.includes('|')) {
+ return;
+ }
+ console.info(message);
+
+ let messageData = message.split('|');
+ let code = messageData[0];
+
+ switch (code) {
+ case 'login':
+ let providedToken = messageData[1];
+ let data = fs.readFileSync('config.json', 'utf8');
+ try {
+ data = JSON.parse(data);
+ for (const key in data.guilds) {
+ let guild = client.guilds.cache.get(key);
+ if (!guild) continue;
+
+ if (data.guilds[key] == providedToken) {
+ syncs.set(providedToken, connection);
+ connection.send(`status|linked|${guild.name}`)
+ connection.send('serverList|');
+ connection.send('playerList|');
+ }
+ }
+
+ sockets.set(providedToken, connection);
+ } catch (err) {
+ console.info(err);
+ }
+ break;
+ case 'notify':
+ let guildId = () => {
+ let token;
+ sockets.forEach((value, key) => {
+ if (value == connection) token = key;
+ });
+
+ let k;
+ let data = fs.readFileSync('config.json', 'utf8');
+ data = JSON.parse(data);
+
+ for (const key in data.guilds) {
+ let guild = client.guilds.cache.get(key);
+ if (!guild) continue;
+
+ if (data.guilds[key] == token) {
+ k = key;
+ }
+ }
+
+ return k;
+ }
+ let gId = guildId();
+ let guild = client.guilds.cache.get(gId);
+ if (!guild) return;
+
+ let serverName = messageData[1];
+ let messageId = messageData[2];
+ let action = messageData[3];
+ let resultCode = messageData[4];
+
+ let interaction = iterations.get(messageId);
+ //let message = await channel.messages.fetch(messageId);
+
+ var embed;
+ switch (resultCode) {
+ case "44":
+ embed = new EmbedBuilder()
+ .setColor('#be2230')
+ .setTitle('Not started')
+ .setAuthor({
+ name: 'Fork'
+ })
+ .setDescription(`Failed to start server ${serverName} because it does not exist`);
+ break;
+ case "40":
+ embed = new EmbedBuilder()
+ .setColor('#be2230')
+ .setTitle('Not started')
+ .setAuthor({
+ name: 'Fork'
+ });
+
+ if (action == "start") {
+ embed.setDescription(`Failed to start server ${serverName}. Probably it is already started`);
+ } else {
+ embed.setDescription(`Failed to stop server ${serverName}. Probably it is not started`);
+ }
+ break
+ case "20":
+ embed = new EmbedBuilder()
+ .setColor('#72cc72')
+ .setTitle('Started')
+ .setAuthor({
+ name: 'Fork'
+ });
+
+ if (action == "start") {
+ embed.setDescription(`Sending start task to server ${serverName}.`);
+ } else {
+ embed.setDescription(`Sending kill task to server ${serverName}.`);
+ }
+ break;
+ case "21":
+ embed = new EmbedBuilder()
+ .setColor('#72cc72')
+ .setTitle('Started')
+ .setAuthor({
+ name: 'Fork'
+ });
+
+ if (action == "start") {
+ embed.setDescription(`Successfully started server ${serverName}. It might take a few minutes to completely start`);
+ } else {
+ embed.setDescription(`Successfully stopped server ${serverName}. It might take a few seconds to complete`);
+ }
+ break;
+ }
+
+ if (resultCode != "20") {
+ iterations.delete(messageId);
+ }
+ return await interaction.editReply({ embeds: [embed], ephemeral: true });
+ }
+ });
+ });
+
+ server.listen(8181, () => {
+ console.info('Successfully started Fork websocket. SSL:', fs.existsSync(certPath))
+ });
+});
+
+client.on(Events.InteractionCreate, async interaction => {
+ if (interaction.isChatInputCommand()) {
+ const command = interaction.client.commands.get(interaction.commandName);
+
+ if (!command) {
+ console.error(`No command matching ${interaction.commandName} was found.`);
+ return;
+ }
+
+ try {
+ await command.execute(interaction, syncs, iterations, sockets);
+ } catch (error) {
+ console.error(error);
+ await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true });
+ }
+ }
+});
+
+const commands = [];
+client.commands = new Collection();
+
+console.info('Loading commands.');
+const commandsPath = path.join(__dirname, 'commands');
+const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));
+
+for (const file of commandFiles) {
+ const filePath = path.join(commandsPath, file);
+ const command = require(filePath);
+ let instance = new command();
+
+ if ('data' in instance && 'execute' in instance) {
+ if (instance.setClient != undefined) {
+ instance.setClient(client);
+ }
+
+ client.commands.set(instance.data.name, instance);
+ commands.push(instance.data.toJSON());
+ } else {
+ console.warn(`The command at ${filePath} is missing a required "data" or "execute" property.`);
+ }
+}
+
+client.login(token);
+
+(async () => {
+ try {
+ console.log(`Started refreshing ${commands.length} application (/) commands.`);
+
+ const data = await rest.put(
+ Routes.applicationCommands(process.env.DISCORD_BOT_ID),
+ { body: commands },
+ );
+
+ console.log(`Successfully reloaded ${data.length} application (/) commands.`);
+ } catch (error) {
+ console.error(error);
+ }
+})();
\ No newline at end of file
diff --git a/ssl/cert.pfx b/ssl/cert.pfx
new file mode 100644
index 0000000..3792a1b
Binary files /dev/null and b/ssl/cert.pfx differ