65 Commits

Author SHA1 Message Date
0d5c90323a 2023-02-12 12:25:53 +02:00
5b01b15216 Merge branch 'preview' of https://github.com/Wizzy69/DiscordBotWithAPI into preview 2023-01-31 16:08:02 +02:00
4f18f505f4 Updated to allow mention as command prefix. Updated DBCommand 2023-01-31 16:07:53 +02:00
2d3566a01a 2023-01-12 15:21:45 +02:00
22f2cd4e59 linux updater 2023-01-10 19:42:10 +02:00
1683234376 updater for linux is now working 2023-01-10 19:41:03 +02:00
69d99b4189 Updated Logger and message handler. Updated to latest Discord.Net version 2023-01-01 21:55:29 +02:00
4a5e0ef2f3 2022-12-17 12:38:21 +02:00
79731a9704 2022-12-17 12:35:26 +02:00
bd53d099d1 2022-12-09 14:49:05 +02:00
de61f5de88 2022-12-09 14:49:03 +02:00
0527d43dd2 patch 2022-12-09 14:46:10 +02:00
e3511cd96b 2022-11-18 10:45:43 +02:00
d355d3c9b7 2022-11-18 10:38:47 +02:00
5bb13aa4a6 The library can now be used for Windows exclusive bots (Made with WinForm or Wpf) 2022-11-13 16:28:44 +02:00
655f5e2ce0 2022-11-12 12:20:02 +02:00
9014d78a7d 2022-11-04 14:08:35 +02:00
1c026e7f49 patch 2022-11-02 19:42:58 +02:00
d32b3902c9 2022-11-02 18:59:33 +02:00
e5f3aff39a patch (database & slash commands) 2022-11-02 15:35:18 +02:00
11ec02ef68 Changed Config System 2022-10-25 21:37:52 +03:00
cad19935d5 Merge branch 'preview' of https://github.com/Wizzy69/DiscordBotWithAPI into preview 2022-10-23 20:11:47 +03:00
47f88f167f patch 2022-10-23 20:11:27 +03:00
9d6c335799 2022-10-23 11:08:46 +03:00
cbaf552e7a 2022-10-22 16:02:05 +03:00
a4975a4578 Merge branch 'preview' of https://github.com/Wizzy69/DiscordBotWithAPI into preview 2022-10-22 14:45:35 +03:00
725d02d152 2022-10-22 14:44:55 +03:00
ae7118e89a Update to Discord.Net 3.8.1 (API v10) 2022-10-22 13:55:48 +03:00
cad3bb5b75 2022-10-14 12:44:44 +03:00
269d7d56ff 2022-10-14 12:44:21 +03:00
403c023191 2022-10-14 11:13:09 +03:00
3f7a8e04d4 2022-10-14 11:06:56 +03:00
0abbd24b86 Code cleanup 2022-10-12 20:29:00 +03:00
21f1975fbc 2022-10-09 20:59:16 +03:00
d6f072904e patch 2022-10-09 20:26:39 +03:00
6fc491a0d6 2022-10-07 13:36:15 +03:00
7bc9db03f0 patch 2022-10-03 21:46:34 +03:00
641f0f2856 patch 2022-10-03 21:28:52 +03:00
ef5439d204 2022-10-01 20:59:46 +03:00
c2093c2aca added support for GUI 2022-10-01 20:59:08 +03:00
a39f7bb0c9 patch 2022-10-01 17:14:19 +03:00
6d73ec7f24 Linux compatibility update 2022-09-26 19:30:53 +03:00
24d4bee85b Merge branch 'preview' of https://github.com/Wizzy69/DiscordBotWithAPI into preview 2022-09-25 23:03:48 +03:00
a1bde013e6 2022-09-25 23:03:18 +03:00
23f951167b 2022-09-24 15:00:02 +03:00
26505fd5c9 2022-09-22 10:39:51 +03:00
28fff8db8a 2022-09-16 17:47:01 +03:00
fa15bc2333 Merge branch 'preview' of https://github.com/Wizzy69/DiscordBotWithAPI into preview 2022-09-16 17:37:08 +03:00
113c64279f 2022-09-16 17:37:01 +03:00
81cc6709d6 patch 2022-09-10 16:47:00 +03:00
571c0a5360 patch 2022-09-10 16:46:48 +03:00
Wizzy69
eefdea2de9 Delete .idea/.idea.SethDiscordBot/.idea directory 2022-09-09 17:18:28 +03:00
f7e6b0a398 DBCommand interface update & all other plugins were updated 2022-09-03 16:28:03 +03:00
68a83b052a Updater added 2022-08-28 12:59:41 +03:00
d689eee7fa 2022-08-26 10:42:15 +03:00
f6442af30c patch: listplugs, plugin version system and progress bar 2022-08-25 15:15:47 +03:00
b98f57fcf8 Merge branch 'preview' of https://github.com/Wizzy69/DiscordBotWithAPI into preview 2022-08-24 21:34:13 +03:00
77aad985fa Added a new ProgressBar type 2022-08-24 21:34:06 +03:00
Wizzy69
f8ebf76f92 Delete .idea/.idea.SethDiscordBot/.idea directory 2022-08-20 20:52:21 +03:00
6da9828e5c improved save method 2022-08-20 17:44:19 +03:00
3ba45790e7 Merge branch 'preview' of https://github.com/Wizzy69/DiscordBotWithAPI into preview 2022-08-17 20:31:55 +03:00
e440e97948 2022-08-17 20:31:52 +03:00
Wizzy69
938c73c810 Delete DiscordBotConsoleLauncher directory 2022-08-17 20:31:28 +03:00
a8520c8c96 fixed some bugs 2022-08-17 20:23:06 +03:00
debdc58646 The ability to remove a plugin has been added 2022-08-17 20:12:31 +03:00
101 changed files with 2888 additions and 5061 deletions

7
.gitignore vendored
View File

@@ -98,6 +98,7 @@ StyleCopReport.xml
*.pidb
*.svclog
*.scc
*.code-workspace
# Chutzpah Test files
_Chutzpah*
@@ -364,3 +365,9 @@ MigrationBackup/
FodyWeavers.xsd
*.txt
#folders
/Plugins/
/DiscordBot.rar
/DiscordBot/Data/
/DiscordBot/Updater/

View File

@@ -1,13 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Rider ignored files
/projectSettingsUpdater.xml
/contentModel.xml
/.idea.SethDiscordBot.iml
/modules.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@@ -1 +0,0 @@
SethDiscordBot

View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
</project>

View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="UserContentModel">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,268 +0,0 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v5.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v5.0": {
"CMD_LevelingSystem/1.0.0": {
"dependencies": {
"PluginManager": "1.0.0"
},
"runtime": {
"CMD_LevelingSystem.dll": {}
}
},
"Discord.Net/3.5.0": {
"dependencies": {
"Discord.Net.Commands": "3.5.0",
"Discord.Net.Core": "3.5.0",
"Discord.Net.Interactions": "3.5.0",
"Discord.Net.Rest": "3.5.0",
"Discord.Net.WebSocket": "3.5.0",
"Discord.Net.Webhook": "3.5.0"
}
},
"Discord.Net.Commands/3.5.0": {
"dependencies": {
"Discord.Net.Core": "3.5.0"
},
"runtime": {
"lib/net5.0/Discord.Net.Commands.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"Discord.Net.Core/3.5.0": {
"dependencies": {
"Newtonsoft.Json": "13.0.1",
"System.Collections.Immutable": "5.0.0",
"System.Interactive.Async": "5.0.0",
"System.ValueTuple": "4.5.0"
},
"runtime": {
"lib/net5.0/Discord.Net.Core.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"Discord.Net.Interactions/3.5.0": {
"dependencies": {
"Discord.Net.Core": "3.5.0",
"Discord.Net.Rest": "3.5.0",
"Discord.Net.WebSocket": "3.5.0",
"Microsoft.Extensions.DependencyInjection.Abstractions": "5.0.0",
"System.Collections.Immutable": "5.0.0",
"System.Reactive": "5.0.0"
},
"runtime": {
"lib/net5.0/Discord.Net.Interactions.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"Discord.Net.Rest/3.5.0": {
"dependencies": {
"Discord.Net.Core": "3.5.0"
},
"runtime": {
"lib/net5.0/Discord.Net.Rest.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"Discord.Net.Webhook/3.5.0": {
"dependencies": {
"Discord.Net.Core": "3.5.0",
"Discord.Net.Rest": "3.5.0"
},
"runtime": {
"lib/net5.0/Discord.Net.Webhook.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"Discord.Net.WebSocket/3.5.0": {
"dependencies": {
"Discord.Net.Core": "3.5.0",
"Discord.Net.Rest": "3.5.0"
},
"runtime": {
"lib/net5.0/Discord.Net.WebSocket.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions/5.0.0": {
"runtime": {
"lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.20.51904"
}
}
},
"Newtonsoft.Json/13.0.1": {
"runtime": {
"lib/netstandard2.0/Newtonsoft.Json.dll": {
"assemblyVersion": "13.0.0.0",
"fileVersion": "13.0.1.25517"
}
}
},
"System.Collections.Immutable/5.0.0": {},
"System.Interactive.Async/5.0.0": {
"dependencies": {
"System.Linq.Async": "5.0.0"
},
"runtime": {
"lib/netcoreapp3.1/System.Interactive.Async.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.0.1"
}
}
},
"System.Linq.Async/5.0.0": {
"runtime": {
"lib/netcoreapp3.1/System.Linq.Async.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.0.1"
}
}
},
"System.Reactive/5.0.0": {
"runtime": {
"lib/net5.0/System.Reactive.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.0.1"
}
}
},
"System.ValueTuple/4.5.0": {},
"PluginManager/1.0.0": {
"dependencies": {
"Discord.Net": "3.5.0"
},
"runtime": {
"PluginManager.dll": {}
}
}
}
},
"libraries": {
"CMD_LevelingSystem/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Discord.Net/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-IUtexpvogudb1rllKBWkIEpBVQoToMjtVo81KPkt+gNMe7KtRDcZJgcn6+72viMtyw0e95OJPXFV5VEA/n2OQQ==",
"path": "discord.net/3.5.0",
"hashPath": "discord.net.3.5.0.nupkg.sha512"
},
"Discord.Net.Commands/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ClTv8aiTlitvS48YatRiTLvgE2f2uKgmHNPVBIuvJBHZO2u4bZCzoN1fid+pZn2sbVOkt8uftlLGzz5DSZlFIA==",
"path": "discord.net.commands/3.5.0",
"hashPath": "discord.net.commands.3.5.0.nupkg.sha512"
},
"Discord.Net.Core/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-rCzzaznMVQ+bLMxOpYwTyqm9V22kMy6BxlQisSxemHZDe2Jedz3Clp/a0dToACLz+Dlp3u+jYUfCBnTz7L6f4g==",
"path": "discord.net.core/3.5.0",
"hashPath": "discord.net.core.3.5.0.nupkg.sha512"
},
"Discord.Net.Interactions/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-wE9+V9DJ7r+1s4euOi4sGPIAt4sD7r+Tk5s9mrlbLCHVQTK4KllAvcrL25bPFI38FuFceREEzFoRlTrekSyB2Q==",
"path": "discord.net.interactions/3.5.0",
"hashPath": "discord.net.interactions.3.5.0.nupkg.sha512"
},
"Discord.Net.Rest/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-BnTdLFuuQsKvCv08VQrD4X1Hw2Xp+MELIRQiDiKfG01IiQlRTN+1gc3LB1zXgn5xBvC0HXjHxwV22GrMD9uKHQ==",
"path": "discord.net.rest/3.5.0",
"hashPath": "discord.net.rest.3.5.0.nupkg.sha512"
},
"Discord.Net.Webhook/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-vCIGZS+m88sQDuFmdbUqg+2RIXS/NJWx8ei3MX+ZEYiAvOkDgQfkIlEnU1NKpds6ivTt5GFlv6UzcWubb5VJ1w==",
"path": "discord.net.webhook/3.5.0",
"hashPath": "discord.net.webhook.3.5.0.nupkg.sha512"
},
"Discord.Net.WebSocket/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-LjBOvcP40vJ+dhOtBDi8haEeblPAKpAIqR04NBzTM1/0RVavJZH89ovfSQIk42ygkiOaDV4E2x0Mmh6DRoIYcw==",
"path": "discord.net.websocket/3.5.0",
"hashPath": "discord.net.websocket.3.5.0.nupkg.sha512"
},
"Microsoft.Extensions.DependencyInjection.Abstractions/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ORj7Zh81gC69TyvmcUm9tSzytcy8AVousi+IVRAI8nLieQjOFryRusSFh7+aLk16FN9pQNqJAiMd7BTKINK0kA==",
"path": "microsoft.extensions.dependencyinjection.abstractions/5.0.0",
"hashPath": "microsoft.extensions.dependencyinjection.abstractions.5.0.0.nupkg.sha512"
},
"Newtonsoft.Json/13.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==",
"path": "newtonsoft.json/13.0.1",
"hashPath": "newtonsoft.json.13.0.1.nupkg.sha512"
},
"System.Collections.Immutable/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-FXkLXiK0sVVewcso0imKQoOxjoPAj42R8HtjjbSjVPAzwDfzoyoznWxgA3c38LDbN9SJux1xXoXYAhz98j7r2g==",
"path": "system.collections.immutable/5.0.0",
"hashPath": "system.collections.immutable.5.0.0.nupkg.sha512"
},
"System.Interactive.Async/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-QaqhQVDiULcu4vm6o89+iP329HcK44cETHOYgy/jfEjtzeFy0ZxmuM7nel9ocjnKxEM4yh1mli7hgh8Q9o+/Iw==",
"path": "system.interactive.async/5.0.0",
"hashPath": "system.interactive.async.5.0.0.nupkg.sha512"
},
"System.Linq.Async/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-cPtIuuH8TIjVHSi2ewwReWGW1PfChPE0LxPIDlfwVcLuTM9GANFTXiMB7k3aC4sk3f0cQU25LNKzx+jZMxijqw==",
"path": "system.linq.async/5.0.0",
"hashPath": "system.linq.async.5.0.0.nupkg.sha512"
},
"System.Reactive/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ==",
"path": "system.reactive/5.0.0",
"hashPath": "system.reactive.5.0.0.nupkg.sha512"
},
"System.ValueTuple/4.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ==",
"path": "system.valuetuple/4.5.0",
"hashPath": "system.valuetuple.4.5.0.nupkg.sha512"
},
"PluginManager/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
}
}
}

Binary file not shown.

View File

@@ -1,268 +0,0 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v5.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v5.0": {
"CMD_Utils/1.0.0": {
"dependencies": {
"PluginManager": "1.0.0"
},
"runtime": {
"CMD_Utils.dll": {}
}
},
"Discord.Net/3.5.0": {
"dependencies": {
"Discord.Net.Commands": "3.5.0",
"Discord.Net.Core": "3.5.0",
"Discord.Net.Interactions": "3.5.0",
"Discord.Net.Rest": "3.5.0",
"Discord.Net.WebSocket": "3.5.0",
"Discord.Net.Webhook": "3.5.0"
}
},
"Discord.Net.Commands/3.5.0": {
"dependencies": {
"Discord.Net.Core": "3.5.0"
},
"runtime": {
"lib/net5.0/Discord.Net.Commands.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"Discord.Net.Core/3.5.0": {
"dependencies": {
"Newtonsoft.Json": "13.0.1",
"System.Collections.Immutable": "5.0.0",
"System.Interactive.Async": "5.0.0",
"System.ValueTuple": "4.5.0"
},
"runtime": {
"lib/net5.0/Discord.Net.Core.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"Discord.Net.Interactions/3.5.0": {
"dependencies": {
"Discord.Net.Core": "3.5.0",
"Discord.Net.Rest": "3.5.0",
"Discord.Net.WebSocket": "3.5.0",
"Microsoft.Extensions.DependencyInjection.Abstractions": "5.0.0",
"System.Collections.Immutable": "5.0.0",
"System.Reactive": "5.0.0"
},
"runtime": {
"lib/net5.0/Discord.Net.Interactions.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"Discord.Net.Rest/3.5.0": {
"dependencies": {
"Discord.Net.Core": "3.5.0"
},
"runtime": {
"lib/net5.0/Discord.Net.Rest.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"Discord.Net.Webhook/3.5.0": {
"dependencies": {
"Discord.Net.Core": "3.5.0",
"Discord.Net.Rest": "3.5.0"
},
"runtime": {
"lib/net5.0/Discord.Net.Webhook.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"Discord.Net.WebSocket/3.5.0": {
"dependencies": {
"Discord.Net.Core": "3.5.0",
"Discord.Net.Rest": "3.5.0"
},
"runtime": {
"lib/net5.0/Discord.Net.WebSocket.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions/5.0.0": {
"runtime": {
"lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.20.51904"
}
}
},
"Newtonsoft.Json/13.0.1": {
"runtime": {
"lib/netstandard2.0/Newtonsoft.Json.dll": {
"assemblyVersion": "13.0.0.0",
"fileVersion": "13.0.1.25517"
}
}
},
"System.Collections.Immutable/5.0.0": {},
"System.Interactive.Async/5.0.0": {
"dependencies": {
"System.Linq.Async": "5.0.0"
},
"runtime": {
"lib/netcoreapp3.1/System.Interactive.Async.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.0.1"
}
}
},
"System.Linq.Async/5.0.0": {
"runtime": {
"lib/netcoreapp3.1/System.Linq.Async.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.0.1"
}
}
},
"System.Reactive/5.0.0": {
"runtime": {
"lib/net5.0/System.Reactive.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.0.1"
}
}
},
"System.ValueTuple/4.5.0": {},
"PluginManager/1.0.0": {
"dependencies": {
"Discord.Net": "3.5.0"
},
"runtime": {
"PluginManager.dll": {}
}
}
}
},
"libraries": {
"CMD_Utils/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Discord.Net/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-IUtexpvogudb1rllKBWkIEpBVQoToMjtVo81KPkt+gNMe7KtRDcZJgcn6+72viMtyw0e95OJPXFV5VEA/n2OQQ==",
"path": "discord.net/3.5.0",
"hashPath": "discord.net.3.5.0.nupkg.sha512"
},
"Discord.Net.Commands/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ClTv8aiTlitvS48YatRiTLvgE2f2uKgmHNPVBIuvJBHZO2u4bZCzoN1fid+pZn2sbVOkt8uftlLGzz5DSZlFIA==",
"path": "discord.net.commands/3.5.0",
"hashPath": "discord.net.commands.3.5.0.nupkg.sha512"
},
"Discord.Net.Core/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-rCzzaznMVQ+bLMxOpYwTyqm9V22kMy6BxlQisSxemHZDe2Jedz3Clp/a0dToACLz+Dlp3u+jYUfCBnTz7L6f4g==",
"path": "discord.net.core/3.5.0",
"hashPath": "discord.net.core.3.5.0.nupkg.sha512"
},
"Discord.Net.Interactions/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-wE9+V9DJ7r+1s4euOi4sGPIAt4sD7r+Tk5s9mrlbLCHVQTK4KllAvcrL25bPFI38FuFceREEzFoRlTrekSyB2Q==",
"path": "discord.net.interactions/3.5.0",
"hashPath": "discord.net.interactions.3.5.0.nupkg.sha512"
},
"Discord.Net.Rest/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-BnTdLFuuQsKvCv08VQrD4X1Hw2Xp+MELIRQiDiKfG01IiQlRTN+1gc3LB1zXgn5xBvC0HXjHxwV22GrMD9uKHQ==",
"path": "discord.net.rest/3.5.0",
"hashPath": "discord.net.rest.3.5.0.nupkg.sha512"
},
"Discord.Net.Webhook/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-vCIGZS+m88sQDuFmdbUqg+2RIXS/NJWx8ei3MX+ZEYiAvOkDgQfkIlEnU1NKpds6ivTt5GFlv6UzcWubb5VJ1w==",
"path": "discord.net.webhook/3.5.0",
"hashPath": "discord.net.webhook.3.5.0.nupkg.sha512"
},
"Discord.Net.WebSocket/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-LjBOvcP40vJ+dhOtBDi8haEeblPAKpAIqR04NBzTM1/0RVavJZH89ovfSQIk42ygkiOaDV4E2x0Mmh6DRoIYcw==",
"path": "discord.net.websocket/3.5.0",
"hashPath": "discord.net.websocket.3.5.0.nupkg.sha512"
},
"Microsoft.Extensions.DependencyInjection.Abstractions/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ORj7Zh81gC69TyvmcUm9tSzytcy8AVousi+IVRAI8nLieQjOFryRusSFh7+aLk16FN9pQNqJAiMd7BTKINK0kA==",
"path": "microsoft.extensions.dependencyinjection.abstractions/5.0.0",
"hashPath": "microsoft.extensions.dependencyinjection.abstractions.5.0.0.nupkg.sha512"
},
"Newtonsoft.Json/13.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==",
"path": "newtonsoft.json/13.0.1",
"hashPath": "newtonsoft.json.13.0.1.nupkg.sha512"
},
"System.Collections.Immutable/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-FXkLXiK0sVVewcso0imKQoOxjoPAj42R8HtjjbSjVPAzwDfzoyoznWxgA3c38LDbN9SJux1xXoXYAhz98j7r2g==",
"path": "system.collections.immutable/5.0.0",
"hashPath": "system.collections.immutable.5.0.0.nupkg.sha512"
},
"System.Interactive.Async/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-QaqhQVDiULcu4vm6o89+iP329HcK44cETHOYgy/jfEjtzeFy0ZxmuM7nel9ocjnKxEM4yh1mli7hgh8Q9o+/Iw==",
"path": "system.interactive.async/5.0.0",
"hashPath": "system.interactive.async.5.0.0.nupkg.sha512"
},
"System.Linq.Async/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-cPtIuuH8TIjVHSi2ewwReWGW1PfChPE0LxPIDlfwVcLuTM9GANFTXiMB7k3aC4sk3f0cQU25LNKzx+jZMxijqw==",
"path": "system.linq.async/5.0.0",
"hashPath": "system.linq.async.5.0.0.nupkg.sha512"
},
"System.Reactive/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ==",
"path": "system.reactive/5.0.0",
"hashPath": "system.reactive.5.0.0.nupkg.sha512"
},
"System.ValueTuple/4.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ==",
"path": "system.valuetuple/4.5.0",
"hashPath": "system.valuetuple.4.5.0.nupkg.sha512"
},
"PluginManager/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
}
}
}

Binary file not shown.

View File

@@ -1,268 +0,0 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v5.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v5.0": {
"EVE_LevelingSystem/1.0.0": {
"dependencies": {
"PluginManager": "1.0.0"
},
"runtime": {
"EVE_LevelingSystem.dll": {}
}
},
"Discord.Net/3.5.0": {
"dependencies": {
"Discord.Net.Commands": "3.5.0",
"Discord.Net.Core": "3.5.0",
"Discord.Net.Interactions": "3.5.0",
"Discord.Net.Rest": "3.5.0",
"Discord.Net.WebSocket": "3.5.0",
"Discord.Net.Webhook": "3.5.0"
}
},
"Discord.Net.Commands/3.5.0": {
"dependencies": {
"Discord.Net.Core": "3.5.0"
},
"runtime": {
"lib/net5.0/Discord.Net.Commands.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"Discord.Net.Core/3.5.0": {
"dependencies": {
"Newtonsoft.Json": "13.0.1",
"System.Collections.Immutable": "5.0.0",
"System.Interactive.Async": "5.0.0",
"System.ValueTuple": "4.5.0"
},
"runtime": {
"lib/net5.0/Discord.Net.Core.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"Discord.Net.Interactions/3.5.0": {
"dependencies": {
"Discord.Net.Core": "3.5.0",
"Discord.Net.Rest": "3.5.0",
"Discord.Net.WebSocket": "3.5.0",
"Microsoft.Extensions.DependencyInjection.Abstractions": "5.0.0",
"System.Collections.Immutable": "5.0.0",
"System.Reactive": "5.0.0"
},
"runtime": {
"lib/net5.0/Discord.Net.Interactions.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"Discord.Net.Rest/3.5.0": {
"dependencies": {
"Discord.Net.Core": "3.5.0"
},
"runtime": {
"lib/net5.0/Discord.Net.Rest.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"Discord.Net.Webhook/3.5.0": {
"dependencies": {
"Discord.Net.Core": "3.5.0",
"Discord.Net.Rest": "3.5.0"
},
"runtime": {
"lib/net5.0/Discord.Net.Webhook.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"Discord.Net.WebSocket/3.5.0": {
"dependencies": {
"Discord.Net.Core": "3.5.0",
"Discord.Net.Rest": "3.5.0"
},
"runtime": {
"lib/net5.0/Discord.Net.WebSocket.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions/5.0.0": {
"runtime": {
"lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.20.51904"
}
}
},
"Newtonsoft.Json/13.0.1": {
"runtime": {
"lib/netstandard2.0/Newtonsoft.Json.dll": {
"assemblyVersion": "13.0.0.0",
"fileVersion": "13.0.1.25517"
}
}
},
"System.Collections.Immutable/5.0.0": {},
"System.Interactive.Async/5.0.0": {
"dependencies": {
"System.Linq.Async": "5.0.0"
},
"runtime": {
"lib/netcoreapp3.1/System.Interactive.Async.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.0.1"
}
}
},
"System.Linq.Async/5.0.0": {
"runtime": {
"lib/netcoreapp3.1/System.Linq.Async.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.0.1"
}
}
},
"System.Reactive/5.0.0": {
"runtime": {
"lib/net5.0/System.Reactive.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.0.1"
}
}
},
"System.ValueTuple/4.5.0": {},
"PluginManager/1.0.0": {
"dependencies": {
"Discord.Net": "3.5.0"
},
"runtime": {
"PluginManager.dll": {}
}
}
}
},
"libraries": {
"EVE_LevelingSystem/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Discord.Net/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-IUtexpvogudb1rllKBWkIEpBVQoToMjtVo81KPkt+gNMe7KtRDcZJgcn6+72viMtyw0e95OJPXFV5VEA/n2OQQ==",
"path": "discord.net/3.5.0",
"hashPath": "discord.net.3.5.0.nupkg.sha512"
},
"Discord.Net.Commands/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ClTv8aiTlitvS48YatRiTLvgE2f2uKgmHNPVBIuvJBHZO2u4bZCzoN1fid+pZn2sbVOkt8uftlLGzz5DSZlFIA==",
"path": "discord.net.commands/3.5.0",
"hashPath": "discord.net.commands.3.5.0.nupkg.sha512"
},
"Discord.Net.Core/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-rCzzaznMVQ+bLMxOpYwTyqm9V22kMy6BxlQisSxemHZDe2Jedz3Clp/a0dToACLz+Dlp3u+jYUfCBnTz7L6f4g==",
"path": "discord.net.core/3.5.0",
"hashPath": "discord.net.core.3.5.0.nupkg.sha512"
},
"Discord.Net.Interactions/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-wE9+V9DJ7r+1s4euOi4sGPIAt4sD7r+Tk5s9mrlbLCHVQTK4KllAvcrL25bPFI38FuFceREEzFoRlTrekSyB2Q==",
"path": "discord.net.interactions/3.5.0",
"hashPath": "discord.net.interactions.3.5.0.nupkg.sha512"
},
"Discord.Net.Rest/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-BnTdLFuuQsKvCv08VQrD4X1Hw2Xp+MELIRQiDiKfG01IiQlRTN+1gc3LB1zXgn5xBvC0HXjHxwV22GrMD9uKHQ==",
"path": "discord.net.rest/3.5.0",
"hashPath": "discord.net.rest.3.5.0.nupkg.sha512"
},
"Discord.Net.Webhook/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-vCIGZS+m88sQDuFmdbUqg+2RIXS/NJWx8ei3MX+ZEYiAvOkDgQfkIlEnU1NKpds6ivTt5GFlv6UzcWubb5VJ1w==",
"path": "discord.net.webhook/3.5.0",
"hashPath": "discord.net.webhook.3.5.0.nupkg.sha512"
},
"Discord.Net.WebSocket/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-LjBOvcP40vJ+dhOtBDi8haEeblPAKpAIqR04NBzTM1/0RVavJZH89ovfSQIk42ygkiOaDV4E2x0Mmh6DRoIYcw==",
"path": "discord.net.websocket/3.5.0",
"hashPath": "discord.net.websocket.3.5.0.nupkg.sha512"
},
"Microsoft.Extensions.DependencyInjection.Abstractions/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ORj7Zh81gC69TyvmcUm9tSzytcy8AVousi+IVRAI8nLieQjOFryRusSFh7+aLk16FN9pQNqJAiMd7BTKINK0kA==",
"path": "microsoft.extensions.dependencyinjection.abstractions/5.0.0",
"hashPath": "microsoft.extensions.dependencyinjection.abstractions.5.0.0.nupkg.sha512"
},
"Newtonsoft.Json/13.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==",
"path": "newtonsoft.json/13.0.1",
"hashPath": "newtonsoft.json.13.0.1.nupkg.sha512"
},
"System.Collections.Immutable/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-FXkLXiK0sVVewcso0imKQoOxjoPAj42R8HtjjbSjVPAzwDfzoyoznWxgA3c38LDbN9SJux1xXoXYAhz98j7r2g==",
"path": "system.collections.immutable/5.0.0",
"hashPath": "system.collections.immutable.5.0.0.nupkg.sha512"
},
"System.Interactive.Async/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-QaqhQVDiULcu4vm6o89+iP329HcK44cETHOYgy/jfEjtzeFy0ZxmuM7nel9ocjnKxEM4yh1mli7hgh8Q9o+/Iw==",
"path": "system.interactive.async/5.0.0",
"hashPath": "system.interactive.async.5.0.0.nupkg.sha512"
},
"System.Linq.Async/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-cPtIuuH8TIjVHSi2ewwReWGW1PfChPE0LxPIDlfwVcLuTM9GANFTXiMB7k3aC4sk3f0cQU25LNKzx+jZMxijqw==",
"path": "system.linq.async/5.0.0",
"hashPath": "system.linq.async.5.0.0.nupkg.sha512"
},
"System.Reactive/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ==",
"path": "system.reactive/5.0.0",
"hashPath": "system.reactive.5.0.0.nupkg.sha512"
},
"System.ValueTuple/4.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ==",
"path": "system.valuetuple/4.5.0",
"hashPath": "system.valuetuple.4.5.0.nupkg.sha512"
},
"PluginManager/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
}
}
}

Binary file not shown.

View File

@@ -1,268 +0,0 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v5.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v5.0": {
"MusicCommands/1.0.0": {
"dependencies": {
"PluginManager": "1.0.0"
},
"runtime": {
"MusicCommands.dll": {}
}
},
"Discord.Net/3.5.0": {
"dependencies": {
"Discord.Net.Commands": "3.5.0",
"Discord.Net.Core": "3.5.0",
"Discord.Net.Interactions": "3.5.0",
"Discord.Net.Rest": "3.5.0",
"Discord.Net.WebSocket": "3.5.0",
"Discord.Net.Webhook": "3.5.0"
}
},
"Discord.Net.Commands/3.5.0": {
"dependencies": {
"Discord.Net.Core": "3.5.0"
},
"runtime": {
"lib/net5.0/Discord.Net.Commands.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"Discord.Net.Core/3.5.0": {
"dependencies": {
"Newtonsoft.Json": "13.0.1",
"System.Collections.Immutable": "5.0.0",
"System.Interactive.Async": "5.0.0",
"System.ValueTuple": "4.5.0"
},
"runtime": {
"lib/net5.0/Discord.Net.Core.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"Discord.Net.Interactions/3.5.0": {
"dependencies": {
"Discord.Net.Core": "3.5.0",
"Discord.Net.Rest": "3.5.0",
"Discord.Net.WebSocket": "3.5.0",
"Microsoft.Extensions.DependencyInjection.Abstractions": "5.0.0",
"System.Collections.Immutable": "5.0.0",
"System.Reactive": "5.0.0"
},
"runtime": {
"lib/net5.0/Discord.Net.Interactions.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"Discord.Net.Rest/3.5.0": {
"dependencies": {
"Discord.Net.Core": "3.5.0"
},
"runtime": {
"lib/net5.0/Discord.Net.Rest.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"Discord.Net.Webhook/3.5.0": {
"dependencies": {
"Discord.Net.Core": "3.5.0",
"Discord.Net.Rest": "3.5.0"
},
"runtime": {
"lib/net5.0/Discord.Net.Webhook.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"Discord.Net.WebSocket/3.5.0": {
"dependencies": {
"Discord.Net.Core": "3.5.0",
"Discord.Net.Rest": "3.5.0"
},
"runtime": {
"lib/net5.0/Discord.Net.WebSocket.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions/5.0.0": {
"runtime": {
"lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.20.51904"
}
}
},
"Newtonsoft.Json/13.0.1": {
"runtime": {
"lib/netstandard2.0/Newtonsoft.Json.dll": {
"assemblyVersion": "13.0.0.0",
"fileVersion": "13.0.1.25517"
}
}
},
"System.Collections.Immutable/5.0.0": {},
"System.Interactive.Async/5.0.0": {
"dependencies": {
"System.Linq.Async": "5.0.0"
},
"runtime": {
"lib/netcoreapp3.1/System.Interactive.Async.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.0.1"
}
}
},
"System.Linq.Async/5.0.0": {
"runtime": {
"lib/netcoreapp3.1/System.Linq.Async.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.0.1"
}
}
},
"System.Reactive/5.0.0": {
"runtime": {
"lib/net5.0/System.Reactive.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.0.1"
}
}
},
"System.ValueTuple/4.5.0": {},
"PluginManager/1.0.0": {
"dependencies": {
"Discord.Net": "3.5.0"
},
"runtime": {
"PluginManager.dll": {}
}
}
}
},
"libraries": {
"MusicCommands/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Discord.Net/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-IUtexpvogudb1rllKBWkIEpBVQoToMjtVo81KPkt+gNMe7KtRDcZJgcn6+72viMtyw0e95OJPXFV5VEA/n2OQQ==",
"path": "discord.net/3.5.0",
"hashPath": "discord.net.3.5.0.nupkg.sha512"
},
"Discord.Net.Commands/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ClTv8aiTlitvS48YatRiTLvgE2f2uKgmHNPVBIuvJBHZO2u4bZCzoN1fid+pZn2sbVOkt8uftlLGzz5DSZlFIA==",
"path": "discord.net.commands/3.5.0",
"hashPath": "discord.net.commands.3.5.0.nupkg.sha512"
},
"Discord.Net.Core/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-rCzzaznMVQ+bLMxOpYwTyqm9V22kMy6BxlQisSxemHZDe2Jedz3Clp/a0dToACLz+Dlp3u+jYUfCBnTz7L6f4g==",
"path": "discord.net.core/3.5.0",
"hashPath": "discord.net.core.3.5.0.nupkg.sha512"
},
"Discord.Net.Interactions/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-wE9+V9DJ7r+1s4euOi4sGPIAt4sD7r+Tk5s9mrlbLCHVQTK4KllAvcrL25bPFI38FuFceREEzFoRlTrekSyB2Q==",
"path": "discord.net.interactions/3.5.0",
"hashPath": "discord.net.interactions.3.5.0.nupkg.sha512"
},
"Discord.Net.Rest/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-BnTdLFuuQsKvCv08VQrD4X1Hw2Xp+MELIRQiDiKfG01IiQlRTN+1gc3LB1zXgn5xBvC0HXjHxwV22GrMD9uKHQ==",
"path": "discord.net.rest/3.5.0",
"hashPath": "discord.net.rest.3.5.0.nupkg.sha512"
},
"Discord.Net.Webhook/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-vCIGZS+m88sQDuFmdbUqg+2RIXS/NJWx8ei3MX+ZEYiAvOkDgQfkIlEnU1NKpds6ivTt5GFlv6UzcWubb5VJ1w==",
"path": "discord.net.webhook/3.5.0",
"hashPath": "discord.net.webhook.3.5.0.nupkg.sha512"
},
"Discord.Net.WebSocket/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-LjBOvcP40vJ+dhOtBDi8haEeblPAKpAIqR04NBzTM1/0RVavJZH89ovfSQIk42ygkiOaDV4E2x0Mmh6DRoIYcw==",
"path": "discord.net.websocket/3.5.0",
"hashPath": "discord.net.websocket.3.5.0.nupkg.sha512"
},
"Microsoft.Extensions.DependencyInjection.Abstractions/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ORj7Zh81gC69TyvmcUm9tSzytcy8AVousi+IVRAI8nLieQjOFryRusSFh7+aLk16FN9pQNqJAiMd7BTKINK0kA==",
"path": "microsoft.extensions.dependencyinjection.abstractions/5.0.0",
"hashPath": "microsoft.extensions.dependencyinjection.abstractions.5.0.0.nupkg.sha512"
},
"Newtonsoft.Json/13.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==",
"path": "newtonsoft.json/13.0.1",
"hashPath": "newtonsoft.json.13.0.1.nupkg.sha512"
},
"System.Collections.Immutable/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-FXkLXiK0sVVewcso0imKQoOxjoPAj42R8HtjjbSjVPAzwDfzoyoznWxgA3c38LDbN9SJux1xXoXYAhz98j7r2g==",
"path": "system.collections.immutable/5.0.0",
"hashPath": "system.collections.immutable.5.0.0.nupkg.sha512"
},
"System.Interactive.Async/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-QaqhQVDiULcu4vm6o89+iP329HcK44cETHOYgy/jfEjtzeFy0ZxmuM7nel9ocjnKxEM4yh1mli7hgh8Q9o+/Iw==",
"path": "system.interactive.async/5.0.0",
"hashPath": "system.interactive.async.5.0.0.nupkg.sha512"
},
"System.Linq.Async/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-cPtIuuH8TIjVHSi2ewwReWGW1PfChPE0LxPIDlfwVcLuTM9GANFTXiMB7k3aC4sk3f0cQU25LNKzx+jZMxijqw==",
"path": "system.linq.async/5.0.0",
"hashPath": "system.linq.async.5.0.0.nupkg.sha512"
},
"System.Reactive/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ==",
"path": "system.reactive/5.0.0",
"hashPath": "system.reactive.5.0.0.nupkg.sha512"
},
"System.ValueTuple/4.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ==",
"path": "system.valuetuple/4.5.0",
"hashPath": "system.valuetuple.4.5.0.nupkg.sha512"
},
"PluginManager/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
}
}
}

Binary file not shown.

Binary file not shown.

View File

@@ -1,268 +0,0 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v5.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v5.0": {
"StartupEvents/1.0.0": {
"dependencies": {
"PluginManager": "1.0.0"
},
"runtime": {
"StartupEvents.dll": {}
}
},
"Discord.Net/3.5.0": {
"dependencies": {
"Discord.Net.Commands": "3.5.0",
"Discord.Net.Core": "3.5.0",
"Discord.Net.Interactions": "3.5.0",
"Discord.Net.Rest": "3.5.0",
"Discord.Net.WebSocket": "3.5.0",
"Discord.Net.Webhook": "3.5.0"
}
},
"Discord.Net.Commands/3.5.0": {
"dependencies": {
"Discord.Net.Core": "3.5.0"
},
"runtime": {
"lib/net5.0/Discord.Net.Commands.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"Discord.Net.Core/3.5.0": {
"dependencies": {
"Newtonsoft.Json": "13.0.1",
"System.Collections.Immutable": "5.0.0",
"System.Interactive.Async": "5.0.0",
"System.ValueTuple": "4.5.0"
},
"runtime": {
"lib/net5.0/Discord.Net.Core.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"Discord.Net.Interactions/3.5.0": {
"dependencies": {
"Discord.Net.Core": "3.5.0",
"Discord.Net.Rest": "3.5.0",
"Discord.Net.WebSocket": "3.5.0",
"Microsoft.Extensions.DependencyInjection.Abstractions": "5.0.0",
"System.Collections.Immutable": "5.0.0",
"System.Reactive": "5.0.0"
},
"runtime": {
"lib/net5.0/Discord.Net.Interactions.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"Discord.Net.Rest/3.5.0": {
"dependencies": {
"Discord.Net.Core": "3.5.0"
},
"runtime": {
"lib/net5.0/Discord.Net.Rest.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"Discord.Net.Webhook/3.5.0": {
"dependencies": {
"Discord.Net.Core": "3.5.0",
"Discord.Net.Rest": "3.5.0"
},
"runtime": {
"lib/net5.0/Discord.Net.Webhook.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"Discord.Net.WebSocket/3.5.0": {
"dependencies": {
"Discord.Net.Core": "3.5.0",
"Discord.Net.Rest": "3.5.0"
},
"runtime": {
"lib/net5.0/Discord.Net.WebSocket.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions/5.0.0": {
"runtime": {
"lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.20.51904"
}
}
},
"Newtonsoft.Json/13.0.1": {
"runtime": {
"lib/netstandard2.0/Newtonsoft.Json.dll": {
"assemblyVersion": "13.0.0.0",
"fileVersion": "13.0.1.25517"
}
}
},
"System.Collections.Immutable/5.0.0": {},
"System.Interactive.Async/5.0.0": {
"dependencies": {
"System.Linq.Async": "5.0.0"
},
"runtime": {
"lib/netcoreapp3.1/System.Interactive.Async.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.0.1"
}
}
},
"System.Linq.Async/5.0.0": {
"runtime": {
"lib/netcoreapp3.1/System.Linq.Async.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.0.1"
}
}
},
"System.Reactive/5.0.0": {
"runtime": {
"lib/net5.0/System.Reactive.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.0.1"
}
}
},
"System.ValueTuple/4.5.0": {},
"PluginManager/1.0.0": {
"dependencies": {
"Discord.Net": "3.5.0"
},
"runtime": {
"PluginManager.dll": {}
}
}
}
},
"libraries": {
"StartupEvents/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Discord.Net/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-IUtexpvogudb1rllKBWkIEpBVQoToMjtVo81KPkt+gNMe7KtRDcZJgcn6+72viMtyw0e95OJPXFV5VEA/n2OQQ==",
"path": "discord.net/3.5.0",
"hashPath": "discord.net.3.5.0.nupkg.sha512"
},
"Discord.Net.Commands/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ClTv8aiTlitvS48YatRiTLvgE2f2uKgmHNPVBIuvJBHZO2u4bZCzoN1fid+pZn2sbVOkt8uftlLGzz5DSZlFIA==",
"path": "discord.net.commands/3.5.0",
"hashPath": "discord.net.commands.3.5.0.nupkg.sha512"
},
"Discord.Net.Core/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-rCzzaznMVQ+bLMxOpYwTyqm9V22kMy6BxlQisSxemHZDe2Jedz3Clp/a0dToACLz+Dlp3u+jYUfCBnTz7L6f4g==",
"path": "discord.net.core/3.5.0",
"hashPath": "discord.net.core.3.5.0.nupkg.sha512"
},
"Discord.Net.Interactions/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-wE9+V9DJ7r+1s4euOi4sGPIAt4sD7r+Tk5s9mrlbLCHVQTK4KllAvcrL25bPFI38FuFceREEzFoRlTrekSyB2Q==",
"path": "discord.net.interactions/3.5.0",
"hashPath": "discord.net.interactions.3.5.0.nupkg.sha512"
},
"Discord.Net.Rest/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-BnTdLFuuQsKvCv08VQrD4X1Hw2Xp+MELIRQiDiKfG01IiQlRTN+1gc3LB1zXgn5xBvC0HXjHxwV22GrMD9uKHQ==",
"path": "discord.net.rest/3.5.0",
"hashPath": "discord.net.rest.3.5.0.nupkg.sha512"
},
"Discord.Net.Webhook/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-vCIGZS+m88sQDuFmdbUqg+2RIXS/NJWx8ei3MX+ZEYiAvOkDgQfkIlEnU1NKpds6ivTt5GFlv6UzcWubb5VJ1w==",
"path": "discord.net.webhook/3.5.0",
"hashPath": "discord.net.webhook.3.5.0.nupkg.sha512"
},
"Discord.Net.WebSocket/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-LjBOvcP40vJ+dhOtBDi8haEeblPAKpAIqR04NBzTM1/0RVavJZH89ovfSQIk42ygkiOaDV4E2x0Mmh6DRoIYcw==",
"path": "discord.net.websocket/3.5.0",
"hashPath": "discord.net.websocket.3.5.0.nupkg.sha512"
},
"Microsoft.Extensions.DependencyInjection.Abstractions/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ORj7Zh81gC69TyvmcUm9tSzytcy8AVousi+IVRAI8nLieQjOFryRusSFh7+aLk16FN9pQNqJAiMd7BTKINK0kA==",
"path": "microsoft.extensions.dependencyinjection.abstractions/5.0.0",
"hashPath": "microsoft.extensions.dependencyinjection.abstractions.5.0.0.nupkg.sha512"
},
"Newtonsoft.Json/13.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==",
"path": "newtonsoft.json/13.0.1",
"hashPath": "newtonsoft.json.13.0.1.nupkg.sha512"
},
"System.Collections.Immutable/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-FXkLXiK0sVVewcso0imKQoOxjoPAj42R8HtjjbSjVPAzwDfzoyoznWxgA3c38LDbN9SJux1xXoXYAhz98j7r2g==",
"path": "system.collections.immutable/5.0.0",
"hashPath": "system.collections.immutable.5.0.0.nupkg.sha512"
},
"System.Interactive.Async/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-QaqhQVDiULcu4vm6o89+iP329HcK44cETHOYgy/jfEjtzeFy0ZxmuM7nel9ocjnKxEM4yh1mli7hgh8Q9o+/Iw==",
"path": "system.interactive.async/5.0.0",
"hashPath": "system.interactive.async.5.0.0.nupkg.sha512"
},
"System.Linq.Async/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-cPtIuuH8TIjVHSi2ewwReWGW1PfChPE0LxPIDlfwVcLuTM9GANFTXiMB7k3aC4sk3f0cQU25LNKzx+jZMxijqw==",
"path": "system.linq.async/5.0.0",
"hashPath": "system.linq.async.5.0.0.nupkg.sha512"
},
"System.Reactive/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ==",
"path": "system.reactive/5.0.0",
"hashPath": "system.reactive.5.0.0.nupkg.sha512"
},
"System.ValueTuple/4.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ==",
"path": "system.valuetuple/4.5.0",
"hashPath": "system.valuetuple.4.5.0.nupkg.sha512"
},
"PluginManager/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
}
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,268 +0,0 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v6.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v6.0": {
"CMD_Utils/1.0.0": {
"dependencies": {
"PluginManager": "1.0.0"
},
"runtime": {
"CMD_Utils.dll": {}
}
},
"Discord.Net/3.7.2": {
"dependencies": {
"Discord.Net.Commands": "3.7.2",
"Discord.Net.Core": "3.7.2",
"Discord.Net.Interactions": "3.7.2",
"Discord.Net.Rest": "3.7.2",
"Discord.Net.WebSocket": "3.7.2",
"Discord.Net.Webhook": "3.7.2"
}
},
"Discord.Net.Commands/3.7.2": {
"dependencies": {
"Discord.Net.Core": "3.7.2"
},
"runtime": {
"lib/net6.0/Discord.Net.Commands.dll": {
"assemblyVersion": "3.7.2.0",
"fileVersion": "3.7.2.0"
}
}
},
"Discord.Net.Core/3.7.2": {
"dependencies": {
"Newtonsoft.Json": "13.0.1",
"System.Collections.Immutable": "5.0.0",
"System.Interactive.Async": "5.0.0",
"System.ValueTuple": "4.5.0"
},
"runtime": {
"lib/net6.0/Discord.Net.Core.dll": {
"assemblyVersion": "3.7.2.0",
"fileVersion": "3.7.2.0"
}
}
},
"Discord.Net.Interactions/3.7.2": {
"dependencies": {
"Discord.Net.Core": "3.7.2",
"Discord.Net.Rest": "3.7.2",
"Discord.Net.WebSocket": "3.7.2",
"Microsoft.Extensions.DependencyInjection.Abstractions": "5.0.0",
"System.Collections.Immutable": "5.0.0",
"System.Reactive": "5.0.0"
},
"runtime": {
"lib/net6.0/Discord.Net.Interactions.dll": {
"assemblyVersion": "3.7.2.0",
"fileVersion": "3.7.2.0"
}
}
},
"Discord.Net.Rest/3.7.2": {
"dependencies": {
"Discord.Net.Core": "3.7.2"
},
"runtime": {
"lib/net6.0/Discord.Net.Rest.dll": {
"assemblyVersion": "3.7.2.0",
"fileVersion": "3.7.2.0"
}
}
},
"Discord.Net.Webhook/3.7.2": {
"dependencies": {
"Discord.Net.Core": "3.7.2",
"Discord.Net.Rest": "3.7.2"
},
"runtime": {
"lib/net6.0/Discord.Net.Webhook.dll": {
"assemblyVersion": "3.7.2.0",
"fileVersion": "3.7.2.0"
}
}
},
"Discord.Net.WebSocket/3.7.2": {
"dependencies": {
"Discord.Net.Core": "3.7.2",
"Discord.Net.Rest": "3.7.2"
},
"runtime": {
"lib/net6.0/Discord.Net.WebSocket.dll": {
"assemblyVersion": "3.7.2.0",
"fileVersion": "3.7.2.0"
}
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions/5.0.0": {
"runtime": {
"lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.20.51904"
}
}
},
"Newtonsoft.Json/13.0.1": {
"runtime": {
"lib/netstandard2.0/Newtonsoft.Json.dll": {
"assemblyVersion": "13.0.0.0",
"fileVersion": "13.0.1.25517"
}
}
},
"System.Collections.Immutable/5.0.0": {},
"System.Interactive.Async/5.0.0": {
"dependencies": {
"System.Linq.Async": "5.0.0"
},
"runtime": {
"lib/netcoreapp3.1/System.Interactive.Async.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.0.1"
}
}
},
"System.Linq.Async/5.0.0": {
"runtime": {
"lib/netcoreapp3.1/System.Linq.Async.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.0.1"
}
}
},
"System.Reactive/5.0.0": {
"runtime": {
"lib/net5.0/System.Reactive.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.0.1"
}
}
},
"System.ValueTuple/4.5.0": {},
"PluginManager/1.0.0": {
"dependencies": {
"Discord.Net": "3.7.2"
},
"runtime": {
"PluginManager.dll": {}
}
}
}
},
"libraries": {
"CMD_Utils/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Discord.Net/3.7.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-FAiCLGu5rp6+Z10FjKbbJ6LLpKjbMBGpozixkJlz5LZvuncPx8f4AWFAw7pBecKUuAh983qiZ8CZYZcNXsI4qg==",
"path": "discord.net/3.7.2",
"hashPath": "discord.net.3.7.2.nupkg.sha512"
},
"Discord.Net.Commands/3.7.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-aOEGP04X64htsTr7ozKj9qHpmvOfitSw5gfR8Tw9TX0+FdswD2LNL2KfOAIaxRKZmRTm34aXQEJrVq0K8AptmQ==",
"path": "discord.net.commands/3.7.2",
"hashPath": "discord.net.commands.3.7.2.nupkg.sha512"
},
"Discord.Net.Core/3.7.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-apwswc6LjN4dj3u27SO3Hr56Jzl91wzReahieoD7IQhV+BJQaRxhTRiEEWFTrBzHfeFHEOQ7r6vZnra3zeFhKA==",
"path": "discord.net.core/3.7.2",
"hashPath": "discord.net.core.3.7.2.nupkg.sha512"
},
"Discord.Net.Interactions/3.7.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-dwGhEdDB0yyo/lGtjwIDVZmsuD52di7lIZWu/sBtvvA05dMgYZq5S6ILdsBXjOyaHeXd+EV4YMlj2VS/rm619w==",
"path": "discord.net.interactions/3.7.2",
"hashPath": "discord.net.interactions.3.7.2.nupkg.sha512"
},
"Discord.Net.Rest/3.7.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-dyp8YaMBNJ837EH1KNz2PNGZqc2y71WFd1+pdldF+pLQJ3Gf/+V7685paAR7bQw7yFNyqEBR/QRBCNp+QIQ7Wg==",
"path": "discord.net.rest/3.7.2",
"hashPath": "discord.net.rest.3.7.2.nupkg.sha512"
},
"Discord.Net.Webhook/3.7.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-da3i/mTq2y7mfj3xlHH14S4PivHbflJCVr8OUikJtQrxBOxvPkqP7ZYk3Y9S28q0K8qik+TUjCcjL5gELKrh/A==",
"path": "discord.net.webhook/3.7.2",
"hashPath": "discord.net.webhook.3.7.2.nupkg.sha512"
},
"Discord.Net.WebSocket/3.7.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-pYCd6ET44ADaNiyEw82TaJnR7TKYHfrKCytWFWMPL5faJhoh260avZn3Hwunlf331lEQ0f4K1CujPkQbNuq7kQ==",
"path": "discord.net.websocket/3.7.2",
"hashPath": "discord.net.websocket.3.7.2.nupkg.sha512"
},
"Microsoft.Extensions.DependencyInjection.Abstractions/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ORj7Zh81gC69TyvmcUm9tSzytcy8AVousi+IVRAI8nLieQjOFryRusSFh7+aLk16FN9pQNqJAiMd7BTKINK0kA==",
"path": "microsoft.extensions.dependencyinjection.abstractions/5.0.0",
"hashPath": "microsoft.extensions.dependencyinjection.abstractions.5.0.0.nupkg.sha512"
},
"Newtonsoft.Json/13.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==",
"path": "newtonsoft.json/13.0.1",
"hashPath": "newtonsoft.json.13.0.1.nupkg.sha512"
},
"System.Collections.Immutable/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-FXkLXiK0sVVewcso0imKQoOxjoPAj42R8HtjjbSjVPAzwDfzoyoznWxgA3c38LDbN9SJux1xXoXYAhz98j7r2g==",
"path": "system.collections.immutable/5.0.0",
"hashPath": "system.collections.immutable.5.0.0.nupkg.sha512"
},
"System.Interactive.Async/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-QaqhQVDiULcu4vm6o89+iP329HcK44cETHOYgy/jfEjtzeFy0ZxmuM7nel9ocjnKxEM4yh1mli7hgh8Q9o+/Iw==",
"path": "system.interactive.async/5.0.0",
"hashPath": "system.interactive.async.5.0.0.nupkg.sha512"
},
"System.Linq.Async/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-cPtIuuH8TIjVHSi2ewwReWGW1PfChPE0LxPIDlfwVcLuTM9GANFTXiMB7k3aC4sk3f0cQU25LNKzx+jZMxijqw==",
"path": "system.linq.async/5.0.0",
"hashPath": "system.linq.async.5.0.0.nupkg.sha512"
},
"System.Reactive/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ==",
"path": "system.reactive/5.0.0",
"hashPath": "system.reactive.5.0.0.nupkg.sha512"
},
"System.ValueTuple/4.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ==",
"path": "system.valuetuple/4.5.0",
"hashPath": "system.valuetuple.4.5.0.nupkg.sha512"
},
"PluginManager/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
}
}
}

Binary file not shown.

View File

@@ -1,334 +0,0 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v6.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v6.0": {
"Music Commands/1.0.0": {
"dependencies": {
"PluginManager": "1.0.0",
"YoutubeExplode": "6.2.0"
},
"runtime": {
"Music Commands.dll": {}
}
},
"AngleSharp/0.17.0": {
"dependencies": {
"System.Buffers": "4.5.1",
"System.Text.Encoding.CodePages": "5.0.0"
},
"runtime": {
"lib/netstandard2.0/AngleSharp.dll": {
"assemblyVersion": "0.17.0.0",
"fileVersion": "0.17.0.0"
}
}
},
"Discord.Net/3.7.2": {
"dependencies": {
"Discord.Net.Commands": "3.7.2",
"Discord.Net.Core": "3.7.2",
"Discord.Net.Interactions": "3.7.2",
"Discord.Net.Rest": "3.7.2",
"Discord.Net.WebSocket": "3.7.2",
"Discord.Net.Webhook": "3.7.2"
}
},
"Discord.Net.Commands/3.7.2": {
"dependencies": {
"Discord.Net.Core": "3.7.2"
},
"runtime": {
"lib/net6.0/Discord.Net.Commands.dll": {
"assemblyVersion": "3.7.2.0",
"fileVersion": "3.7.2.0"
}
}
},
"Discord.Net.Core/3.7.2": {
"dependencies": {
"Newtonsoft.Json": "13.0.1",
"System.Collections.Immutable": "5.0.0",
"System.Interactive.Async": "5.0.0",
"System.ValueTuple": "4.5.0"
},
"runtime": {
"lib/net6.0/Discord.Net.Core.dll": {
"assemblyVersion": "3.7.2.0",
"fileVersion": "3.7.2.0"
}
}
},
"Discord.Net.Interactions/3.7.2": {
"dependencies": {
"Discord.Net.Core": "3.7.2",
"Discord.Net.Rest": "3.7.2",
"Discord.Net.WebSocket": "3.7.2",
"Microsoft.Extensions.DependencyInjection.Abstractions": "5.0.0",
"System.Collections.Immutable": "5.0.0",
"System.Reactive": "5.0.0"
},
"runtime": {
"lib/net6.0/Discord.Net.Interactions.dll": {
"assemblyVersion": "3.7.2.0",
"fileVersion": "3.7.2.0"
}
}
},
"Discord.Net.Rest/3.7.2": {
"dependencies": {
"Discord.Net.Core": "3.7.2"
},
"runtime": {
"lib/net6.0/Discord.Net.Rest.dll": {
"assemblyVersion": "3.7.2.0",
"fileVersion": "3.7.2.0"
}
}
},
"Discord.Net.Webhook/3.7.2": {
"dependencies": {
"Discord.Net.Core": "3.7.2",
"Discord.Net.Rest": "3.7.2"
},
"runtime": {
"lib/net6.0/Discord.Net.Webhook.dll": {
"assemblyVersion": "3.7.2.0",
"fileVersion": "3.7.2.0"
}
}
},
"Discord.Net.WebSocket/3.7.2": {
"dependencies": {
"Discord.Net.Core": "3.7.2",
"Discord.Net.Rest": "3.7.2"
},
"runtime": {
"lib/net6.0/Discord.Net.WebSocket.dll": {
"assemblyVersion": "3.7.2.0",
"fileVersion": "3.7.2.0"
}
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions/5.0.0": {
"runtime": {
"lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.20.51904"
}
}
},
"Microsoft.NETCore.Platforms/5.0.0": {},
"Newtonsoft.Json/13.0.1": {
"runtime": {
"lib/netstandard2.0/Newtonsoft.Json.dll": {
"assemblyVersion": "13.0.0.0",
"fileVersion": "13.0.1.25517"
}
}
},
"System.Buffers/4.5.1": {},
"System.Collections.Immutable/5.0.0": {},
"System.Interactive.Async/5.0.0": {
"dependencies": {
"System.Linq.Async": "5.0.0"
},
"runtime": {
"lib/netcoreapp3.1/System.Interactive.Async.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.0.1"
}
}
},
"System.Linq.Async/5.0.0": {
"runtime": {
"lib/netcoreapp3.1/System.Linq.Async.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.0.1"
}
}
},
"System.Reactive/5.0.0": {
"runtime": {
"lib/net5.0/System.Reactive.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.0.1"
}
}
},
"System.Text.Encoding.CodePages/5.0.0": {
"dependencies": {
"Microsoft.NETCore.Platforms": "5.0.0"
}
},
"System.ValueTuple/4.5.0": {},
"YoutubeExplode/6.2.0": {
"dependencies": {
"AngleSharp": "0.17.0"
},
"runtime": {
"lib/net5.0/YoutubeExplode.dll": {
"assemblyVersion": "6.2.0.0",
"fileVersion": "6.2.0.0"
}
}
},
"PluginManager/1.0.0": {
"dependencies": {
"Discord.Net": "3.7.2"
},
"runtime": {
"PluginManager.dll": {}
}
}
}
},
"libraries": {
"Music Commands/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"AngleSharp/0.17.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-74haoXINcj4SdMsmiNzk+9VUwIX1U9P61O6AZd5Uao8SGNnJJB8Y/r8VJRc8orn4c7Vk/oURAKSNF9XcSDxbfA==",
"path": "anglesharp/0.17.0",
"hashPath": "anglesharp.0.17.0.nupkg.sha512"
},
"Discord.Net/3.7.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-FAiCLGu5rp6+Z10FjKbbJ6LLpKjbMBGpozixkJlz5LZvuncPx8f4AWFAw7pBecKUuAh983qiZ8CZYZcNXsI4qg==",
"path": "discord.net/3.7.2",
"hashPath": "discord.net.3.7.2.nupkg.sha512"
},
"Discord.Net.Commands/3.7.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-aOEGP04X64htsTr7ozKj9qHpmvOfitSw5gfR8Tw9TX0+FdswD2LNL2KfOAIaxRKZmRTm34aXQEJrVq0K8AptmQ==",
"path": "discord.net.commands/3.7.2",
"hashPath": "discord.net.commands.3.7.2.nupkg.sha512"
},
"Discord.Net.Core/3.7.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-apwswc6LjN4dj3u27SO3Hr56Jzl91wzReahieoD7IQhV+BJQaRxhTRiEEWFTrBzHfeFHEOQ7r6vZnra3zeFhKA==",
"path": "discord.net.core/3.7.2",
"hashPath": "discord.net.core.3.7.2.nupkg.sha512"
},
"Discord.Net.Interactions/3.7.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-dwGhEdDB0yyo/lGtjwIDVZmsuD52di7lIZWu/sBtvvA05dMgYZq5S6ILdsBXjOyaHeXd+EV4YMlj2VS/rm619w==",
"path": "discord.net.interactions/3.7.2",
"hashPath": "discord.net.interactions.3.7.2.nupkg.sha512"
},
"Discord.Net.Rest/3.7.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-dyp8YaMBNJ837EH1KNz2PNGZqc2y71WFd1+pdldF+pLQJ3Gf/+V7685paAR7bQw7yFNyqEBR/QRBCNp+QIQ7Wg==",
"path": "discord.net.rest/3.7.2",
"hashPath": "discord.net.rest.3.7.2.nupkg.sha512"
},
"Discord.Net.Webhook/3.7.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-da3i/mTq2y7mfj3xlHH14S4PivHbflJCVr8OUikJtQrxBOxvPkqP7ZYk3Y9S28q0K8qik+TUjCcjL5gELKrh/A==",
"path": "discord.net.webhook/3.7.2",
"hashPath": "discord.net.webhook.3.7.2.nupkg.sha512"
},
"Discord.Net.WebSocket/3.7.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-pYCd6ET44ADaNiyEw82TaJnR7TKYHfrKCytWFWMPL5faJhoh260avZn3Hwunlf331lEQ0f4K1CujPkQbNuq7kQ==",
"path": "discord.net.websocket/3.7.2",
"hashPath": "discord.net.websocket.3.7.2.nupkg.sha512"
},
"Microsoft.Extensions.DependencyInjection.Abstractions/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ORj7Zh81gC69TyvmcUm9tSzytcy8AVousi+IVRAI8nLieQjOFryRusSFh7+aLk16FN9pQNqJAiMd7BTKINK0kA==",
"path": "microsoft.extensions.dependencyinjection.abstractions/5.0.0",
"hashPath": "microsoft.extensions.dependencyinjection.abstractions.5.0.0.nupkg.sha512"
},
"Microsoft.NETCore.Platforms/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-VyPlqzH2wavqquTcYpkIIAQ6WdenuKoFN0BdYBbCWsclXacSOHNQn66Gt4z5NBqEYW0FAPm5rlvki9ZiCij5xQ==",
"path": "microsoft.netcore.platforms/5.0.0",
"hashPath": "microsoft.netcore.platforms.5.0.0.nupkg.sha512"
},
"Newtonsoft.Json/13.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==",
"path": "newtonsoft.json/13.0.1",
"hashPath": "newtonsoft.json.13.0.1.nupkg.sha512"
},
"System.Buffers/4.5.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==",
"path": "system.buffers/4.5.1",
"hashPath": "system.buffers.4.5.1.nupkg.sha512"
},
"System.Collections.Immutable/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-FXkLXiK0sVVewcso0imKQoOxjoPAj42R8HtjjbSjVPAzwDfzoyoznWxgA3c38LDbN9SJux1xXoXYAhz98j7r2g==",
"path": "system.collections.immutable/5.0.0",
"hashPath": "system.collections.immutable.5.0.0.nupkg.sha512"
},
"System.Interactive.Async/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-QaqhQVDiULcu4vm6o89+iP329HcK44cETHOYgy/jfEjtzeFy0ZxmuM7nel9ocjnKxEM4yh1mli7hgh8Q9o+/Iw==",
"path": "system.interactive.async/5.0.0",
"hashPath": "system.interactive.async.5.0.0.nupkg.sha512"
},
"System.Linq.Async/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-cPtIuuH8TIjVHSi2ewwReWGW1PfChPE0LxPIDlfwVcLuTM9GANFTXiMB7k3aC4sk3f0cQU25LNKzx+jZMxijqw==",
"path": "system.linq.async/5.0.0",
"hashPath": "system.linq.async.5.0.0.nupkg.sha512"
},
"System.Reactive/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ==",
"path": "system.reactive/5.0.0",
"hashPath": "system.reactive.5.0.0.nupkg.sha512"
},
"System.Text.Encoding.CodePages/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-NyscU59xX6Uo91qvhOs2Ccho3AR2TnZPomo1Z0K6YpyztBPM/A5VbkzOO19sy3A3i1TtEnTxA7bCe3Us+r5MWg==",
"path": "system.text.encoding.codepages/5.0.0",
"hashPath": "system.text.encoding.codepages.5.0.0.nupkg.sha512"
},
"System.ValueTuple/4.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ==",
"path": "system.valuetuple/4.5.0",
"hashPath": "system.valuetuple.4.5.0.nupkg.sha512"
},
"YoutubeExplode/6.2.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-oH5kst4w1QkUwRjJco0alF57JOmFofSGlPkr4OniODB8R6MEyRWn1xFg3JS2wFYd6scZluoXRDhM3/uyUjO9/g==",
"path": "youtubeexplode/6.2.0",
"hashPath": "youtubeexplode.6.2.0.nupkg.sha512"
},
"PluginManager/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
}
}
}

Binary file not shown.

Binary file not shown.

View File

@@ -1,14 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<BaseOutputPath>bin\</BaseOutputPath>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\PluginManager\PluginManager.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,50 +0,0 @@
using Discord;
using Discord.Commands;
using Discord.WebSocket;
using PluginManager;
using PluginManager.Interfaces;
using PluginManager.Others;
namespace CMD_LevelingSystem;
internal class Level : DBCommand
{
public string Command => "level";
public List<string> Aliases => new() { "lvl" };
public string Description => "Display tour current level";
public string Usage => "level";
public bool canUseDM => false;
public bool canUseServer => true;
public bool requireAdmin => false;
public async void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM)
{
if (!File.Exists(Config.GetValue<string>("LevelingSystemPath") + $"/{message.Author.Id}.dat"))
{
await context.Channel.SendMessageAsync("You are now unranked !");
return;
}
var user = await Functions.ConvertFromJson<User>(Config.GetValue<string>("LevelingSystemPath") + $"/{message.Author.Id}.dat");
if (user == null)
{
await context.Channel.SendMessageAsync("You are now unranked !");
return;
}
var builder = new EmbedBuilder();
var r = new Random();
builder.WithColor(r.Next(256), r.Next(256), r.Next(256));
builder.AddField("Current Level", user.CurrentLevel, true)
.AddField("Current EXP", user.CurrentEXP, true)
.AddField("Required Exp", user.RequiredEXPToLevelUp, true);
builder.WithTimestamp(DateTimeOffset.Now);
await context.Channel.SendMessageAsync(embed: builder.Build());
}
}

View File

@@ -1,18 +0,0 @@
using Discord.WebSocket;
namespace CMD_LevelingSystem;
public class DiscordUser
{
public string Username { get; set; }
public ushort DiscordTag { get; set; }
public ulong userID { get; set; }
}
public class User
{
public DiscordUser user { get; set; }
public int CurrentLevel { get; set; }
public long CurrentEXP { get; set; }
public long RequiredEXPToLevelUp { get; set; }
}

View File

@@ -1,19 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<BaseOutputPath>bin\</BaseOutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputPath>..\BUILDS\</OutputPath>
<ErrorReport>prompt</ErrorReport>
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\PluginManager\PluginManager.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,26 +0,0 @@
using Discord.Commands;
using Discord.WebSocket;
using PluginManager.Interfaces;
using System.Collections.Generic;
internal class Echo : DBCommand
{
public string Command => "echo";
public List<string> Aliases => null;
public string Description => "Replay with the same message";
public string Usage => "echo [message]";
public bool canUseDM => true;
public bool canUseServer => true;
public bool requireAdmin => false;
public async void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM)
{
var m = message.Content.Substring(6);
await message.Channel.SendMessageAsync(m);
}
}

View File

@@ -1,33 +0,0 @@
using Discord.Commands;
using Discord.WebSocket;
using PluginManager.Interfaces;
using System.Collections.Generic;
namespace CMD_Utils;
internal class FlipCoin : DBCommand
{
public string Command => "flip";
public List<string> Aliases => null;
public string Description => "Flip a coin";
public string Usage => "flip";
public bool canUseDM => true;
public bool canUseServer => true;
public bool requireAdmin => false;
public async void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM)
{
var random = new System.Random();
var r = random.Next(1, 3);
if (r == 1)
await message.Channel.SendMessageAsync("Heads");
else
await message.Channel.SendMessageAsync("Tails");
}
}

View File

@@ -1,47 +0,0 @@
using System.Collections.Generic;
using Discord;
using Discord.Commands;
using Discord.WebSocket;
using PluginManager.Interfaces;
using PluginManager.Others;
namespace CMD_Utils;
public class Poll : DBCommand
{
public string Command => "poll";
public List<string> Aliases => null;
public string Description => "Create a poll with options";
public string Usage => "poll [This-is-question] [This-is-answer-1] [This-is-answer-2] ... ";
public bool canUseDM => false;
public bool canUseServer => true;
public bool requireAdmin => true;
public async void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM)
{
if (isDM) return;
var question = message.Content.Split(' ')[1].Replace('-', ' ');
var answers = Functions.MergeStrings(message.Content.Split(' '), 2).Split(' ');
var embedBuilder = new EmbedBuilder();
embedBuilder.Title = question;
var len = answers.Length;
for (var i = 0; i < len; i++) embedBuilder.AddField($"Answer {i + 1}", answers[i].Replace('-', ' '), true);
var msg = await context.Channel.SendMessageAsync(embed: embedBuilder.Build());
var emotes = new List<IEmote>();
emotes.Add(Emoji.Parse(":one:"));
emotes.Add(Emoji.Parse(":two:"));
emotes.Add(Emoji.Parse(":three:"));
emotes.Add(Emoji.Parse(":four:"));
emotes.Add(Emoji.Parse(":five:"));
emotes.Add(Emoji.Parse(":six:"));
for (var i = 0; i < len; i++) await msg.AddReactionAsync(emotes[i]);
}
}

View File

@@ -1,42 +0,0 @@
using System.Collections.Generic;
using Discord.Commands;
using Discord.WebSocket;
using PluginManager.Interfaces;
public class Random : DBCommand
{
public string Command => "random";
public List<string> Aliases => new() { "rnd" };
public string Description => "random number between number1 and number2";
public string Usage => "random [number1] [number2]";
public bool canUseDM => true;
public bool canUseServer => true;
public bool requireAdmin => false;
public async void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM)
{
try
{
var msg = message.Content;
var a = int.Parse(msg.Split(' ')[1]);
var b = int.Parse(msg.Split(' ')[2]);
if (a > b)
{
var temp = a;
a = b;
b = temp;
}
await message.Channel.SendMessageAsync("Your random generated number is " + new System.Random().Next(a, b));
}
catch
{
await message.Channel.SendMessageAsync("Invalid numbers or no numbers:\nUsage: " + Usage);
}
}
}

View File

@@ -1,4 +0,0 @@
<dependentAssembly>
<assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>

View File

@@ -1,8 +1,9 @@
using System.Collections.Generic;
using System.Linq;
using System;
using System.Collections.Generic;
using Discord;
using Discord.Commands;
using Discord.WebSocket;
using PluginManager;
using PluginManager.Interfaces;
using PluginManager.Loaders;
using PluginManager.Others;
@@ -31,16 +32,6 @@ internal class Help : DBCommand
/// </summary>
public string Usage => "help <command>";
/// <summary>
/// Check if the command can be used <inheritdoca DM <see cref="IChannel" />/>
/// </summary>
public bool canUseDM => true;
/// <summary>
/// Check if the command can be used in a server
/// </summary>
public bool canUseServer => true;
/// <summary>
/// Check if the command require administrator to be executed
/// </summary>
@@ -50,22 +41,16 @@ internal class Help : DBCommand
/// The main body of the command
/// </summary>
/// <param name="context">The command context</param>
/// <param name="message">The command message</param>
/// <param name="client">The discord bot client</param>
/// <param name="isDM">True if the message was sent from a DM channel, false otherwise</param>
public void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM)
public void ExecuteServer(CmdArgs args)
{
var args = Functions.GetArguments(message);
if (args.Count != 0)
if (args.arguments is not null)
{
foreach (var item in args)
{
var e = GenerateHelpCommand(item);
var e = GenerateHelpCommand(args.arguments[0]);
if (e is null)
context.Channel.SendMessageAsync("Unknown Command " + item);
args.context.Channel.SendMessageAsync("Unknown Command " + args.arguments[0]);
else
context.Channel.SendMessageAsync(embed: e.Build());
}
args.context.Channel.SendMessageAsync(embed: e.Build());
return;
}
@@ -74,31 +59,29 @@ internal class Help : DBCommand
var adminCommands = "";
var normalCommands = "";
var DMCommands = "";
foreach (var cmd in PluginLoader.Commands!)
{
if (cmd.canUseDM)
DMCommands += cmd.Command + " ";
if (cmd.requireAdmin)
adminCommands += cmd.Command + " ";
if (cmd.canUseServer)
else
normalCommands += cmd.Command + " ";
}
if(adminCommands.Length > 0)
embedBuilder.AddField("Admin Commands", adminCommands);
if(normalCommands.Length > 0)
embedBuilder.AddField("Normal Commands", normalCommands);
embedBuilder.AddField("DM Commands", DMCommands);
context.Channel.SendMessageAsync(embed: embedBuilder.Build());
args.context.Channel.SendMessageAsync(embed: embedBuilder.Build());
}
private EmbedBuilder GenerateHelpCommand(string command)
{
var embedBuilder = new EmbedBuilder();
var cmd = PluginLoader.Commands!.Find(p => p.Command == command || (p.Aliases is not null && p.Aliases.Contains(command)));
var cmd = PluginLoader.Commands!.Find(p => p.Command == command ||
(p.Aliases is not null && p.Aliases.Contains(command)));
if (cmd == null) return null;
embedBuilder.AddField("Usage", cmd.Usage);
embedBuilder.AddField("Usage", Config.Variables.GetValue("prefix") + cmd.Usage);
embedBuilder.AddField("Description", cmd.Description);
if (cmd.Aliases is null)
return embedBuilder;

View File

@@ -1,116 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Discord.WebSocket;
using PluginManager.Interfaces;
using PluginManager.Others;
using PluginManager.Others.Permissions;
using DiscordLibCommands = Discord.Commands;
using DiscordLib = Discord;
using OperatingSystem = PluginManager.Others.OperatingSystem;
namespace DiscordBot.Discord.Commands;
internal class Restart : DBCommand
{
/// <summary>
/// Command name
/// </summary>
public string Command => "restart";
public List<string> Aliases => null;
/// <summary>
/// Command Description
/// </summary>
public string Description => "Restart the bot";
/// <summary>
/// Command usage
/// </summary>
public string Usage => "restart [-p | -c | -args | -cmd] <args>";
/// <summary>
/// Check if the command can be used <inheritdoca DM <see cref="IChannel" />/>
/// </summary>
public bool canUseDM => false;
/// <summary>
/// Check if the command can be used in a server
/// </summary>
public bool canUseServer => true;
/// <summary>
/// Check if the command require administrator to be executed
/// </summary>
public bool requireAdmin => false;
/// <summary>
/// The main body of the command
/// </summary>
/// <param name="context">The command context</param>
/// <param name="message">The command message</param>
/// <param name="client">The discord bot client</param>
/// <param name="isDM">True if the message was sent from a DM channel, false otherwise</param>
public async void Execute(DiscordLibCommands.SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM)
{
if (!(message.Author as SocketGuildUser).hasPermission(DiscordLib.GuildPermission.Administrator)) return;
var args = Functions.GetArguments(message);
var OS = Functions.GetOperatingSystem();
if (args.Count == 0)
{
switch (OS)
{
case OperatingSystem.WINDOWS:
Process.Start("./DiscordBot.exe");
break;
case OperatingSystem.LINUX:
case OperatingSystem.MAC_OS:
Process.Start("./DiscordBot");
break;
default:
return;
}
return;
}
switch (args[0])
{
case "-p":
case "-poweroff":
case "-c":
case "-close":
Environment.Exit(0);
break;
case "-cmd":
case "-args":
var cmd = "--args";
if (args.Count > 1)
for (var i = 1; i < args.Count; i++)
cmd += $" {args[i]}";
switch (OS)
{
case OperatingSystem.WINDOWS:
Functions.WriteLogFile("Restarting the bot with the following arguments: \"" + cmd + "\"");
Process.Start("./DiscordBot.exe", cmd);
break;
case OperatingSystem.LINUX:
//case PluginManager.Others.OperatingSystem.MAC_OS: ?? - not tested
Process.Start("./DiscordBot", cmd);
break;
default:
return;
}
Environment.Exit(0);
break;
default:
await context.Channel.SendMessageAsync("Invalid argument. Use `help restart` to see the usage.");
break;
}
}
}

View File

@@ -1,100 +0,0 @@
using System;
using System.Collections.Generic;
using Discord;
using Discord.Commands;
using Discord.WebSocket;
using PluginManager;
using PluginManager.Interfaces;
namespace DiscordBot.Discord.Commands;
internal class Settings : DBCommand
{
/// <summary>
/// Command name
/// </summary>
public string Command => "set";
public List<string> Aliases => null;
/// <summary>
/// Command Description
/// </summary>
public string Description => "This command allows you change all settings. Use \"set help\" to show details";
/// <summary>
/// Command usage
/// </summary>
public string Usage => "set [keyword] [new Value]";
/// <summary>
/// Check if the command can be used <inheritdoca DM <see cref="IChannel" />/>
/// </summary>
public bool canUseDM => true;
/// <summary>
/// Check if the command can be used in a server
/// </summary>
public bool canUseServer => true;
/// <summary>
/// Check if the command require administrator to be executed
/// </summary>
public bool requireAdmin => true;
/// <summary>
/// The main body of the command
/// </summary>
/// <param name="context">The command context</param>
/// <param name="message">The command message</param>
/// <param name="client">The discord bot client</param>
/// <param name="isDM">True if the message was sent from a DM channel, false otherwise</param>
public async void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM)
{
var channel = message.Channel;
try
{
var content = message.Content;
var data = content.Split(' ');
var keyword = data[1];
if (keyword.ToLower() == "help")
{
await channel.SendMessageAsync("set token [new value] -- set the value of the new token (require restart)");
await channel.SendMessageAsync("set prefix [new value] -- set the value of the new preifx (require restart)");
return;
}
switch (keyword.ToLower())
{
case "token":
if (data.Length != 3)
{
await channel.SendMessageAsync("Invalid token !");
return;
}
Config.SetValue("token", data[2]);
break;
case "prefix":
if (data.Length != 3)
{
await channel.SendMessageAsync("Invalid token !");
return;
}
Config.SetValue("token", data[2]);
break;
default:
return;
}
await channel.SendMessageAsync("Restart required ...");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
await channel.SendMessageAsync("Unknown usage to this command !\nUsage: " + Usage);
}
}
}

View File

@@ -1,11 +1,11 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Discord;
using Discord.Commands;
using Discord.WebSocket;
using PluginManager;
using static PluginManager.Others.Functions;
namespace DiscordBot.Discord.Core;
@@ -60,7 +60,16 @@ internal class Boot
/// <returns>Task</returns>
public async Task Awake()
{
DiscordSocketConfig config = new DiscordSocketConfig { AlwaysDownloadUsers = true };
var config = new DiscordSocketConfig
{
AlwaysDownloadUsers = true,
//Disable system clock checkup (for responses at slash commands)
UseInteractionSnowflakeDate = false,
GatewayIntents = GatewayIntents.All
};
client = new DiscordSocketClient(config);
service = new CommandService();
@@ -68,11 +77,15 @@ internal class Boot
CommonTasks();
await client.LoginAsync(TokenType.Bot, botToken);
await client.StartAsync();
commandServiceHandler = new CommandHandler(client, service, botPrefix);
await commandServiceHandler.InstallCommandsAsync();
await Task.Delay(2000);
while (!isReady) ;
}
@@ -84,27 +97,38 @@ internal class Boot
client.Log += Log;
client.LoggedIn += LoggedIn;
client.Ready += Ready;
client.Disconnected += Client_Disconnected;
}
private Task Client_LoggedOut()
private Task Client_Disconnected(Exception arg)
{
WriteLogFile("Successfully Logged Out");
Log(new LogMessage(LogSeverity.Info, "Boot", "Successfully logged out from discord !"));
if (arg.Message.Contains("401"))
{
Config.Variables.RemoveKey("token");
Program.GenerateStartUI("The token is invalid");
}
Logger.WriteErrFile(arg);
return Task.CompletedTask;
}
private async Task Client_LoggedOut()
{
Logger.WriteLine("Successfully Logged Out");
await Log(new LogMessage(LogSeverity.Info, "Boot", "Successfully logged out from discord !"));
}
private Task Ready()
{
Console.Title = "ONLINE";
isReady = true;
return Task.CompletedTask;
}
private Task LoggedIn()
{
Console.Title = "CONNECTED";
WriteLogFile("The bot has been logged in at " + DateTime.Now.ToShortDateString() + " (" +
Logger.WriteLine("The bot has been logged in at " + DateTime.Now.ToShortDateString() + " (" +
DateTime.Now.ToShortTimeString() + ")"
);
return Task.CompletedTask;
@@ -116,7 +140,7 @@ internal class Boot
{
case LogSeverity.Error:
case LogSeverity.Critical:
WriteErrFile(message.Message);
Logger.WriteErrFile(message.Message);
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("[ERROR] " + message.Message);
@@ -126,7 +150,7 @@ internal class Boot
case LogSeverity.Info:
case LogSeverity.Debug:
WriteLogFile(message.Message);
Logger.WriteLogFile(message.Message);
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("[INFO] " + message.Message);

View File

@@ -1,12 +1,17 @@
using System.Linq;
using System;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Discord.Commands;
using Discord.WebSocket;
using PluginManager.Interfaces;
using PluginManager.Loaders;
using PluginManager.Others;
using PluginManager.Others.Permissions;
using static PluginManager.Logger;
namespace DiscordBot.Discord.Core;
internal class CommandHandler
@@ -26,6 +31,7 @@ internal class CommandHandler
this.client = client;
this.commandService = commandService;
this.botPrefix = botPrefix;
}
/// <summary>
@@ -35,9 +41,37 @@ internal class CommandHandler
public async Task InstallCommandsAsync()
{
client.MessageReceived += MessageHandler;
client.SlashCommandExecuted += Client_SlashCommandExecuted;
await commandService.AddModulesAsync(Assembly.GetEntryAssembly(), null);
}
private Task Client_SlashCommandExecuted(SocketSlashCommand arg)
{
try
{
var plugin = PluginLoader.SlashCommands!
.Where(p => p.Name == arg.Data.Name)
.FirstOrDefault();
if (plugin is null)
throw new Exception("Failed to run command. !");
if (arg.Channel is SocketDMChannel)
plugin.ExecuteDM(arg);
else plugin.ExecuteServer(arg);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
ex.WriteErrFile();
}
return Task.CompletedTask;
}
/// <summary>
/// The message handler for the bot
/// </summary>
@@ -45,87 +79,89 @@ internal class CommandHandler
/// <returns></returns>
private async Task MessageHandler(SocketMessage Message)
{
try
{
if (Message.Author.IsBot)
return;
if (Message as SocketUserMessage == null)
return;
var message = Message as SocketUserMessage;
if (message == null)
return;
if (!message.Content.StartsWith(botPrefix))
if (message is null)
return;
var argPos = 0;
if (message.HasMentionPrefix(client.CurrentUser, ref argPos))
{
await message.Channel.SendMessageAsync("Can not exec mentioned commands !");
return;
}
if (message.Author.IsBot)
if (!message.Content.StartsWith(botPrefix) && !message.HasMentionPrefix(client.CurrentUser, ref argPos))
return;
var context = new SocketCommandContext(client, message);
await commandService.ExecuteAsync(context, argPos, null);
var plugin = PluginLoader.Commands!.Where(p => p.Command == message.Content.Split(' ')[0].Substring(botPrefix.Length) || (p.Aliases is not null && p.Aliases.Contains(message.Content.Split(' ')[0].Substring(botPrefix.Length)))).FirstOrDefault();
DBCommand plugin;
string cleanMessage = "";
if (message.HasMentionPrefix(client.CurrentUser, ref argPos))
{
string mentionPrefix = "<@" + client.CurrentUser.Id + ">";
if (plugin != null)
plugin = PluginLoader.Commands!
.Where
(
plug => plug.Command == message.Content.Substring(mentionPrefix.Length+1).Split(' ')[0] ||
(
plug.Aliases is not null &&
plug.Aliases.Contains(message.CleanContent.Substring(mentionPrefix.Length+1).Split(' ')[0])
)
)
.FirstOrDefault();
cleanMessage = message.Content.Substring(mentionPrefix.Length + 1);
}
else
{
if (message.Channel == await message.Author.CreateDMChannelAsync())
{
if (plugin.canUseDM)
{
if (plugin.requireAdmin)
{
if (message.Author.isAdmin())
{
plugin.Execute(context, message, client, true);
Functions.WriteLogFile($"[{message.Author.Id}] Executed command (DM) : " + plugin.Command);
plugin = PluginLoader.Commands!
.Where(
p => p.Command == message.Content.Split(' ')[0].Substring(botPrefix.Length) ||
(p.Aliases is not null &&
p.Aliases.Contains(
message.Content.Split(' ')[0].Substring(botPrefix.Length))))
.FirstOrDefault();
cleanMessage = message.Content.Substring(botPrefix.Length);
}
if (plugin is null)
throw new Exception($"Failed to run command ! " + message.CleanContent);
if (plugin.requireAdmin && !context.Message.Author.isAdmin())
return;
}
await message.Channel.SendMessageAsync("This command is for administrators only !");
return;
}
string[] split = cleanMessage.Split(' ');
plugin.Execute(context, message, client, true);
Functions.WriteLogFile($"[{message.Author.Id}] Executed command (DM) : " + plugin.Command);
return;
}
string[] argsClean = null;
if(split.Length > 1)
argsClean = string.Join(' ', split, 1, split.Length-1).Split(' ');
await message.Channel.SendMessageAsync("This command is not for DMs");
return;
}
CmdArgs cmd = new() {
context = context,
cleanContent = cleanMessage,
commandUsed = split[0],
arguments = argsClean
};
if (plugin.canUseServer)
if (context.Channel is SocketDMChannel)
plugin.ExecuteDM(cmd);
else plugin.ExecuteServer(cmd);
}
catch (Exception ex)
{
if (plugin.requireAdmin)
{
if (message.Author.isAdmin())
{
plugin.Execute(context, message, client, false);
Functions.WriteLogFile($"[{message.Author.Id}] Executed command : " + plugin.Command);
return;
}
ex.WriteErrFile();
await message.Channel.SendMessageAsync("This command is for administrators only !");
return;
}
plugin.Execute(context, message, client, false);
Functions.WriteLogFile($"[{message.Author.Id}] Executed command : " + plugin.Command);
}
}
}
catch
{
Console.WriteLine(ex.ToString());
}
}
}

View File

@@ -8,7 +8,7 @@
<StartupObject />
<SignAssembly>False</SignAssembly>
<IsPublishable>True</IsPublishable>
<AssemblyVersion>1.0.0.2</AssemblyVersion>
<AssemblyVersion>1.0.1.2</AssemblyVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
@@ -38,7 +38,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Discord.Net" Version="3.7.2" />
<PackageReference Include="Discord.Net" Version="3.9.0" />
</ItemGroup>
<ItemGroup>

32
DiscordBot/Entry.cs Normal file
View File

@@ -0,0 +1,32 @@
using PluginManager.Others;
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
namespace DiscordBot
{
public class Entry
{
internal static StartupArguments startupArguments;
public static void Main(string[] args)
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += new ResolveEventHandler(LoadFromSameFolder);
static Assembly LoadFromSameFolder(object sender, ResolveEventArgs args)
{
string folderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "./Libraries");
string assemblyPath = Path.Combine(folderPath, new AssemblyName(args.Name).Name + ".dll");
if (!File.Exists(assemblyPath)) return null;
Assembly assembly = Assembly.LoadFrom(assemblyPath);
return assembly;
}
Program.Startup(args);
}
}
}

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
@@ -9,121 +9,69 @@ using System.Threading.Tasks;
using DiscordBot.Discord.Core;
using PluginManager;
using PluginManager.Database;
using PluginManager.Items;
using PluginManager.Online;
using PluginManager.Online.Helpers;
using PluginManager.Others;
using Terminal.Gui;
using OperatingSystem = PluginManager.Others.OperatingSystem;
namespace DiscordBot;
public class Program
{
private static bool loadPluginsOnStartup;
private static bool listPluginsAtStartup;
private static ConsoleCommandsHandler consoleCommandsHandler;
//private static bool isUI_ON;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
[Obsolete]
public static void Main(string[] args)
public static void Startup(string[] args)
{
PreLoadComponents(args).Wait();
Directory.CreateDirectory("./Data/Resources");
Directory.CreateDirectory("./Data/Plugins/Commands");
Directory.CreateDirectory("./Data/Plugins/Events");
PreLoadComponents().Wait();
if (!Config.ContainsKey("ServerID"))
if (!Config.Variables.Exists("ServerID") || !Config.Variables.Exists("token") ||
Config.Variables.GetValue("token") == null ||
(Config.Variables.GetValue("token")?.Length != 70 && Config.Variables.GetValue("token")?.Length != 59) ||
!Config.Variables.Exists("prefix") || Config.Variables.GetValue("prefix") == null ||
Config.Variables.GetValue("prefix")?.Length != 1 ||
(args.Length == 1 && args[0] == "/reset"))
{
do
{
Console.Clear();
Console.WriteLine("Please enter the server ID: ");
Console_Utilities.WriteColorText("You can find it in the Server Settings at &r\"Widget\"&c section");
Console.WriteLine("Example: 1234567890123456789");
Console.WriteLine("This is not required, but is recommended. If you refuse to provide the ID, just press enter.\nThe server id is required to make easier for the bot to interact with the server.\nRemember: this bot is for one server ONLY.");
Console.Write("User Input > ");
ConsoleKeyInfo key = Console.ReadKey();
if (key.Key == ConsoleKey.Enter)
Config.AddValueToVariables("ServerID", "null", false);
else
{
string SID = key.KeyChar + Console.ReadLine();
if (SID.Length != 18)
{
Console.WriteLine("Your server ID is not 18 characters long. Please try again.");
continue;
GenerateStartUI("First time setup. Please fill the following with your discord bot data.\nThis are saved ONLY on YOUR computer.");
}
Config.AddValueToVariables("ServerID", SID, false);
}
break;
} while (true);
}
if (!Config.ContainsKey("token") || Config.GetValue<string>("token") == null || Config.GetValue<string>("token")?.Length != 70)
{
Console.WriteLine("Please insert your token");
Console.Write("Token = ");
var token = Console.ReadLine();
if (token?.Length == 59 || token?.Length == 70)
Config.AddValueToVariables("token", token, true);
else
Console.WriteLine("Invalid token");
Console.WriteLine("Please insert your prefix (max. 1 character long):");
Console.WriteLine("For a prefix longer then one character, the first character will be saved and the others will be ignored.\n No spaces or numbers allowed");
Console.Write("Prefix = ");
var prefix = Console.ReadLine()![0];
if (prefix == ' ' || char.IsDigit(prefix))
return;
Config.AddValueToVariables("prefix", prefix.ToString(), false);
}
if (!Config.ContainsKey("prefix") || Config.GetValue<string>("prefix") == default)
{
Console.WriteLine("Please insert your prefix (max. 1 character long):");
Console.WriteLine("For a prefix longer then one character, the first character will be saved and the others will be ignored.\n No spaces or numbers allowed");
Console.Write("Prefix = ");
var prefix = Console.ReadLine()![0];
if (prefix == ' ') return;
Config.AddValueToVariables("prefix", prefix.ToString(), false);
}
HandleInput(args).Wait();
}
/// <summary>
/// The main loop for the discord bot
/// </summary>
/// <param name="discordbooter">The discord booter used to start the application</param>
private static void NoGUI(Boot discordbooter)
private static void NoGUI()
{
var consoleCommandsHandler = new ConsoleCommandsHandler(discordbooter.client);
#if DEBUG
Console.WriteLine();
consoleCommandsHandler.HandleCommand("lp");
#else
if (loadPluginsOnStartup) consoleCommandsHandler.HandleCommand("lp");
if (listPluginsAtStartup) consoleCommandsHandler.HandleCommand("listplugs");
Logger.WriteLine();
Logger.WriteLine("Debug mode enabled");
Logger.WriteLine();
#endif
Config.SaveConfig();
if (loadPluginsOnStartup)
consoleCommandsHandler.HandleCommand("lp");
while (true)
{
//Console_Utilities.WriteColorText("&rSethBot (&yDEBUG&r) &c> ", false);
var cmd = Console.ReadLine();
if (!consoleCommandsHandler.HandleCommand(cmd!,
if (!consoleCommandsHandler.HandleCommand(cmd!
#if DEBUG
false
, false
#endif
) && cmd.Length > 0)
Console.WriteLine("Failed to run command " + cmd);
Logger.WriteLine("Failed to run command " + cmd);
}
}
@@ -131,68 +79,55 @@ public class Program
/// Start the bot without user interface
/// </summary>
/// <returns>Returns the boot loader for the Discord Bot</returns>
private static async Task<Boot> StartNoGUI()
private static async Task<Boot> StartNoGui()
{
Console.Clear();
Console.ForegroundColor = ConsoleColor.DarkYellow;
List<string> startupMessageList = await ServerCom.ReadTextFromURL("https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/StartupMessage");
var startupMessageList =
await ServerCom.ReadTextFromURL(
"https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/StartupMessage");
foreach (var message in startupMessageList)
Console.WriteLine(message);
Logger.WriteLine(message);
Console.WriteLine($"Running on version: {Config.GetValue<string>("Version") ?? System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString()}");
Console.WriteLine($"Git URL: {Config.GetValue<string>("GitURL") ?? " Could not find Git URL"}");
Logger.WriteLine(
$"Running on version: {Assembly.GetExecutingAssembly().GetName().Version}");
Logger.WriteLine($"Git URL: {Settings.Variables.WebsiteURL}");
Console_Utilities.WriteColorText("&rRemember to close the bot using the ShutDown command (&ysd&r) or some settings won't be saved\n");
Utilities.WriteColorText(
"&rRemember to close the bot using the ShutDown command (&ysd&r) or some settings won't be saved\n");
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine($"============================ LOG ============================");
if (Config.Variables.Exists("LaunchMessage"))
Utilities.WriteColorText(Config.Variables.GetValue("LaunchMessage"));
Utilities.WriteColorText(
"Please note that the bot saves a backup save file every time you are using the shudown command (&ysd&c)");
Logger.WriteLine("============================ LOG ============================");
try
{
var token = Config.GetValue<string>("token");
string token = "";
#if DEBUG
Console.WriteLine("Starting in DEBUG MODE");
if (!Directory.Exists("./Data/BetaTest"))
Console.WriteLine("Failed to start in debug mode because the folder ./Data/BetaTest does not exist");
else
{
token = File.ReadAllText("./Data/BetaTest/token.txt");
//Debug mode code...
}
if (File.Exists("./Data/Resources/token.txt")) token = File.ReadAllText("./Data/Resources/token.txt");
else token = Config.Variables.GetValue("token");
#else
token = Config.Variables.GetValue("token");
#endif
var prefix = Config.GetValue<string>("prefix");
var prefix = Config.Variables.GetValue("prefix");
var discordbooter = new Boot(token, prefix);
await discordbooter.Awake();
return discordbooter;
}
catch (Exception ex)
{
Console.WriteLine(ex);
Logger.LogError(ex);
return null;
}
}
/// <summary>
/// Clear folder
/// </summary>
/// <param name="d">Directory path</param>
private static Task ClearFolder(string d)
{
var files = Directory.GetFiles(d);
var fileNumb = files.Length;
for (var i = 0; i < fileNumb; i++)
{
File.Delete(files[i]);
Console.WriteLine("Deleting : " + files[i]);
}
return Task.CompletedTask;
}
/// <summary>
/// Handle user input arguments from the startup of the application
/// </summary>
@@ -201,165 +136,365 @@ public class Program
{
var len = args.Length;
if (len == 3 && args[0] == "/download")
var b = await StartNoGui();
consoleCommandsHandler = new ConsoleCommandsHandler(b.client);
if (Entry.startupArguments.loadPluginsAtStartup) { loadPluginsOnStartup = true; }
if (len > 0 && args[0] == "/remplug")
{
var url = args[1];
var location = args[2];
await ServerCom.DownloadFileAsync(url, location);
return;
}
if (len > 0 && (args.Contains("--cmd") || args.Contains("--args") || args.Contains("--nomessage")))
{
if (args.Contains("lp") || args.Contains("loadplugins"))
var plugName = string.Join(' ', args, 1, args.Length - 1);
Logger.WriteLine("Starting to remove " + plugName);
await ConsoleCommandsHandler.ExecuteCommad("remplug " + plugName);
loadPluginsOnStartup = true;
if (args.Contains("listplugs"))
listPluginsAtStartup = true;
len = 0;
}
if (len == 0 || (args[0] != "--exec" && args[0] != "--execute"))
{
var b = await StartNoGUI();
Thread mainThread = new Thread(() => NoGUI(b));
var mainThread = new Thread(() =>
{
try
{
NoGUI();
}
catch (IOException ex)
{
if (ex.Message == "No process is on the other end of the pipe." || (uint)ex.HResult == 0x800700E9)
{
if (Config.Variables.Exists("LaunchMessage"))
Config.Variables.Add("LaunchMessage",
"An error occured while closing the bot last time. Please consider closing the bot using the &rsd&c method !\nThere is a risk of losing all data or corruption of the save file, which in some cases requires to reinstall the bot !",
false);
Logger.WriteErrFile(ex.ToString());
}
}
});
mainThread.Start();
return;
}
Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.WriteLine("Execute command interface noGUI\n\n");
Console.WriteLine(
"\tCommand name\t\t\t\tDescription\n" +
"-- help | -help\t\t ------ \tDisplay the help message\n" +
"--reset-full\t\t ------ \tReset all files (clear files)\n" +
"--reset-logs\t\t ------ \tClear up the output folder\n" +
"--start\t\t ------ \tStart the bot\n" +
"exit\t\t\t ------ \tClose the application"
);
while (true)
private static async Task PreLoadComponents(string[] args)
{
Console.ForegroundColor = ConsoleColor.White;
Console.Write("> ");
var message = Console.ReadLine().Split(' ');
Directory.CreateDirectory("./Data/Resources");
Directory.CreateDirectory("./Data/Plugins");
Directory.CreateDirectory("./Data/PAKS");
switch (message[0])
if (!File.Exists(Functions.dataFolder + "loader.json"))
{
case "--help":
case "-help":
Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.WriteLine("\tCommand name\t\t\t\tDescription\n" + "-- help | -help\t\t ------ \tDisplay the help message\n" + "--reset-full\t\t ------ \tReset all files (clear files)\n" + "--reset-settings\t ------ \tReset only bot settings\n" + "--reset-logs\t\t ------ \tClear up the output folder\n" + "--start\t\t ------ \tStart the bot\n" + "exit\t\t\t ------ \tClose the application");
break;
case "--reset-full":
await ClearFolder("./Data/Resources/");
await ClearFolder("./Output/Logs/");
await ClearFolder("./Output/Errors");
await ClearFolder("./Data/Languages/");
await ClearFolder("./Data/Plugins/Commands");
await ClearFolder("./Data/Plugins/Events");
Console.WriteLine("Successfully cleared all folders");
break;
case "--reset-logs":
await ClearFolder("./Output/Logs");
await ClearFolder("./Output/Errors");
Console.WriteLine("Successfully clear logs folder");
break;
case "--exit":
case "exit":
Environment.Exit(0);
break;
Entry.startupArguments = new StartupArguments();
await Functions.SaveToJsonFile(Functions.dataFolder + "loader.json", Entry.startupArguments);
}
else
Entry.startupArguments = await Functions.ConvertFromJson<StartupArguments>(Functions.dataFolder + "loader.json");
default:
Console.WriteLine("Failed to execute command " + message[0]);
break;
}
}
}
private static async Task PreLoadComponents()
{
await Config.LoadConfig();
if (Config.ContainsKey("DeleteLogsAtStartup"))
if (Config.GetValue<bool>("DeleteLogsAtStartup"))
Settings.sqlDatabase = new SqlDatabase("SetDB.dat");
await Settings.sqlDatabase.Open();
await Config.Initialize();
Logger.Initialize(true);
ArchiveManager.Initialize();
Logger.LogEvent += (message) => { Console.Write(message); };
Logger.WriteLine("Loading resources ...");
var main = new Utilities.ProgressBar(ProgressBarType.NO_END);
main.Start();
if (await Config.Variables.ExistsAsync("DeleteLogsAtStartup"))
if (await Config.Variables.GetValueAsync("DeleteLogsAtStartup") == "true")
foreach (var file in Directory.GetFiles("./Output/Logs/"))
File.Delete(file);
List<string> OnlineDefaultKeys = await ServerCom.ReadTextFromURL("https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/SetupKeys");
var OnlineDefaultKeys =
await ServerCom.ReadTextFromURL(
"https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/SetupKeys");
Config.PluginConfig.Load();
if (!Config.ContainsKey("Version"))
Config.AddValueToVariables("Version", Assembly.GetExecutingAssembly().GetName().Version.ToString(), false);
if (!await Config.Variables.ExistsAsync("Version"))
await Config.Variables.AddAsync("Version", Assembly.GetExecutingAssembly().GetName().Version.ToString(),
false);
else
Config.SetValue("Version", Assembly.GetExecutingAssembly().GetName().Version.ToString());
await Config.Variables.SetValueAsync(
"Version", Assembly.GetExecutingAssembly().GetName().Version.ToString());
foreach (var key in OnlineDefaultKeys)
{
if (key.Length <= 3 || !key.Contains(' ')) continue;
string[] s = key.Split(' ');
var s = key.Split(' ');
try
{
if (Config.ContainsKey(s[0])) Config.SetValue(s[0], s[1]);
else Config.GetAndAddValueToVariable(s[0], s[1], s[2].Equals("true", StringComparison.CurrentCultureIgnoreCase));
if (await Config.Variables.ExistsAsync(s[0])) await Config.Variables.SetValueAsync(s[0], s[1]);
else
await Config.Variables.AddAsync(s[0], s[1], s[2].ToLower() == "true");
}
catch (Exception ex)
{
Functions.WriteErrFile(ex.Message);
Logger.WriteErrFile(ex.Message);
}
}
List<string> onlineSettingsList = await ServerCom.ReadTextFromURL("https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/OnlineData");
var onlineSettingsList =
await ServerCom.ReadTextFromURL(
"https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/OnlineData");
main.Stop("Loaded online settings. Loading updates ...");
foreach (var key in onlineSettingsList)
{
if (key.Length <= 3 || !key.Contains(' ')) continue;
string[] s = key.Split(' ');
var s = key.Split(' ');
switch (s[0])
{
case "CurrentVersion":
string newVersion = s[1];
if (!newVersion.Equals(Config.GetValue<string>("Version")))
var newVersion = s[1];
if (!newVersion.Equals(await Config.Variables.GetValueAsync("Version")))
{
Console.WriteLine("A new version has been released on github page.");
Console.WriteLine("Download the new version using the following link wrote in yellow");
Console_Utilities.WriteColorText("&y" + Config.GetValue<string>("GitURL") + "&c");
Console.WriteLine();
Console.WriteLine("Your product will work just fine on this outdated version, but an update is recommended.\n" +
"From now on, this version is no longer supported"
);
Console_Utilities.WriteColorText("&rUse at your own risk&c");
Console_Utilities.WriteColorText("&mCurrent Version: " + Config.GetValue<string>("Version") + "&c");
Console_Utilities.WriteColorText("&gNew Version: " + newVersion + "&c");
Console.WriteLine("\n\n");
await Task.Delay(1000);
int waitTime = 10; //wait time to proceed
Console.Write($"The bot will start in {waitTime} seconds");
while (waitTime > 0)
var nVer = new VersionString(newVersion.Substring(2));
var cVer = new VersionString((await Config.Variables.GetValueAsync("Version")).Substring(2));
if (cVer > nVer)
{
await Task.Delay(1000);
waitTime--;
Console.SetCursorPosition("The bot will start in ".Length, Console.CursorTop);
Console.Write(" ");
Console.SetCursorPosition("The bot will start in ".Length, Console.CursorTop);
Console.Write(waitTime + " seconds");
await Config.Variables.SetValueAsync("Version", "1." + cVer.ToShortString() + " (Beta)");
break;
}
Console.Clear();
Console.ForegroundColor = ConsoleColor.Red;
Logger.WriteLine("A new version of the bot is available !");
Console.ForegroundColor = ConsoleColor.Yellow;
Logger.WriteLine("Current version : " +
Assembly.GetExecutingAssembly().GetName().Version.ToString());
Console.ForegroundColor = ConsoleColor.Green;
Logger.WriteLine("New version : " + newVersion);
Console.ForegroundColor = ConsoleColor.White;
Logger.WriteLine("Changelog :");
List<string> changeLog = await ServerCom.ReadTextFromURL(
"https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/VersionData/DiscordBot");
foreach (var item in changeLog)
Utilities.WriteColorText(item);
Logger.WriteLine("Do you want to update the bot ? (y/n)");
if (Console.ReadKey().Key == ConsoleKey.Y)
{
if (Functions.GetOperatingSystem() == OperatingSystem.WINDOWS)
{
var url =
$"https://github.com/Wizzy69/SethDiscordBot/releases/download/v{newVersion}/net6.0.zip";
Process.Start($"{Functions.dataFolder}Applications/Updater.exe",
$"{newVersion} {url} {Process.GetCurrentProcess().ProcessName}");
}
else
{
var url =
$"https://github.com/Wizzy69/SethDiscordBot/releases/download/v{newVersion}/net6.0_linux.zip";
if (Logger.isConsole)
Console.SetCursorPosition(0, Console.CursorTop);
Logger.WriteLine($"executing: download_file {url}");
await ServerCom.DownloadFileAsync(url, "./update.zip", new Progress<float>(percent => { Logger.Write($"\rProgress: {percent}% "); }));
await File.WriteAllTextAsync("Install.sh",
"#!/bin/bash\nunzip -qq -o update.zip \nrm update.zip\nchmod a+x DiscordBot");
Logger.WriteLine();
try
{
Logger.WriteLine("executing: chmod a+x Install.sh");
Process.Start("chmod", "a+x Install.sh").WaitForExit();
Process.Start("Install.sh").WaitForExit();
Logger.WriteLine("executing: rm Install.sh");
Process.Start("rm", "Install.sh").WaitForExit();
Logger.WriteLine("The new version of the bot has been installed.");
Logger.WriteLine("Please restart the bot.");
Environment.Exit(0);
}
catch (Exception ex)
{
Logger.WriteErrFile(ex.Message);
if (ex.Message.Contains("Access de"))
Logger.WriteLine("Please run the bot as root.");
}
//Process.Start(Functions.dataFolder + "Applications/Updater", $"{url}");
}
}
}
break;
case "UpdaterVersion":
var updaternewversion = s[1];
if (Functions.GetOperatingSystem() == OperatingSystem.LINUX)
break;
if (!await Config.Variables.ExistsAsync("UpdaterVersion"))
await Config.Variables.AddAsync("UpdaterVersion", "0.0.0.0", false);
if (await Config.Variables.GetValueAsync("UpdaterVersion") != updaternewversion ||
!File.Exists(Functions.dataFolder+"Applications/Updater.exe"))
{
Console.Clear();
Logger.WriteLine("Installing updater ...\nDo NOT close the bot during update !");
var bar = new Utilities.ProgressBar(ProgressBarType.NO_END);
bar.Start();
await ServerCom.DownloadFileNoProgressAsync(
"https://github.com/Wizzy69/installer/releases/download/release-1-discordbot/Updater.exe",
$"{Functions.dataFolder}Applications/Updater.exe");
//await ArchiveManager.ExtractArchive("./Updater.zip", "./", null,
// UnzipProgressType.PercentageFromTotalSize);
await Config.Variables.SetValueAsync("UpdaterVersion", updaternewversion);
// File.Delete("Updater.zip");
bar.Stop("Updater has been updated !");
Console.Clear();
}
break;
}
}
Console_Utilities.Initialize();
Console.Clear();
}
Config.SaveConfig();
public static void GenerateStartUI(string titleMessage)
{
Application.Init();
var top = Application.Top;
var win = new Window("Discord Bot Config - " + Assembly.GetExecutingAssembly().GetName().Version)
{
X = 0,
Y = 1,
Width = Dim.Fill(),
Height = Dim.Fill()
};
top.Add(win);
var labelInfo = new Label(titleMessage)
{
X = Pos.Center(),
Y = 2
};
var labelToken = new Label("Please insert your token here: ")
{
X = 5,
Y = 5
};
var textFiledToken = new TextField(Config.Variables.GetValue("token") ?? "")
{
X = Pos.Left(labelToken) + labelToken.Text.Length + 2,
Y = labelToken.Y,
Width = 70
};
var labelPrefix = new Label("Please insert your prefix here: ")
{
X = 5,
Y = 8
};
var textFiledPrefix = new TextField(Config.Variables.GetValue("prefix") ?? "")
{
X = Pos.Left(labelPrefix) + labelPrefix.Text.Length + 2,
Y = labelPrefix.Y,
Width = 1
};
var labelServerid = new Label("Please insert your server id here (optional): ")
{
X = 5,
Y = 11
};
var textFiledServerID = new TextField(Config.Variables.GetValue("ServerID") ?? "")
{
X = Pos.Left(labelServerid) + labelServerid.Text.Length + 2,
Y = labelServerid.Y,
Width = 18
};
var button = new Button("Submit")
{
X = Pos.Center() - 10,
Y = 16
};
var button2 = new Button("License")
{
X = Pos.Center() + 10,
Y = 16
};
var button3 = new Button("ⓘ")
{
X = Pos.Left(textFiledServerID) + 20,
Y = textFiledServerID.Y
};
Console.CancelKeyPress += (sender, e) => { top.Running = false; };
button.Clicked += () =>
{
var passMessage = "";
if (textFiledToken.Text.Length != 70 && textFiledToken.Text.Length != 59)
passMessage += "Invalid token, ";
if (textFiledPrefix.Text.ContainsAny("0123456789/\\ ") || textFiledPrefix.Text.Length != 1)
passMessage += "Invalid prefix, ";
if (textFiledServerID.Text.Length != 18 && textFiledServerID.Text.Length > 0)
passMessage += "Invalid serverID";
if (passMessage != "")
{
MessageBox.ErrorQuery("Discord Bot Settings",
"Failed to pass check. Invalid information given:\n" + passMessage, "Retry");
return;
}
Config.Variables.Add("ServerID", (string)textFiledServerID.Text, true);
Config.Variables.Add("token", (string)textFiledToken.Text, true);
Config.Variables.Add("prefix", (string)textFiledPrefix.Text, true);
MessageBox.Query("Discord Bot Settings", "Successfully saved config !\nJust start the bot :D",
"Start :D");
top.Running = false;
};
button2.Clicked += async () =>
{
var license =
await ServerCom.ReadTextFromURL(
"https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/LICENSE.txt");
var ProductLicense =
"Seth Discord Bot\n\nDeveloped by Wizzy#9181\nThis application can be used and modified by anyone. Plugin development for this application is also free and supported";
var r = MessageBox.Query("Discord Bot Settings", ProductLicense, "Close", "Read about libraries used");
if (r == 1)
{
var i = 0;
while (i < license.Count)
{
var print_message = license[i++] + "\n";
for (; i < license.Count && !license[i].StartsWith("-----------"); i++)
print_message += license[i] + "\n";
if (print_message.Contains("https://"))
print_message += "\n\nCTRL + Click on a link to open it";
if (MessageBox.Query("Licenses", print_message, "Next", "Quit") == 1) break;
}
}
};
button3.Clicked += () =>
{
MessageBox.Query("Discord Bot Settings",
"Server ID can be found in Server settings => Widget => Server ID",
"Close");
};
win.Add(labelInfo, labelPrefix, labelServerid, labelToken);
win.Add(textFiledToken, textFiledPrefix, textFiledServerID, button3);
win.Add(button, button2);
Application.Run();
Application.Shutdown();
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DiscordBot
{
internal class StartupArguments
{
public string runArgs { get; } = "";
public bool loadPluginsAtStartup { get; } = true;
}
}

View File

@@ -1,14 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\PluginManager\PluginManager.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,21 +0,0 @@
using PluginManager.Online.Updates;
try
{
bool requireUpdate = await PluginUpdater.CheckForUpdates("DiscordBotConsoleLauncher");
if (requireUpdate)
{
var update = await PluginUpdater.DownloadUpdateInfo("DiscordBotConsoleLauncher");
if (update == Update.Empty)
return;
Console.WriteLine("Found an update: ");
Console.WriteLine(update.ToString());
}
}
catch (Exception ex)
{
Console.WriteLine("An exception was thrown. ");
Console.WriteLine(ex.Message);
Environment.Exit(-2);
}

View File

@@ -1,20 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<BaseOutputPath></BaseOutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Remove="bin\**" />
<EmbeddedResource Remove="bin\**" />
<None Remove="bin\**" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PluginManager\PluginManager.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,59 +0,0 @@
using Discord;
using Discord.WebSocket;
using EVE_LevelingSystem.LevelingSystemCore;
using PluginManager;
using PluginManager.Interfaces;
using PluginManager.Others;
namespace EVE_LevelingSystem
{
internal class Level : DBEvent
{
public string name => "Leveling System Event Handler";
public string description => "The Leveling System Event Handler";
internal static Settings globalSettings = new();
public async void Start(DiscordSocketClient client)
{
Directory.CreateDirectory("./Data/Resources/LevelingSystem");
if (!Config.ContainsKey("LevelingSystemPath"))
Config.AddValueToVariables("LevelingSystemPath", "./Data/Resources/LevelingSystem", true);
if (!Config.ContainsKey("LevelingSystemSettingsFile"))
Config.AddValueToVariables("LevelingSystemSettingsFile", "./Data/Resources/LevelingSystemSettings.txt", true);
//PluginManager.Config.AddValueToVariables
if (!File.Exists(Config.GetValue<string>("LevelingSystemSettingsFile")))
{
globalSettings = new Settings { TimeToWaitBetweenMessages = 5 };
await Functions.SaveToJsonFile<Settings>(Config.GetValue<string>("LevelingSystemSettingsFile"), globalSettings);
}
else
globalSettings = await Functions.ConvertFromJson<Settings>(Config.GetValue<string>("LevelingSystemSettingsFile"));
// Console.WriteLine(globalSettings.TimeToWaitBetweenMessages);
client.MessageReceived += ClientOnMessageReceived;
}
private async Task ClientOnMessageReceived(SocketMessage arg)
{
if (arg.Author.IsBot || arg.IsTTS || arg.Content.StartsWith(Config.GetValue<string>("prefix"))) return;
string userID = arg.Author.Id.ToString();
User user;
if (File.Exists($"{Config.GetValue<string>("LevelingSystemPath")}/{userID}.dat"))
{
user = await Functions.ConvertFromJson<User>(Config.GetValue<string>("LevelingSystemPath")! + $"/{userID}.dat");
// Console.WriteLine(Config.GetValue("LevelingSystemPath"));
if (user.AddEXP()) await arg.Channel.SendMessageAsync($"{arg.Author.Mention} is now level {user.CurrentLevel}");
await Functions.SaveToJsonFile(Config.GetValue<string>("LevelingSystemPath") + $"/{userID}.dat", user);
return;
}
user = new User { CurrentEXP = 0, CurrentLevel = 1, RequiredEXPToLevelUp = LevelCalculator.GetNextLevelRequiredEXP(1), user = new DiscordUser { DiscordTag = arg.Author.DiscriminatorValue, userID = arg.Author.Id, Username = arg.Author.Username } };
if (user.AddEXP()) await arg.Channel.SendMessageAsync($"{arg.Author.Mention} is now level {user.CurrentLevel}");
await Functions.SaveToJsonFile<User>($"{Config.GetValue<string>("LevelingSystemPath")}/{userID}.dat", user);
}
}
}

View File

@@ -1,58 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PluginManager;
namespace EVE_LevelingSystem.LevelingSystemCore
{
internal static class LevelCalculator
{
internal static List<string> OnWaitingList = new();
internal static Int64 GetNextLevelRequiredEXP(int currentLevel)
{
return currentLevel * 8 + 24;
}
internal static void LevelUp(this User user)
{
user.CurrentEXP = 0;
user.RequiredEXPToLevelUp = GetNextLevelRequiredEXP(user.CurrentLevel);
user.CurrentLevel++;
}
internal static bool AddEXP(this User user)
{
if (OnWaitingList.Contains(user.user.userID.ToString())) return false;
Random r = new Random();
int exp = r.Next(Level.globalSettings.MinEXP, Level.globalSettings.MaxEXP + 1);
Int64 userXP = user.CurrentEXP;
Int64 reqEXP = user.RequiredEXPToLevelUp;
if (userXP + exp >= reqEXP)
{
user.LevelUp();
user.CurrentEXP = exp - (reqEXP - userXP);
//Console.WriteLine("Level up");
return true;
}
user.CurrentEXP += exp;
OnWaitingList.Add(user.user.userID.ToString());
new Thread(() =>
{
int minutesToWait = Level.globalSettings.TimeToWaitBetweenMessages;
Thread.Sleep(60000 * minutesToWait);
OnWaitingList.Remove(user.user.userID.ToString());
}
).Start();
return false;
}
}
}

View File

@@ -1,20 +0,0 @@
using Discord;
using Discord.WebSocket;
namespace EVE_LevelingSystem.LevelingSystemCore
{
public class DiscordUser
{
public string Username { get; set; }
public ushort DiscordTag { get; set; }
public ulong userID { get; set; }
}
public class User
{
public DiscordUser user { get; set; }
public int CurrentLevel { get; set; }
public long CurrentEXP { get; set; }
public long RequiredEXPToLevelUp { get; set; }
}
}

View File

@@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EVE_LevelingSystem
{
public class Settings
{
public int TimeToWaitBetweenMessages { get; set; }
public int MinEXP { get; set; }
public int MaxEXP { get; set; }
}
}

View File

@@ -1,34 +0,0 @@
using AngleSharp.Dom;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MusicCommands
{
internal class AudioFile
{
internal string Name { get; set; }
internal string Url { get; set; }
internal AudioFile(string name, string url)
{
Name = name;
Url = url;
}
internal async Task DownloadAudioFile()
{
Process proc = new Process();
proc.StartInfo.FileName = "MusicDownloader.exe";
proc.StartInfo.Arguments = $"{Url},{Name}";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.Start();
await proc.WaitForExitAsync();
}
}
}

View File

@@ -1,13 +0,0 @@
using Discord;
using Discord.Audio;
namespace MusicCommands;
internal static class Data
{
internal static IAudioClient audioClient = null;
internal static IVoiceChannel voiceChannel = null;
internal static MusicPlayer MusicPlayer = null;
internal static MusicPlaylist Playlist = new();
}

View File

@@ -1,44 +0,0 @@
using System.Collections.Generic;
using Discord.Commands;
using Discord.WebSocket;
using PluginManager.Interfaces;
namespace MusicCommands;
internal class Leave : DBCommand
{
public string Command => "leave";
public List<string> Aliases => null;
public string Description => "Leave the voice channel";
public string Usage => "leave";
public bool canUseDM => false;
public bool canUseServer => true;
public bool requireAdmin => false;
public async void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM)
{
if (Data.audioClient is not null && Data.voiceChannel is not null)
{
await Data.audioClient.StopAsync();
await Data.voiceChannel.DisconnectAsync();
}
if (Data.Playlist is not null)
{
Data.Playlist.ClearQueue();
Data.Playlist = new();
}
if (Data.MusicPlayer is not null)
{
Data.MusicPlayer.Stop();
Data.MusicPlayer = null;
}
}
}

View File

@@ -1,25 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>warnings</Nullable>
<BaseOutputPath>bin\</BaseOutputPath>
<AssemblyName>Music Commands</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputPath>../BUILDS/</OutputPath>
<ErrorReport>none</ErrorReport>
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\PluginManager\PluginManager.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="YoutubeExplode" Version="6.2.0" />
</ItemGroup>
</Project>

View File

@@ -1,53 +0,0 @@
using System.IO;
using System.Threading.Tasks;
namespace MusicCommands;
internal class MusicPlayer
{
private Stream outputStream { get; }
internal AudioFile NowPlaying = null;
internal bool isPlaying, isPaused;
public MusicPlayer(Stream outputChannel)
{
outputStream = outputChannel;
}
public async Task Play(Stream source, int byteSize, AudioFile songPlaying)
{
isPlaying = true;
NowPlaying = songPlaying;
while (isPlaying)
{
if (isPaused)
continue;
var bits = new byte[byteSize];
var read = await source.ReadAsync(bits, 0, byteSize);
if (read == 0)
break;
try
{
await outputStream.WriteAsync(bits, 0, read);
}
catch
{
break;
}
}
await source.FlushAsync();
await source.DisposeAsync();
source.Close();
await outputStream.FlushAsync();
isPlaying = false;
}
public void Stop()
{
isPlaying = false;
}
}

View File

@@ -1,25 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MusicCommands
{
internal class MusicPlaylist
{
internal MusicPlaylist()
{
Console.WriteLine("Initialized playlist.");
}
public Queue<AudioFile> QueueList = new();
public void Enqueue(AudioFile query) => QueueList.Enqueue(query);
public void ClearQueue() => QueueList.Clear();
public int Count => QueueList.Count;
public AudioFile GetNextSong => QueueList.Dequeue();
public AudioFile WhatIsNext => QueueList.Peek();
}
}

View File

@@ -1,28 +0,0 @@
using System.Collections.Generic;
using Discord.Commands;
using Discord.WebSocket;
using PluginManager.Interfaces;
namespace MusicCommands;
internal class Pause : DBCommand
{
public string Command => "pause";
public List<string> Aliases => null;
public string Description => "Pause/Unpause the music that is currently running";
public string Usage => "pause";
public bool canUseDM => false;
public bool canUseServer => true;
public bool requireAdmin => false;
public void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM)
{
Data.MusicPlayer.isPaused = !Data.MusicPlayer.isPaused;
}
}

View File

@@ -1,119 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using Discord;
using Discord.Audio;
using Discord.Commands;
using Discord.WebSocket;
using PluginManager.Interfaces;
using PluginManager.Others;
namespace MusicCommands;
internal class Play : DBCommand
{
public string Command => "play";
public List<string> Aliases => new() { "p" };
public string Description => "Play music from a file";
public string Usage => "play [name/url]";
public bool canUseDM => false;
public bool canUseServer => true;
public bool requireAdmin => false;
public async void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM)
{
Directory.CreateDirectory("Music");
var path = "./Music/";
string[] splitted = message.Content.Split(' ');
if (splitted.Length < 2)
return;
do
{
if (splitted.Length == 2 && splitted[1].Contains("youtube.com") || splitted[1].Contains("youtu.be"))
{
var url = splitted[1];
path += $"{Functions.CreateMD5(url)}";
if (File.Exists(path))
{
Data.Playlist.Enqueue(new AudioFile(path, null));
}
else
{
var file = new AudioFile(path, url);
await file.DownloadAudioFile();
Data.Playlist.Enqueue(file);
}
}
else
{
var searchString = splitted.MergeStrings(1);
path += $"{Functions.CreateMD5(searchString)}";
if (File.Exists(path))
{
Data.Playlist.Enqueue(new AudioFile(path, null));
}
else
{
await context.Channel.SendMessageAsync("Searching for " + searchString);
var file = new AudioFile(path, searchString);
await file.DownloadAudioFile();
Data.Playlist.Enqueue(file);
if (Data.MusicPlayer is null)
await context.Channel.SendMessageAsync("Playing: " + searchString);
}
}
if (Data.MusicPlayer is not null)
{
await context.Channel.SendMessageAsync("Queued your request: " + splitted.MergeStrings(1));
return;
}
}
while (false); // run only one time !
Data.voiceChannel = (context.User as IGuildUser)?.VoiceChannel;
if (Data.voiceChannel == null)
{
await context.Channel.SendMessageAsync("User must be in a voice channel, or a voice channel must be passed as an argument.");
return;
}
if (Data.audioClient is null)
{
Data.audioClient = await Data.voiceChannel.ConnectAsync(true);
Data.MusicPlayer = null;
}
using (var discordChanneAudioOutStream = Data.audioClient.CreatePCMStream(AudioApplication.Mixed))
{
Data.MusicPlayer ??= new MusicPlayer(discordChanneAudioOutStream);
while (Data.Playlist.Count > 0)
{
var nowPlaying = Data.Playlist.GetNextSong;
using (var ffmpeg = CreateStream(nowPlaying.Name))
using (var ffmpegOutputBaseStream = ffmpeg.StandardOutput.BaseStream)
{
await Data.MusicPlayer.Play(ffmpegOutputBaseStream, 1024, nowPlaying);
Console.WriteLine("Finished playing from " + nowPlaying.Url);
}
}
Data.MusicPlayer = null;
}
}
private static Process CreateStream(string path)
{
return Process.Start(new ProcessStartInfo { FileName = "ffmpeg", Arguments = $"-hide_banner -loglevel panic -i \"{path}\" -ac 2 -f s16le -ar 48000 pipe:1", UseShellExecute = false, RedirectStandardOutput = true });
}
}

View File

@@ -1,42 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Discord.Commands;
using Discord.WebSocket;
using PluginManager.Interfaces;
namespace MusicCommands
{
public class Skip : DBCommand
{
public string Command => "skip";
public List<string> Aliases => null;
public string Description => "skip the music that is currently running";
public string Usage => "skip";
public bool canUseDM => false;
public bool canUseServer => true;
public bool requireAdmin => false;
public void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM)
{
var loadedSong = Data.MusicPlayer.NowPlaying;
if (loadedSong is null || Data.MusicPlayer.isPlaying == false)
{
message.Channel.SendMessageAsync("There is no music playing");
return;
}
Data.MusicPlayer.isPlaying = false;
message.Channel.SendMessageAsync($"You have skipped {loadedSong.Name}");
}
}
}

View File

@@ -1,32 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Discord.Commands;
using Discord.WebSocket;
using PluginManager.Interfaces;
namespace MusicCommands
{
public class queue : DBCommand
{
public string Command => "queue";
public List<string> Aliases => new() { "q" };
public string Description => "check queue";
public string Usage => "queue";
public bool canUseDM => false;
public bool canUseServer => true;
public bool requireAdmin => false;
public async void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM)
{
await context.Channel.SendMessageAsync($"You have {Data.Playlist.Count} items in queue");
}
}
}

View File

@@ -1,209 +1,202 @@
using System;
using PluginManager.Others;
using System.IO;
using System.Text.Json;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading;
namespace PluginManager
using PluginManager.Online.Helpers;
namespace PluginManager;
public static class Config
{
internal class AppConfig
private static bool IsLoaded = false;
public static async Task Initialize()
{
public Dictionary<string, object>? ApplicationVariables { get; init; }
public List<string>? ProtectedKeyWords { get; init; }
public Dictionary<string, string> PluginVersions { get; init; }
}
public static class Config
{
public static class PluginConfig
{
public static readonly List<Tuple<string, PluginType>> InstalledPlugins = new();
public static void Load()
{
new Thread(LoadCommands).Start();
new Thread(LoadEvents).Start();
}
private static void LoadCommands()
{
string cmd_path = "./Data/Plugins/Commands/";
string[] files = Directory.GetFiles(cmd_path, $"*.{Loaders.PluginLoader.pluginCMDExtension}", SearchOption.AllDirectories);
foreach (var file in files)
if (!file.Contains("PluginManager", StringComparison.InvariantCultureIgnoreCase))
{
string PluginName = new FileInfo(file).Name;
string name = PluginName.Substring(0, PluginName.Length - 1 - PluginManager.Loaders.PluginLoader.pluginCMDExtension.Length);
InstalledPlugins.Add(new(name, PluginType.Command));
}
}
private static void LoadEvents()
{
string eve_path = "./Data/Plugins/Events/";
string[] files = Directory.GetFiles(eve_path, $"*.{Loaders.PluginLoader.pluginEVEExtension}", SearchOption.AllDirectories);
foreach (var file in files)
if (!file.Contains("PluginManager", StringComparison.InvariantCultureIgnoreCase))
if (!file.Contains("PluginManager", StringComparison.InvariantCultureIgnoreCase))
{
string PluginName = new FileInfo(file).Name;
string name = PluginName.Substring(0, PluginName.Length - 1 - PluginManager.Loaders.PluginLoader.pluginEVEExtension.Length);
InstalledPlugins.Add(new(name, PluginType.Event));
}
}
public static bool Contains(string pluginName)
{
foreach (var tuple in InstalledPlugins)
{
if (tuple.Item1 == pluginName) return true;
}
return false;
}
public static PluginType GetPluginType(string pluginName)
{
foreach (var tuple in InstalledPlugins)
if (tuple.Item1 == pluginName)
return tuple.Item2;
return PluginType.Unknown;
}
}
private static AppConfig? appConfig { get; set; }
public static string GetPluginVersion(string pluginName) => appConfig.PluginVersions[pluginName];
public static void SetPluginVersion(string pluginName, string newVersion)
{
if (appConfig.PluginVersions.ContainsKey(pluginName))
appConfig.PluginVersions[pluginName] = newVersion;
else appConfig.PluginVersions.Add(pluginName, newVersion);
// SaveConfig();
}
public static void RemovePluginVersion(string pluginName) => appConfig.PluginVersions.Remove(pluginName);
public static bool PluginVersionsContainsKey(string pluginName) => appConfig.PluginVersions.ContainsKey(pluginName);
public static void AddValueToVariables<T>(string key, T value, bool isProtected)
{
if (value == null)
throw new Exception("The value cannot be null");
if (appConfig!.ApplicationVariables!.ContainsKey(key))
throw new Exception($"The key ({key}) already exists in the variables. Value {GetValue<T>(key)}");
appConfig.ApplicationVariables.Add(key, value);
if (isProtected && key != "Version")
appConfig.ProtectedKeyWords!.Add(key);
SaveConfig();
}
public static Type GetVariableType(string value)
{
if (int.TryParse(value, out var intValue))
return typeof(int);
if (bool.TryParse(value, out var boolValue))
return typeof(bool);
if (float.TryParse(value, out var floatValue))
return typeof(float);
if (double.TryParse(value, out var doubleValue))
return typeof(double);
if (uint.TryParse(value, out var uintValue))
return typeof(uint);
if (long.TryParse(value, out var longValue))
return typeof(long);
if (byte.TryParse(value, out var byteValue))
return typeof(byte);
return typeof(string);
}
public static void GetAndAddValueToVariable(string key, string value, bool isReadOnly)
{
if (Config.ContainsKey(key))
if (IsLoaded)
return;
if (int.TryParse(value, out var intValue))
Config.AddValueToVariables(key, intValue, isReadOnly);
else if (bool.TryParse(value, out var boolValue))
Config.AddValueToVariables(key, boolValue, isReadOnly);
else if (float.TryParse(value, out var floatValue))
Config.AddValueToVariables(key, floatValue, isReadOnly);
else if (double.TryParse(value, out var doubleValue))
Config.AddValueToVariables(key, doubleValue, isReadOnly);
else if (uint.TryParse(value, out var uintValue))
Config.AddValueToVariables(key, uintValue, isReadOnly);
else if (long.TryParse(value, out var longValue))
Config.AddValueToVariables(key, longValue, isReadOnly);
else if (byte.TryParse(value, out var byteValue))
Config.AddValueToVariables(key, byteValue, isReadOnly);
else
Config.AddValueToVariables(key, value, isReadOnly);
if (!await Settings.sqlDatabase.TableExistsAsync("Plugins"))
await Settings.sqlDatabase.CreateTableAsync("Plugins", "PluginName", "Version");
if (!await Settings.sqlDatabase.TableExistsAsync("Variables"))
await Settings.sqlDatabase.CreateTableAsync("Variables", "VarName", "Value", "ReadOnly");
IsLoaded = true;
}
public static T? GetValue<T>(string key)
public static class Variables
{
if (!appConfig!.ApplicationVariables!.ContainsKey(key)) return default;
try
public static async Task<string> GetValueAsync(string VarName)
{
JsonElement element = (JsonElement)appConfig.ApplicationVariables[key];
return element.Deserialize<T>();
if (!IsLoaded)
throw new Exception("Config is not loaded");
return await Settings.sqlDatabase.GetValueAsync("Variables", "VarName", VarName, "Value");
}
catch
public static string GetValue(string VarName)
{
return (T)appConfig.ApplicationVariables[key];
if (!IsLoaded)
throw new Exception("Config is not loaded");
return Settings.sqlDatabase.GetValue("Variables", "VarName", VarName, "Value");
}
public static async Task SetValueAsync(string VarName, string Value)
{
if (!IsLoaded)
throw new Exception("Config is not loaded");
if (await IsReadOnlyAsync(VarName))
throw new Exception($"Variable ({VarName}) is read only and can not be changed to {Value}");
await Settings.sqlDatabase.SetValueAsync("Variables", "VarName", VarName, "Value", Value);
}
public static void SetValue(string VarName, string Value)
{
if (!IsLoaded)
throw new Exception("Config is not loaded");
if (IsReadOnly(VarName))
throw new Exception($"Variable ({VarName}) is read only and can not be changed to {Value}");
Settings.sqlDatabase.SetValue("Variables", "VarName", VarName, "Value", Value);
}
public static async Task<bool> IsReadOnlyAsync(string VarName)
{
if (!IsLoaded)
throw new Exception("Config is not loaded");
return (await Settings.sqlDatabase.GetValueAsync("Variables", "VarName", VarName, "ReadOnly")).Equals("true", StringComparison.CurrentCultureIgnoreCase);
}
public static bool IsReadOnly(string VarName)
{
if (!IsLoaded)
throw new Exception("Config is not loaded");
return (Settings.sqlDatabase.GetValue("Variables", "VarName", VarName, "ReadOnly")).Equals("true", StringComparison.CurrentCultureIgnoreCase);
}
public static async Task SetReadOnlyAsync(string VarName, bool ReadOnly)
{
if (!IsLoaded)
throw new Exception("Config is not loaded");
await Settings.sqlDatabase.SetValueAsync("Variables", "VarName", VarName, "ReadOnly", ReadOnly ? "true" : "false");
}
public static void SetReadOnly(string VarName, bool ReadOnly)
{
if (!IsLoaded)
throw new Exception("Config is not loaded");
Settings.sqlDatabase.SetValue("Variables", "VarName", VarName, "ReadOnly", ReadOnly ? "true" : "false");
}
public static async Task<bool> ExistsAsync(string VarName)
{
if (!IsLoaded)
throw new Exception("Config is not loaded");
return await Settings.sqlDatabase.KeyExistsAsync("Variables", "VarName", VarName);
}
public static bool Exists(string VarName)
{
if (!IsLoaded)
throw new Exception("Config is not loaded");
return Settings.sqlDatabase.KeyExists("Variables", "VarName", VarName);
}
public static async Task AddAsync(string VarName, string Value, bool ReadOnly = false)
{
if (!IsLoaded)
throw new Exception("Config is not loaded");
if (await ExistsAsync(VarName))
{
await SetValueAsync(VarName, Value);
await SetReadOnlyAsync(VarName, ReadOnly);
return;
}
await Settings.sqlDatabase.InsertAsync("Variables", VarName, Value, ReadOnly ? "true" : "false");
}
public static void Add(string VarName, string Value, bool ReadOnly = false)
{
if (!IsLoaded)
throw new Exception("Config is not loaded");
if (Exists(VarName))
{
if (GetValue(VarName) == Value)
return;
SetValue(VarName, Value);
SetReadOnly(VarName, ReadOnly);
return;
}
Settings.sqlDatabase.Insert("Variables", VarName, Value, ReadOnly ? "true" : "false");
}
public static async Task RemoveKeyAsync(string VarName)
{
if (!IsLoaded)
throw new Exception("Config is not loaded");
await Settings.sqlDatabase.RemoveKeyAsync("Variables", "VarName", VarName);
}
public static void RemoveKey(string VarName)
{
if (!IsLoaded)
throw new Exception("Config is not loaded");
Settings.sqlDatabase.RemoveKey("Variables", "VarName", VarName);
}
}
public static void SetValue<T>(string key, T value)
public static class Plugins
{
if (value == null)
throw new Exception("Value is null");
if (!appConfig!.ApplicationVariables!.ContainsKey(key))
throw new Exception("Key does not exist in the config file");
if (appConfig.ProtectedKeyWords!.Contains(key))
throw new Exception("Key is protected");
public static async Task<string> GetVersionAsync(string pluginName)
{
if (!IsLoaded)
throw new Exception("Config is not loaded yet");
appConfig.ApplicationVariables[key] = JsonSerializer.SerializeToElement(value);
SaveConfig();
string result = await Settings.sqlDatabase.GetValueAsync("Plugins", "PluginName", pluginName, "Version");
if (result is null)
return "0.0.0";
return result;
}
public static void RemoveKey(string key)
public static string GetVersion(string pluginName)
{
if (key == "Version" || key == "token" || key == "prefix")
throw new Exception("Key is protected");
appConfig!.ApplicationVariables!.Remove(key);
appConfig.ProtectedKeyWords!.Remove(key);
SaveConfig();
if (!IsLoaded)
throw new Exception("Config is not loaded yet");
string result = Settings.sqlDatabase.GetValue("Plugins", "PluginName", pluginName, "Version");
if (result is null)
return "0.0.0";
return result;
}
public static async void SaveConfig()
public static async Task SetVersionAsync(string pluginName, VersionString version)
{
string path = Functions.dataFolder + "config.json";
await Functions.SaveToJsonFile<AppConfig>(path, appConfig!);
if (!IsLoaded)
throw new Exception("Config is not loaded yet");
if (!await Settings.sqlDatabase.KeyExistsAsync("Plugins", "PluginName", pluginName))
{
await Settings.sqlDatabase.InsertAsync("Plugins", pluginName, version.ToShortString());
return;
}
await Settings.sqlDatabase.SetValueAsync("Plugins", "PluginName", pluginName, "Version", version.ToShortString());
}
public static async Task LoadConfig()
public static void SetVersion(string pluginName, VersionString version)
{
string path = Functions.dataFolder + "config.json";
if (File.Exists(path))
if (!IsLoaded)
throw new Exception("Config is not loaded yet");
if (!Settings.sqlDatabase.KeyExists("Plugins", "PluginName", pluginName))
{
appConfig = await Functions.ConvertFromJson<AppConfig>(path);
Functions.WriteLogFile($"Loaded {appConfig.ApplicationVariables!.Keys.Count} application variables.\nLoaded {appConfig.ProtectedKeyWords!.Count} readonly variables.");
}
else
appConfig = new() { ApplicationVariables = new Dictionary<string, object>(), ProtectedKeyWords = new List<string>(), PluginVersions = new Dictionary<string, string>() };
Settings.sqlDatabase.Insert("Plugins", pluginName, version.ToShortString());
return;
}
public static bool ContainsValue<T>(T value) => appConfig!.ApplicationVariables!.ContainsValue(value!);
public static bool ContainsKey(string key) => appConfig!.ApplicationVariables!.ContainsKey(key);
Settings.sqlDatabase.SetValue("Plugins", "PluginName", pluginName, "Version", version.ToShortString());
}
public static ReadOnlyDictionary<string, object> GetAllVariables() => new(appConfig!.ApplicationVariables!);
}
}

View File

@@ -0,0 +1,327 @@
using System.Collections.Generic;
using System.Data.SQLite;
using System.IO;
using System.Threading.Tasks;
namespace PluginManager.Database
{
public class SqlDatabase
{
private string ConnectionString;
private SQLiteConnection Connection;
public SqlDatabase(string fileName)
{
if (!fileName.StartsWith("./Data/Resources/"))
fileName = Path.Combine("./Data/Resources", fileName);
if (!File.Exists(fileName))
SQLiteConnection.CreateFile(fileName);
ConnectionString = $"URI=file:{fileName}";
Connection = new SQLiteConnection(ConnectionString);
}
public async Task Open()
{
await Connection.OpenAsync();
//Console.WriteLine("Opened database successfully");
}
public async Task InsertAsync(string tableName, params string[] values)
{
string query = $"INSERT INTO {tableName} VALUES (";
for (int i = 0; i < values.Length; i++)
{
query += $"'{values[i]}'";
if (i != values.Length - 1)
query += ", ";
}
query += ")";
SQLiteCommand command = new SQLiteCommand(query, Connection);
await command.ExecuteNonQueryAsync();
}
public void Insert(string tableName, params string[] values)
{
string query = $"INSERT INTO {tableName} VALUES (";
for (int i = 0; i < values.Length; i++)
{
query += $"'{values[i]}'";
if (i != values.Length - 1)
query += ", ";
}
query += ")";
SQLiteCommand command = new SQLiteCommand(query, Connection);
command.ExecuteNonQuery();
}
public async Task RemoveKeyAsync(string tableName, string KeyName, string KeyValue)
{
string query = $"DELETE FROM {tableName} WHERE {KeyName} = '{KeyValue}'";
SQLiteCommand command = new SQLiteCommand(query, Connection);
await command.ExecuteNonQueryAsync();
}
public void RemoveKey(string tableName, string KeyName, string KeyValue)
{
string query = $"DELETE FROM {tableName} WHERE {KeyName} = '{KeyValue}'";
SQLiteCommand command = new SQLiteCommand(query, Connection);
command.ExecuteNonQuery();
}
public async Task<bool> KeyExistsAsync(string tableName, string keyName, string KeyValue)
{
string query = $"SELECT * FROM {tableName} where {keyName} = '{KeyValue}'";
if (await ReadDataAsync(query) is not null)
return true;
return false;
}
public bool KeyExists(string tableName, string keyName, string KeyValue)
{
string query = $"SELECT * FROM {tableName} where {keyName} = '{KeyValue}'";
if (ReadData(query) is not null)
return true;
return false;
}
public async Task SetValueAsync(string tableName, string keyName, string KeyValue, string ResultColumnName,
string ResultColumnValue)
{
if (!await TableExistsAsync(tableName))
throw new System.Exception($"Table {tableName} does not exist");
await ExecuteAsync(
$"UPDATE {tableName} SET {ResultColumnName}='{ResultColumnValue}' WHERE {keyName}='{KeyValue}'");
}
public void SetValue(string tableName, string keyName, string KeyValue, string ResultColumnName,
string ResultColumnValue)
{
if (!TableExists(tableName))
throw new System.Exception($"Table {tableName} does not exist");
Execute($"UPDATE {tableName} SET {ResultColumnName}='{ResultColumnValue}' WHERE {keyName}='{KeyValue}'");
}
public async Task<string?> GetValueAsync(string tableName, string keyName, string KeyValue,
string ResultColumnName)
{
if (!await TableExistsAsync(tableName))
throw new System.Exception($"Table {tableName} does not exist");
return await ReadDataAsync($"SELECT {ResultColumnName} FROM {tableName} WHERE {keyName}='{KeyValue}'");
}
public string? GetValue(string tableName, string keyName, string KeyValue, string ResultColumnName)
{
if (!TableExists(tableName))
throw new System.Exception($"Table {tableName} does not exist");
return ReadData($"SELECT {ResultColumnName} FROM {tableName} WHERE {keyName}='{KeyValue}'");
}
public async void Stop()
{
await Connection.CloseAsync();
}
public async Task AddColumnsToTableAsync(string tableName, string[] columns)
{
var command = Connection.CreateCommand();
command.CommandText = $"SELECT * FROM {tableName}";
var reader = await command.ExecuteReaderAsync();
var tableColumns = new List<string>();
for (int i = 0; i < reader.FieldCount; i++)
tableColumns.Add(reader.GetName(i));
foreach (var column in columns)
{
if (!tableColumns.Contains(column))
{
command.CommandText = $"ALTER TABLE {tableName} ADD COLUMN {column} TEXT";
await command.ExecuteNonQueryAsync();
}
}
}
public void AddColumnsToTable(string tableName, string[] columns)
{
var command = Connection.CreateCommand();
command.CommandText = $"SELECT * FROM {tableName}";
var reader = command.ExecuteReader();
var tableColumns = new List<string>();
for (int i = 0; i < reader.FieldCount; i++)
tableColumns.Add(reader.GetName(i));
foreach (var column in columns)
{
if (!tableColumns.Contains(column))
{
command.CommandText = $"ALTER TABLE {tableName} ADD COLUMN {column} TEXT";
command.ExecuteNonQuery();
}
}
}
public async Task<bool> TableExistsAsync(string tableName)
{
var cmd = Connection.CreateCommand();
cmd.CommandText = $"SELECT name FROM sqlite_master WHERE type='table' AND name='{tableName}'";
var result = await cmd.ExecuteScalarAsync();
if (result == null)
return false;
return true;
}
public bool TableExists(string tableName)
{
var cmd = Connection.CreateCommand();
cmd.CommandText = $"SELECT name FROM sqlite_master WHERE type='table' AND name='{tableName}'";
var result = cmd.ExecuteScalar();
if (result == null)
return false;
return true;
}
public async Task CreateTableAsync(string tableName, params string[] columns)
{
var cmd = Connection.CreateCommand();
cmd.CommandText = $"CREATE TABLE IF NOT EXISTS {tableName} ({string.Join(", ", columns)})";
await cmd.ExecuteNonQueryAsync();
}
public void CreateTable(string tableName, params string[] columns)
{
var cmd = Connection.CreateCommand();
cmd.CommandText = $"CREATE TABLE IF NOT EXISTS {tableName} ({string.Join(", ", columns)})";
cmd.ExecuteNonQuery();
}
public async Task<int> ExecuteAsync(string query)
{
if (!Connection.State.HasFlag(System.Data.ConnectionState.Open))
await Connection.OpenAsync();
var command = new SQLiteCommand(query, Connection);
int answer = await command.ExecuteNonQueryAsync();
return answer;
}
public int Execute(string query)
{
if (!Connection.State.HasFlag(System.Data.ConnectionState.Open))
Connection.Open();
var command = new SQLiteCommand(query, Connection);
int r = command.ExecuteNonQuery();
return r;
}
public async Task<string?> ReadDataAsync(string query)
{
if (!Connection.State.HasFlag(System.Data.ConnectionState.Open))
await Connection.OpenAsync();
var command = new SQLiteCommand(query, Connection);
var reader = await command.ExecuteReaderAsync();
object[] values = new object[reader.FieldCount];
if (reader.Read())
{
reader.GetValues(values);
return string.Join<object>(" ", values);
}
return null;
}
public string? ReadData(string query)
{
if (!Connection.State.HasFlag(System.Data.ConnectionState.Open))
Connection.Open();
var command = new SQLiteCommand(query, Connection);
var reader = command.ExecuteReader();
object[] values = new object[reader.FieldCount];
if (reader.Read())
{
reader.GetValues(values);
return string.Join<object>(" ", values);
}
return null;
}
public async Task<object[]?> ReadDataArrayAsync(string query)
{
if (!Connection.State.HasFlag(System.Data.ConnectionState.Open))
await Connection.OpenAsync();
var command = new SQLiteCommand(query, Connection);
var reader = await command.ExecuteReaderAsync();
object[] values = new object[reader.FieldCount];
if (reader.Read())
{
reader.GetValues(values);
return values;
}
return null;
}
public async Task<List<string[]>?> ReadAllRowsAsync(string query)
{
if (!Connection.State.HasFlag(System.Data.ConnectionState.Open))
await Connection.OpenAsync();
var command = new SQLiteCommand(query, Connection);
var reader = await command.ExecuteReaderAsync();
if (!reader.HasRows)
return null;
List<string[]> rows = new();
while (await reader.ReadAsync())
{
string[] values = new string[reader.FieldCount];
reader.GetValues(values);
rows.Add(values);
}
if (rows.Count == 0) return null;
return rows;
}
public object[]? ReadDataArray(string query)
{
if (!Connection.State.HasFlag(System.Data.ConnectionState.Open))
Connection.Open();
var command = new SQLiteCommand(query, Connection);
var reader = command.ExecuteReader();
object[] values = new object[reader.FieldCount];
if (reader.Read())
{
reader.GetValues(values);
return values;
}
return null;
}
}
}

View File

@@ -1,6 +1,7 @@
using System.Collections.Generic;
using Discord.Commands;
using Discord.WebSocket;
using PluginManager.Others;
namespace PluginManager.Interfaces;
@@ -28,27 +29,24 @@ public interface DBCommand
/// </summary>
string Usage { get; }
/// <summary>
/// true if the command can be used in a DM channel, otherwise false
/// </summary>
bool canUseDM { get; }
/// <summary>
/// true if the command can be used in a server, otherwise false
/// </summary>
bool canUseServer { get; }
/// <summary>
/// true if the command requre admin, otherwise false
/// </summary>
bool requireAdmin { get; }
/// <summary>
/// The main body of the command. This is what is executed when user calls the command
/// The main body of the command. This is what is executed when user calls the command in Server
/// </summary>
/// <param name="context">The disocrd Context</param>
/// <param name="message">The message that the user types</param>
/// <param name="client">The discord client of the bot</param>
/// <param name="isDM">true if the message was sent from DM, otherwise false. It is always false if canUseDM is false</param>
void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM);
void ExecuteServer(CmdArgs args)
{
}
/// <summary>
/// The main body of the command. This is what is executed when user calls the command in DM
/// </summary>
/// <param name="context">The disocrd Context</param>
void ExecuteDM(CmdArgs args)
{
}
}

View File

@@ -7,12 +7,12 @@ public interface DBEvent
/// <summary>
/// The name of the event
/// </summary>
string name { get; }
string Name { get; }
/// <summary>
/// The description of the event
/// </summary>
string description { get; }
string Description { get; }
/// <summary>
/// The method that is invoked when the event is loaded into memory

View File

@@ -0,0 +1,25 @@
using System.Collections.Generic;
using Discord;
using Discord.WebSocket;
namespace PluginManager.Interfaces
{
public interface DBSlashCommand
{
string Name { get; }
string Description { get; }
bool canUseDM { get; }
List<SlashCommandOptionBuilder> Options { get; }
void ExecuteServer(SocketSlashCommand context)
{
}
void ExecuteDM(SocketSlashCommand context) { }
}
}

View File

@@ -1,51 +1,14 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Discord.Commands;
using Discord.WebSocket;
using PluginManager.Others;
namespace PluginManager.Items;
public class Command
{
/// <summary>
/// The author of the command
/// </summary>
public SocketUser? Author;
/// <summary>
/// The Command class contructor
/// </summary>
/// <param name="message">The message that was sent</param>
public Command(SocketMessage message)
{
Author = message.Author;
var data = message.Content.Split(' ');
Arguments = data.Length > 1 ? new List<string>(data.MergeStrings(1).Split(' ')) : new List<string>();
CommandName = data[0].Substring(1);
PrefixUsed = data[0][0];
}
/// <summary>
/// The list of arguments
/// </summary>
public List<string> Arguments { get; }
/// <summary>
/// The command that is executed
/// </summary>
public string CommandName { get; }
/// <summary>
/// The prefix that is used for the command
/// </summary>
public char PrefixUsed { get; }
}
public class ConsoleCommand
{
public string CommandName { get; init; }
public string Description { get; init; }
public string Usage { get; init; }
public Action<string[]> Action { get; init; }
public string? CommandName { get; init; }
public string? Description { get; init; }
public string? Usage { get; init; }
public Action<string[]>? Action { get; init; }
}

View File

@@ -1,51 +1,54 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Discord.WebSocket;
using PluginManager.Interfaces;
using PluginManager.Loaders;
using PluginManager.Online;
using PluginManager.Online.Helpers;
using PluginManager.Online.Updates;
using PluginManager.Others;
using OperatingSystem = PluginManager.Others.OperatingSystem;
namespace PluginManager.Items;
public class ConsoleCommandsHandler
{
private static readonly PluginsManager manager = new("https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/Plugins.txt");
private static readonly PluginsManager manager =
new("https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/Plugins.txt");
private static readonly List<ConsoleCommand> commandList = new();
private static bool isDownloading;
private static bool pluginsLoaded;
private readonly DiscordSocketClient? client;
private static bool isDownloading = false;
private static bool pluginsLoaded = false;
public ConsoleCommandsHandler(DiscordSocketClient client)
{
if (!Logger.isConsole) throw new Exception("Can not use ConsoleCommandsHandler for Non console apps");
this.client = client;
InitializeBasicCommands();
//Console.WriteLine("Initialized console command handler !");
//Logger.WriteLine("Initialized console command handler !");
}
private void InitializeBasicCommands()
{
commandList.Clear();
AddCommand("help", "Show help", "help <command>", args =>
{
if (args.Length <= 1)
{
Console.WriteLine("Available commands:");
List<string[]> items = new List<string[]>();
Logger.WriteLine("Available commands:");
var items = new List<string[]>();
items.Add(new[] { "-", "-", "-" });
items.Add(new[] { "Command", "Description", "Usage" });
items.Add(new[] { " ", " ", "Argument type: <optional> [required]" });
@@ -53,24 +56,24 @@ public class ConsoleCommandsHandler
foreach (var command in commandList)
{
var pa = from p in command.Action.Method.GetParameters() where p.Name != null select p.ParameterType.FullName;
if (!command.CommandName.StartsWith("_"))
items.Add(new[] { command.CommandName, command.Description, command.Usage });
}
items.Add(new[] { "-", "-", "-" });
Console_Utilities.FormatAndAlignTable(items, TableFormat.DEFAULT);
Utilities.FormatAndAlignTable(items, TableFormat.DEFAULT);
}
else
{
foreach (var command in commandList)
if (command.CommandName == args[1])
{
Console.WriteLine("Command description: " + command.Description);
Console.WriteLine("Command execution format:" + command.Usage);
Logger.WriteLine("Command description: " + command.Description);
Logger.WriteLine("Command execution format:" + command.Usage);
return;
}
Console.WriteLine("Command not found");
Logger.WriteLine("Command not found");
}
}
);
@@ -81,29 +84,68 @@ public class ConsoleCommandsHandler
if (pluginsLoaded)
return;
var loader = new PluginLoader(client!);
var cc = Console.ForegroundColor;
loader.onCMDLoad += (name, typeName, success, exception) =>
{
Console.ForegroundColor = ConsoleColor.Green;
if (name == null || name.Length < 2)
name = typeName;
if (success)
Console.WriteLine("[CMD] Successfully loaded command : " + name);
{
Console.ForegroundColor = ConsoleColor.Green;
Logger.WriteLine("[CMD] Successfully loaded command : " + name);
}
else
Console.WriteLine("[CMD] Failed to load command : " + name + " because " + exception!.Message);
{
Console.ForegroundColor = ConsoleColor.Red;
if (exception is null)
Logger.WriteLine("An error occured while loading: " + name);
else
Logger.WriteLine("[CMD] Failed to load command : " + name + " because " + exception!.Message);
}
Console.ForegroundColor = cc;
};
loader.onEVELoad += (name, typeName, success, exception) =>
{
if (name == null || name.Length < 2)
name = typeName;
Console.ForegroundColor = ConsoleColor.Green;
if (success)
Console.WriteLine("[EVENT] Successfully loaded event : " + name);
{
Console.ForegroundColor = ConsoleColor.Green;
Logger.WriteLine("[EVENT] Successfully loaded event : " + name);
}
else
Console.WriteLine("[EVENT] Failed to load event : " + name + " because " + exception!.Message);
{
Console.ForegroundColor = ConsoleColor.Red;
Logger.WriteLine("[EVENT] Failed to load event : " + name + " because " + exception!.Message);
}
Console.ForegroundColor = cc;
};
loader.onSLSHLoad += (name, typeName, success, exception) =>
{
if (name == null || name.Length < 2)
name = typeName;
if (success)
{
Console.ForegroundColor = ConsoleColor.Green;
Logger.WriteLine("[SLASH] Successfully loaded command : " + name);
}
else
{
Console.ForegroundColor = ConsoleColor.Red;
Logger.WriteLine("[SLASH] Failed to load command : " + name + " because " + exception!.Message);
}
Console.ForegroundColor = cc;
};
loader.LoadPlugins();
Console.ForegroundColor = cc;
pluginsLoaded = true;
}
);
@@ -116,11 +158,11 @@ public class ConsoleCommandsHandler
if (args.Length == 1)
{
isDownloading = false;
Console.WriteLine("Please specify plugin name");
Logger.WriteLine("Please specify plugin name");
return;
}
var name = args.MergeStrings(1);
var name = string.Join(' ', args, 1, args.Length - 1);
// info[0] = plugin type
// info[1] = plugin link
// info[2] = if others are required, or string.Empty if none
@@ -130,35 +172,42 @@ public class ConsoleCommandsHandler
if (name == "")
{
isDownloading = false;
Console_Utilities.WriteColorText("Name is invalid");
Utilities.WriteColorText("Name is invalid");
return;
}
isDownloading = false;
Console_Utilities.WriteColorText($"Failed to find plugin &b{name} &c!" + " Use &glistplugs &ccommand to display all available plugins !");
Utilities.WriteColorText($"Failed to find plugin &b{name} &c!" +
" Use &glistplugs &ccommand to display all available plugins !");
return;
}
string path;
if (info[0] == "Command" || info[0] == "Event")
path = "./Data/Plugins/" + info[0] + "s/" + name + "." + (info[0] == "Command" ? PluginLoader.pluginCMDExtension : PluginLoader.pluginEVEExtension);
if (info[0] == "Plugin")
path = "./Data/Plugins/" + name + ".dll";
else
path = $"./{info[1].Split('/')[info[1].Split('/').Length - 1]}";
//Console.WriteLine("Downloading: " + path + " [" + info[1] + "]");
if (OperatingSystem.WINDOWS == Functions.GetOperatingSystem())
{
await ServerCom.DownloadFileAsync(info[1], path);
if (info[0] == "Command" || info[0] == "Event")
if (info[0] == "Event")
Config.PluginConfig.InstalledPlugins.Add(new(name, PluginType.Event));
else if (info[0] == "Command")
Config.PluginConfig.InstalledPlugins.Add(new(name, PluginType.Command));
}
else if (OperatingSystem.LINUX == Functions.GetOperatingSystem())
{
var bar = new Utilities.ProgressBar(ProgressBarType.NO_END);
bar.Start();
await ServerCom.DownloadFileNoProgressAsync(info[1], path);
bar.Stop("Plugin Downloaded !");
}
Console.WriteLine("\n");
Logger.WriteLine("\n");
// check requirements if any
if (info.Length == 3 && info[2] != string.Empty && info[2] != null)
{
Console.WriteLine($"Downloading requirements for plugin : {name}");
Logger.WriteLine($"Downloading requirements for plugin : {name}");
var lines = await ServerCom.ReadTextFromURL(info[2]);
@@ -167,48 +216,49 @@ public class ConsoleCommandsHandler
if (!(line.Length > 0 && line.Contains(",")))
continue;
var split = line.Split(',');
Console.WriteLine($"\nDownloading item: {split[1]}");
Logger.WriteLine($"\nDownloading item: {split[1]}");
if (File.Exists("./" + split[1])) File.Delete("./" + split[1]);
if (OperatingSystem.WINDOWS == Functions.GetOperatingSystem())
{
await ServerCom.DownloadFileAsync(split[0], "./" + split[1]);
Console.WriteLine();
if (split[0].EndsWith(".zip") || split[0].EndsWith(".pak") || split[0].EndsWith(".pkg"))
{
Console.WriteLine($"Extracting {split[1]}");
var proc = 0f;
var isExtracting = true;
var bar = new Console_Utilities.ProgressBar { Max = 100f, Color = ConsoleColor.Green };
IProgress<float> extractProgress = new Progress<float>(value => { proc = value; });
new Thread(new Task(() =>
{
while (isExtracting)
{
bar.Update(proc);
if (proc >= 99.9f)
isExtracting = false;
Thread.Sleep(500);
}
else if (OperatingSystem.LINUX == Functions.GetOperatingSystem())
{
var bar = new Utilities.ProgressBar(ProgressBarType.NO_END);
bar.Start();
await ServerCom.DownloadFileNoProgressAsync(split[0], "./" + split[1]);
bar.Stop("Item downloaded !");
}
).Start
).Start();
await Functions.ExtractArchive("./" + split[1], "./", extractProgress, UnzipProgressType.PercentageFromTotalSize);
bar.Update(100f);
isExtracting = false;
await Task.Delay(1000);
bar.Update(100);
Console.WriteLine("\n");
Logger.WriteLine();
if (split[0].EndsWith(".pak"))
{
File.Move("./" + split[1], "./Data/PAKS/" + split[1], true);
}
else if (split[0].EndsWith(".zip") || split[0].EndsWith(".pkg"))
{
Logger.WriteLine($"Extracting {split[1]} ...");
var bar = new Utilities.ProgressBar(
ProgressBarType.NO_END);
bar.Start();
await ArchiveManager.ExtractArchive("./" + split[1], "./", null,
UnzipProgressType.PercentageFromTotalSize);
bar.Stop("Extracted");
Logger.WriteLine("\n");
File.Delete("./" + split[1]);
}
}
Console.WriteLine();
Logger.WriteLine();
}
VersionString? ver = await VersionString.GetVersionOfPackageFromWeb(name);
var ver = await ServerCom.GetVersionOfPackageFromWeb(name);
if (ver is null) throw new Exception("Incorrect version");
Config.SetPluginVersion(name, $"{ver.PackageID}.{ver.PackageMainVersion}.{ver.PackageCheckVersion}");
// Console.WriteLine();
await Config.Plugins.SetVersionAsync(name, ver);
isDownloading = false;
await ExecuteCommad("localload " + name);
}
);
@@ -217,11 +267,11 @@ public class ConsoleCommandsHandler
{
if (args.Length != 2)
return;
if (!Config.ContainsKey(args[1]))
if (!Config.Variables.Exists(args[1]))
return;
var data = Config.GetValue<string>(args[1]);
Console.WriteLine($"{args[1]} => {data}");
var data = Config.Variables.GetValue(args[1]);
Logger.WriteLine($"{args[1]} => {data}");
}
);
@@ -235,12 +285,12 @@ public class ConsoleCommandsHandler
try
{
Config.GetAndAddValueToVariable(key, value, isReadOnly);
Console.WriteLine($"Updated config file with the following command: {args[1]} => {value}");
Config.Variables.Add(key, value, isReadOnly);
Logger.WriteLine($"Updated config file with the following command: {args[1]} => {value}");
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
Logger.WriteLine(ex.ToString());
}
}
);
@@ -249,60 +299,158 @@ public class ConsoleCommandsHandler
{
if (args.Length < 2)
return;
Config.RemoveKey(args[1]);
Config.Variables.RemoveKey(args[1]);
}
);
AddCommand("sd", "Shuts down the discord bot", () =>
AddCommand("sd", "Shuts down the discord bot", async () =>
{
if (client is null)
return;
client.StopAsync();
client.DisposeAsync();
Config.SaveConfig();
Console.WriteLine("Bot is closing in 2 seconds ! Please wait to save data !");
Thread.Sleep(2000);
Settings.sqlDatabase.Stop();
await client.StopAsync();
await client.DisposeAsync();
await Task.Delay(1000);
Environment.Exit(0);
}
);
AddCommand("extern", "Load an external command", "extern [pluginName]", async (args) =>
AddCommand("import", "Load an external command", "import [pluginName]", async args =>
{
if (args.Length <= 1) return;
string pName = Functions.MergeStrings(args, 1);
HttpClient client = new HttpClient();
string url = (await manager.GetPluginLinkByName(pName))[1];
Stream s = await client.GetStreamAsync(url);
MemoryStream str = new MemoryStream();
try
{
var pName = string.Join(' ', args, 1, args.Length - 1);
using (var client = new HttpClient())
{
var url = (await manager.GetPluginLinkByName(pName))[1];
if (url is null) throw new Exception($"Invalid plugin name {pName}.");
var s = await client.GetStreamAsync(url);
var str = new MemoryStream();
await s.CopyToAsync(str);
var asmb = Assembly.Load(str.ToArray());
var types = asmb.GetTypes();
foreach (var type in types)
{
if (type.IsClass && typeof(DBEvent).IsAssignableFrom(type))
{
DBEvent instance = (DBEvent)Activator.CreateInstance(type);
instance.Start(this.client);
Console.WriteLine($"Loaded external {type.FullName}!");
await PluginLoader.LoadPluginFromAssembly(asmb, this.client);
}
else if (type.IsClass && typeof(DBCommand).IsAssignableFrom(type))
{
Console.WriteLine("Only events can be loaded from external sources !");
return;
}
catch (Exception ex)
{
Logger.WriteLine(ex.Message);
}
});
AddCommand("localload", "Load a local command", "local [pluginName]", async args =>
{
if (args.Length <= 1) return;
try
{
var pName = string.Join(' ', args, 1, args.Length - 1);
var asmb = Assembly.LoadFile(Path.GetFullPath("./Data/Plugins/" + pName + ".dll"));
await PluginLoader.LoadPluginFromAssembly(asmb, this.client);
}
catch (Exception ex)
{
Logger.WriteLine(ex.Message);
Logger.WriteErrFile(ex);
}
});
AddCommand("remplug", "Remove a plugin", "remplug [plugName]", async args =>
{
if (args.Length <= 1) return;
isDownloading = true;
var plugName = string.Join(' ', args, 1, args.Length - 1);
if (pluginsLoaded)
{
if (Functions.GetOperatingSystem() == OperatingSystem.WINDOWS)
{
Process.Start("DiscordBot.exe", $"/remplug {plugName}");
await Task.Delay(100);
Environment.Exit(0);
}
else
{
Process.Start("./DiscordBot", $"/remplug {plugName}");
await Task.Delay(100);
Environment.Exit(0);
}
isDownloading = false;
return;
}
var location = $"./Data/Plugins/{plugName}.dll";
if (!File.Exists(location))
{
Logger.WriteLine("The plugin does not exist");
return;
}
File.Delete(location);
Logger.WriteLine("Removed the plugin DLL. Checking for other files ...");
var info = await manager.GetPluginLinkByName(plugName);
if (info[2] != string.Empty)
{
var lines = await ServerCom.ReadTextFromURL(info[2]);
foreach (var line in lines)
{
if (!(line.Length > 0 && line.Contains(",")))
continue;
var split = line.Split(',');
if (File.Exists("./" + split[1]))
File.Delete("./" + split[1]);
Logger.WriteLine("Removed: " + split[1]);
}
if (Directory.Exists($"./Data/Plugins/{plugName}"))
Directory.Delete($"./Data/Plugins/{plugName}", true);
if (Directory.Exists(plugName))
Directory.Delete(plugName, true);
}
isDownloading = false;
Logger.WriteLine(plugName + " has been successfully deleted !");
});
AddCommand("reload", "Reload the bot with all plugins", () =>
{
if (Functions.GetOperatingSystem() == OperatingSystem.WINDOWS)
{
Process.Start("DiscordBot.exe", "lp");
HandleCommand("sd");
}
else
{
//HandleCommand("sd");
Console.WriteLine("This command can not be used outside of Windows yet. Please restart the bot using the manual way");
}
});
//AddCommand("");
//Sort the commands by name
commandList.Sort((x, y) => x.CommandName.CompareTo(y.CommandName));
}
public static void AddCommand(string command, string description, string usage, Action<string[]> action)
{
commandList.Add(new ConsoleCommand { CommandName = command, Description = description, Action = action, Usage = usage });
commandList.Add(new ConsoleCommand
{ CommandName = command, Description = description, Action = action, Usage = usage });
Console.ForegroundColor = ConsoleColor.White;
Console_Utilities.WriteColorText($"Command &r{command} &cadded to the list of commands");
Utilities.WriteColorText($"Command &r{command} &cadded to the list of commands");
}
public static void AddCommand(string command, string description, Action action)
@@ -325,42 +473,61 @@ public class ConsoleCommandsHandler
return commandList.FirstOrDefault(t => t.CommandName == command);
}
internal static async Task ExecuteCommad(string command)
/* public static async Task ExecuteSpecialCommand(string command)
{
if (!command.StartsWith("_")) return;
string[] args = command.Split(' ');
foreach (var item in commandList)
if (item.CommandName == args[0])
{
Logger.WriteLine();
item.Action(args);
}
}*/
public static async Task ExecuteCommad(string command)
{
if (!Logger.isConsole)
throw new Exception("Can not use console based commands on non console based application !");
var args = command.Split(' ');
foreach (var item in commandList.ToList())
if (item.CommandName == args[0])
{
item.Action.Invoke(args);
Console.WriteLine();
while (isDownloading) await Task.Delay(1000);
}
}
public bool HandleCommand(string command, bool removeCommandExecution = true)
{
if (!Logger.isConsole)
throw new Exception("Can not use console based commands on non console based application !");
Console.ForegroundColor = ConsoleColor.White;
var args = command.Split(' ');
foreach (var item in commandList.ToList())
if (item.CommandName == args[0])
{
if (args[0].StartsWith("_"))
throw new Exception("This command is reserved for internal worker and can not be executed manually !");
if (Logger.isConsole)
if (removeCommandExecution)
{
Console.SetCursorPosition(0, Console.CursorTop - 1);
for (int i = 0; i < command.Length + 30; i++)
Console.Write(" ");
for (var i = 0; i < command.Length + 30; i++)
Logger.Write(" ");
Console.SetCursorPosition(0, Console.CursorTop);
}
Console.WriteLine();
Logger.WriteLine();
item.Action(args);
return true;
}
return false;
//Console.WriteLine($"Executing: {args[0]} with the following parameters: {args.MergeStrings(1)}");
//Logger.WriteLine($"Executing: {args[0]} with the following parameters: {args.MergeStrings(1)}");
}
}

View File

@@ -3,10 +3,6 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using PluginManager.Online.Updates;
using PluginManager.Others;
namespace PluginManager.Loaders;
@@ -31,11 +27,6 @@ internal class Loader<T>
private string path { get; }
private string extension { get; }
internal delegate void FileLoadedEventHandler(LoaderArgs args);
internal delegate void PluginLoadedEventHandler(LoaderArgs args);
internal event FileLoadedEventHandler? FileLoaded;
internal event PluginLoadedEventHandler? PluginLoaded;
@@ -52,7 +43,6 @@ internal class Loader<T>
var files = Directory.GetFiles(path, $"*.{extension}", SearchOption.AllDirectories);
foreach (var file in files)
{
Assembly.LoadFrom(file);
if (FileLoaded != null)
{
@@ -98,15 +88,27 @@ internal class Loader<T>
}
catch (Exception ex)
{
if (PluginLoaded != null) PluginLoaded.Invoke(new LoaderArgs { Exception = ex, IsLoaded = false, PluginName = type.FullName, TypeName = nameof(T) });
if (PluginLoaded != null)
PluginLoaded.Invoke(new LoaderArgs
{
Exception = ex,
IsLoaded = false,
PluginName = type.FullName,
TypeName = nameof(T)
});
}
}
catch (Exception ex)
{
Functions.WriteErrFile(ex.ToString());
Logger.WriteErrFile(ex.ToString());
}
return list;
}
internal delegate void FileLoadedEventHandler(LoaderArgs args);
internal delegate void PluginLoadedEventHandler(LoaderArgs args);
}

View File

@@ -0,0 +1,136 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using PluginManager.Interfaces;
namespace PluginManager.Loaders
{
internal class LoaderV2
{
internal LoaderV2(string path, string extension)
{
this.path = path;
this.extension = extension;
}
private string path { get; }
private string extension { get; }
internal event FileLoadedEventHandler? FileLoaded;
internal event PluginLoadedEventHandler? PluginLoaded;
internal delegate void FileLoadedEventHandler(LoaderArgs args);
internal delegate void PluginLoadedEventHandler(LoaderArgs args);
internal (List<DBEvent>?, List<DBCommand>?, List<DBSlashCommand>?) Load()
{
List<DBEvent> events = new();
List<DBSlashCommand> slashCommands = new();
List<DBCommand> commands = new();
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
return (null, null, null);
}
var files = Directory.GetFiles(path, $"*.{extension}", SearchOption.AllDirectories);
foreach (var file in files)
{
try
{
Assembly.LoadFrom(file);
}
catch (Exception ex)
{
Logger.WriteLine(ex.Message);
Logger.WriteLine("PluginName: " + new FileInfo(file).Name.Split('.')[0] + " not loaded");
continue;
}
if (FileLoaded != null)
{
var args = new LoaderArgs
{
Exception = null,
TypeName = null,
IsLoaded = false,
PluginName = new FileInfo(file).Name.Split('.')[0],
Plugin = null
};
FileLoaded.Invoke(args);
}
}
return (LoadItems<DBEvent>(), LoadItems<DBCommand>(), LoadItems<DBSlashCommand>());
}
internal List<T> LoadItems<T>()
{
List<T> list = new();
try
{
var interfaceType = typeof(T);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(a => a.GetTypes())
.Where(p => interfaceType.IsAssignableFrom(p) && p.IsClass)
.ToArray();
list.Clear();
foreach (var type in types)
try
{
var plugin = (T)Activator.CreateInstance(type)!;
list.Add(plugin);
if (PluginLoaded != null)
PluginLoaded.Invoke(new LoaderArgs
{
Exception = null,
IsLoaded = true,
PluginName = type.FullName,
TypeName = typeof(T) == typeof(DBCommand) ? "DBCommand" : typeof(T) == typeof(DBEvent) ? "DBEvent" : "DBSlashCommand",
Plugin = plugin
}
);
}
catch (Exception ex)
{
if (PluginLoaded != null)
PluginLoaded.Invoke(new LoaderArgs
{
Exception = ex,
IsLoaded = false,
PluginName = type.FullName,
TypeName = nameof(T)
});
}
return list;
}
catch (Exception ex)
{
Logger.WriteErrFile(ex.ToString());
return null;
}
return null;
}
}
}

View File

@@ -1,16 +1,15 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Reflection;
using System.Threading.Tasks;
using Discord;
using Discord.WebSocket;
using PluginManager.Interfaces;
using PluginManager.Online.Helpers;
using PluginManager.Online;
using PluginManager.Online.Updates;
using PluginManager.Others;
namespace PluginManager.Loaders;
@@ -20,11 +19,11 @@ public class PluginLoader
public delegate void EVELoaded(string name, string typeName, bool success, Exception? e = null);
private const string pluginCMDFolder = @"./Data/Plugins/Commands/";
private const string pluginEVEFolder = @"./Data/Plugins/Events/";
public delegate void SLSHLoaded(string name, string tyypename, bool success, Exception? e = null);
internal const string pluginCMDExtension = "dll";
internal const string pluginEVEExtension = "dll";
private const string pluginFolder = @"./Data/Plugins/";
internal const string pluginExtension = "dll";
private readonly DiscordSocketClient _client;
/// <summary>
@@ -37,6 +36,11 @@ public class PluginLoader
/// </summary>
public EVELoaded? onEVELoad;
/// <summary>
/// Event that is fired when a <see cref="DBEvent" /> is successfully loaded into events list
/// </summary>
public SLSHLoaded? onSLSHLoad;
/// <summary>
/// The Plugin Loader constructor
/// </summary>
@@ -57,104 +61,123 @@ public class PluginLoader
/// </summary>
public static List<DBEvent>? Events { get; set; }
/// <summary>
/// A list of <see cref="DBSlashCommand"/> commands
/// </summary>
public static List<DBSlashCommand>? SlashCommands { get; set; }
/// <summary>
/// The main mathod that is called to load all events
/// </summary>
public async void LoadPlugins()
{
//Check for updates in commands
foreach (var file in Directory.GetFiles("./Data/Plugins/Commands", $"*.{pluginCMDExtension}", SearchOption.AllDirectories))
{
foreach (var file in Directory.GetFiles("./Data/Plugins/", $"*.{pluginExtension}",
SearchOption.AllDirectories))
await Task.Run(async () =>
{
string name = new FileInfo(file).Name.Split('.')[0];
if (!Config.PluginVersionsContainsKey(name))
Config.SetPluginVersion(name, (await VersionString.GetVersionOfPackageFromWeb(name))?.PackageID + ".0.0");
var name = new FileInfo(file).Name.Split('.')[0];
var version = await ServerCom.GetVersionOfPackageFromWeb(name);
if (version is null)
return;
if (Config.Plugins.GetVersion(name) is not null)
Config.Plugins.SetVersion(name, version);
if (await PluginUpdater.CheckForUpdates(name))
await PluginUpdater.Download(name);
});
}
//Check for updates in events
foreach (var file in Directory.GetFiles("./Data/Plugins/Events", $"*.{pluginEVEExtension}", SearchOption.AllDirectories))
{
await Task.Run(async () =>
{
string name = new FileInfo(file).Name.Split('.')[0];
if (!Config.PluginVersionsContainsKey(name))
Config.SetPluginVersion(name, (await VersionString.GetVersionOfPackageFromWeb(name))?.PackageID + ".0.0");
if (await PluginUpdater.CheckForUpdates(name))
await PluginUpdater.Download(name);
});
}
//Save the new config file (after the updates)
Config.SaveConfig();
//Load all plugins
Commands = new List<DBCommand>();
Events = new List<DBEvent>();
SlashCommands = new List<DBSlashCommand>();
Functions.WriteLogFile("Starting plugin loader ... Client: " + _client.CurrentUser.Username);
Console.WriteLine("Loading plugins");
var commandsLoader = new Loader<DBCommand>(pluginCMDFolder, pluginCMDExtension);
var eventsLoader = new Loader<DBEvent>(pluginEVEFolder, pluginEVEExtension);
commandsLoader.FileLoaded += OnCommandFileLoaded;
commandsLoader.PluginLoaded += OnCommandLoaded;
eventsLoader.FileLoaded += EventFileLoaded;
eventsLoader.PluginLoaded += OnEventLoaded;
Commands = commandsLoader.Load();
Events = eventsLoader.Load();
Logger.WriteLogFile("Starting plugin loader ... Client: " + _client.CurrentUser.Username);
Logger.WriteLine("Loading plugins");
var loader = new LoaderV2("./Data/Plugins", "dll");
loader.FileLoaded += (args) => Logger.WriteLogFile($"{args.PluginName} file Loaded");
loader.PluginLoaded += Loader_PluginLoaded;
var res = loader.Load();
Events = res.Item1;
Commands = res.Item2;
SlashCommands = res.Item3;
}
private void EventFileLoaded(LoaderArgs e)
private async void Loader_PluginLoaded(LoaderArgs args)
{
if (!e.IsLoaded)
{
Functions.WriteLogFile($"[EVENT] Event from file [{e.PluginName}] has been successfully created !");
}
}
private void OnCommandFileLoaded(LoaderArgs e)
{
if (!e.IsLoaded)
{
Functions.WriteLogFile($"[CMD] Command from file [{e.PluginName}] has been successfully loaded !");
}
}
private void OnEventLoaded(LoaderArgs e)
switch (args.TypeName)
{
case "DBCommand":
onCMDLoad?.Invoke(((DBCommand)args.Plugin!).Command, args.TypeName!, args.IsLoaded, args.Exception);
break;
case "DBEvent":
try
{
if (e.IsLoaded)
((DBEvent)e.Plugin!).Start(_client);
if (args.IsLoaded)
((DBEvent)args.Plugin!).Start(_client);
onEVELoad?.Invoke(((DBEvent)e.Plugin!).name, e.TypeName!, e.IsLoaded, e.Exception);
onEVELoad?.Invoke(((DBEvent)args.Plugin!).Name, args.TypeName!, args.IsLoaded, args.Exception);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
Console.WriteLine("Plugin: " + e.PluginName);
Console.WriteLine("Type: " + e.TypeName);
Console.WriteLine("IsLoaded: " + e.IsLoaded);
Logger.WriteLine(ex.ToString());
Logger.WriteLine("Plugin: " + args.PluginName);
Logger.WriteLine("Type: " + args.TypeName);
Logger.WriteLine("IsLoaded: " + args.IsLoaded);
}
}
private void OnCommandLoaded(LoaderArgs e)
break;
case "DBSlashCommand":
if (args.IsLoaded)
{
onCMDLoad?.Invoke(((DBCommand)e.Plugin!).Command, e.TypeName!, e.IsLoaded, e.Exception);
var slash = (DBSlashCommand)args.Plugin;
SlashCommandBuilder builder = new SlashCommandBuilder();
builder.WithName(slash.Name);
builder.WithDescription(slash.Description);
builder.WithDMPermission(slash.canUseDM);
builder.Options = slash.Options;
onSLSHLoad?.Invoke(((DBSlashCommand)args.Plugin!).Name, args.TypeName, args.IsLoaded, args.Exception);
await _client.CreateGlobalApplicationCommandAsync(builder.Build());
}
break;
}
}
public static async Task LoadPluginFromAssembly(Assembly asmb, DiscordSocketClient client)
{
var types = asmb.GetTypes();
foreach (var type in types)
if (type.IsClass && typeof(DBEvent).IsAssignableFrom(type))
{
var instance = (DBEvent)Activator.CreateInstance(type);
instance.Start(client);
PluginLoader.Events.Add(instance);
Logger.WriteLine($"[EVENT] Loaded external {type.FullName}!");
}
else if (type.IsClass && typeof(DBCommand).IsAssignableFrom(type))
{
var instance = (DBCommand)Activator.CreateInstance(type);
PluginLoader.Commands.Add(instance);
Logger.WriteLine($"[CMD] Instance: {type.FullName} loaded !");
}
else if (type.IsClass && typeof(DBSlashCommand).IsAssignableFrom(type))
{
var instance = (DBSlashCommand)Activator.CreateInstance(type);
SlashCommandBuilder builder = new SlashCommandBuilder();
builder.WithName(instance.Name);
builder.WithDescription(instance.Description);
builder.WithDMPermission(instance.canUseDM);
builder.Options = instance.Options;
await client.CreateGlobalApplicationCommandAsync(builder.Build());
PluginLoader.SlashCommands.Add(instance);
Logger.WriteLine($"[SLASH] Instance: {type.FullName} loaded !");
}
}
}

131
PluginManager/Logger.cs Normal file
View File

@@ -0,0 +1,131 @@
using System;
using System.IO;
using Discord;
namespace PluginManager
{
public static class Logger
{
public static bool isConsole { get; private set; }
private static bool isInitialized;
private static string? logFolder;
private static string? errFolder;
public static void Initialize(bool console)
{
if (isInitialized) throw new Exception("Logger is already initialized");
if (!Config.Variables.Exists("LogFolder"))
Config.Variables.Add("LogFolder", "./Data/Output/Logs/");
if (!Config.Variables.Exists("ErrorFolder"))
Config.Variables.Add("ErrorFolder", "./Data/Output/Errors/");
isInitialized = true;
logFolder = Config.Variables.GetValue("LogFolder");
errFolder = Config.Variables.GetValue("ErrorFolder");
isConsole = console;
}
public delegate void LogEventHandler(string Message);
public static event LogEventHandler LogEvent;
public static void Log(string Message)
{
if (!isInitialized) throw new Exception("Logger is not initialized");
LogEvent?.Invoke(Message);
}
public static void Log(string Message, params object[] Args)
{
if (!isInitialized) throw new Exception("Logger is not initialized");
LogEvent?.Invoke(string.Format(Message, Args));
}
public static void Log(IMessage message, bool newLine)
{
if (!isInitialized) throw new Exception("Logger is not initialized");
LogEvent?.Invoke(message.Content);
if (newLine)
LogEvent?.Invoke("\n");
}
public static void WriteLine(string? message)
{
if (!isInitialized) throw new Exception("Logger is not initialized");
if (message is not null)
LogEvent?.Invoke(message + '\n');
}
public static void LogError(System.Exception ex)
{
if (!isInitialized) throw new Exception("Logger is not initialized");
string message = "[ERROR]" + ex.Message;
LogEvent?.Invoke(message + '\n');
}
public static void LogError(string? message)
{
if (!isInitialized) throw new Exception("Logger is not initialized");
if (message is not null)
LogEvent?.Invoke("[ERROR]" + message + '\n');
}
public static void WriteLine()
{
if (!isInitialized) throw new Exception("Logger is not initialized");
LogEvent?.Invoke("\n");
}
public static void Write(string message)
{
if (!isInitialized) throw new Exception("Logger is not initialized");
LogEvent?.Invoke(message);
}
public static void Write<T>(T c)
{
if (!isInitialized) throw new Exception("Logger is not initialized");
LogEvent?.Invoke($"{c}");
}
/// <summary>
/// Write logs to file
/// </summary>
/// <param name="LogMessage">The message to be wrote</param>
public static void WriteLogFile(string LogMessage)
{
if (!isInitialized) throw new Exception("Logger is not initialized");
var logsPath = logFolder + $"{DateTime.Today.ToShortDateString().Replace("/", "-").Replace("\\", "-")} Log.txt";
Directory.CreateDirectory(logFolder);
File.AppendAllTextAsync(logsPath, LogMessage + " \n").Wait();
}
/// <summary>
/// Write error to file
/// </summary>
/// <param name="ErrMessage">The message to be wrote</param>
public static void WriteErrFile(string ErrMessage)
{
if (!isInitialized) throw new Exception("Logger is not initialized");
var errPath = errFolder +
$"{DateTime.Today.ToShortDateString().Replace("/", "-").Replace("\\", "-")} Error.txt";
Directory.CreateDirectory(errFolder);
File.AppendAllText(errPath, ErrMessage + " \n");
}
public static void WriteErrFile(this Exception ex)
{
if (!isInitialized) throw new Exception("Logger is not initialized");
WriteErrFile(ex.ToString());
}
}
}

View File

@@ -1,24 +1,28 @@
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.IO;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using PluginManager.Others;
namespace PluginManager.Online.Helpers
namespace PluginManager.Online.Helpers;
internal static class OnlineFunctions
{
internal static class OnlineFunctions
{
/// <summary>
/// Downloads a <see cref="Stream"/> and saves it to another <see cref="Stream"/>.
/// Downloads a <see cref="Stream" /> and saves it to another <see cref="Stream" />.
/// </summary>
/// <param name="client">The <see cref="HttpClient"/> that is used to download the file</param>
/// <param name="client">The <see cref="HttpClient" /> that is used to download the file</param>
/// <param name="url">The url to the file</param>
/// <param name="destination">The <see cref="Stream"/> to save the downloaded data</param>
/// <param name="progress">The <see cref="IProgress{T}"/> that is used to track the download progress</param>
/// <param name="destination">The <see cref="Stream" /> to save the downloaded data</param>
/// <param name="progress">The <see cref="IProgress{T}" /> that is used to track the download progress</param>
/// <param name="cancellation">The cancellation token</param>
/// <returns></returns>
internal static async Task DownloadFileAsync(this HttpClient client, string url, Stream destination, IProgress<float>? progress = null, IProgress<long>? downloadedBytes = null, int bufferSize = 81920, CancellationToken cancellation = default)
internal static async Task DownloadFileAsync(this HttpClient client, string url, Stream destination,
IProgress<float>? progress = null,
IProgress<long>? downloadedBytes = null, int bufferSize = 81920,
CancellationToken cancellation = default)
{
using (var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, cancellation))
{
@@ -37,14 +41,14 @@ namespace PluginManager.Online.Helpers
// Convert absolute progress (bytes downloaded) into relative progress (0% - 100%)
var relativeProgress = new Progress<long>(totalBytes =>
{
progress.Report((float)totalBytes / contentLength.Value * 100);
progress?.Report((float)totalBytes / contentLength.Value * 100);
downloadedBytes?.Report(totalBytes);
}
);
// Use extension method to report progress while downloading
await download.CopyToOtherStreamAsync(destination, bufferSize, relativeProgress, cancellation);
progress.Report(1);
progress.Report(100);
}
}
}
@@ -60,8 +64,4 @@ namespace PluginManager.Online.Helpers
using var client = new HttpClient();
return await client.GetStringAsync(url, cancellation);
}
}
}

View File

@@ -1,82 +1,84 @@
using PluginManager.Others;
using System;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Linq;
namespace PluginManager.Online.Helpers;
namespace PluginManager.Online.Helpers
public class VersionString
{
public class VersionString
{
public int PackageID;
public int PackageMainVersion;
public int PackageCheckVersion;
public int PackageMainVersion;
public int PackageVersionID;
public VersionString(string version)
{
string[] data = version.Split('.');
var data = version.Split('.');
try
{
PackageID = int.Parse(data[0]);
PackageVersionID = int.Parse(data[0]);
PackageMainVersion = int.Parse(data[1]);
PackageCheckVersion = int.Parse(data[2]);
}
catch (Exception ex)
{
Console.WriteLine(version);
throw new Exception("Failed to write Version", ex);
}
}
public static bool operator >(VersionString s1, VersionString s2)
{
if (s1.PackageID != s2.PackageID) throw new Exception("Can not compare two different paks");
if (s1.PackageMainVersion > s2.PackageMainVersion) return true;
if (s1.PackageMainVersion == s2.PackageMainVersion && s1.PackageCheckVersion > s2.PackageCheckVersion) return true;
return false;
}
public static bool operator <(VersionString s1, VersionString s2) => !(s1 > s2) && s1 != s2;
public static bool operator ==(VersionString s1, VersionString s2)
{
if (s1.PackageID == s2.PackageID && s1.PackageMainVersion == s2.PackageMainVersion && s1.PackageCheckVersion == s2.PackageCheckVersion) return true;
return false;
}
public static bool operator !=(VersionString s1, VersionString s2) => !(s1 == s2);
public static bool operator <=(VersionString s1, VersionString s2) => (s1 < s2 || s1 == s2);
public static bool operator >=(VersionString s1, VersionString s2) => (s1 > s2 || s1 == s2);
public override string ToString()
{
return "{PackageID: " + PackageID + ", PackageVersion: " + PackageMainVersion + ", PackageCheckVersion: " + PackageCheckVersion + "}";
return "{PackageID: " + PackageVersionID + ", PackageVersion: " + PackageMainVersion +
", PackageCheckVersion: " + PackageCheckVersion + "}";
}
public string ToShortString()
{
return $"{PackageID}.{PackageMainVersion}.{PackageCheckVersion}";
if (PackageVersionID == 0 && PackageCheckVersion == 0 && PackageMainVersion == 0)
return "Unknown";
return $"{PackageVersionID}.{PackageMainVersion}.{PackageCheckVersion}";
}
public static VersionString? GetVersionOfPackage(string pakName)
#region operators
public static bool operator >(VersionString s1, VersionString s2)
{
if (!Config.PluginVersionsContainsKey(pakName))
return null;
return new VersionString(Config.GetPluginVersion(pakName));
}
public static async Task<VersionString?> GetVersionOfPackageFromWeb(string pakName)
if (s1.PackageVersionID > s2.PackageVersionID) return true;
if (s1.PackageVersionID == s2.PackageVersionID)
{
string url = "https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/Versions";
List<string> data = await ServerCom.ReadTextFromURL(url);
string? version = (from item in data
where !item.StartsWith("#") && item.StartsWith(pakName)
select item.Split(',')[1]).FirstOrDefault();
if (version == default || version == null) return null;
return new VersionString(version);
if (s1.PackageMainVersion > s2.PackageMainVersion) return true;
if (s1.PackageMainVersion == s2.PackageMainVersion &&
s1.PackageCheckVersion > s2.PackageCheckVersion) return true;
}
return false;
}
public static bool operator <(VersionString s1, VersionString s2)
{
return !(s1 > s2) && s1 != s2;
}
public static bool operator ==(VersionString s1, VersionString s2)
{
if (s1.PackageVersionID == s2.PackageVersionID && s1.PackageMainVersion == s2.PackageMainVersion &&
s1.PackageCheckVersion == s2.PackageCheckVersion) return true;
return false;
}
public static bool operator !=(VersionString s1, VersionString s2)
{
return !(s1 == s2);
}
public static bool operator <=(VersionString s1, VersionString s2)
{
return s1 < s2 || s1 == s2;
}
public static bool operator >=(VersionString s1, VersionString s2)
{
return s1 > s2 || s1 == s2;
}
#endregion
}

View File

@@ -1,7 +1,10 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using PluginManager.Online.Helpers;
using PluginManager.Others;
using OperatingSystem = PluginManager.Others.OperatingSystem;
namespace PluginManager.Online;
@@ -37,10 +40,10 @@ public class PluginsManager
var op = Functions.GetOperatingSystem();
var len = lines.Length;
string[] titles = { "Name", "Description", "Plugin Type", "Libraries", "Installed" };
data.Add(new[] { "-", "-", "-", "-", "-" });
string[] titles = { "Name", "Description", "Type", "Version" };
data.Add(new[] { "-", "-", "-", "-" });
data.Add(titles);
data.Add(new[] { "-", "-", "-", "-", "-" });
data.Add(new[] { "-", "-", "-", "-" });
for (var i = 0; i < len; i++)
{
if (lines[i].Length <= 2)
@@ -54,15 +57,9 @@ public class PluginsManager
display[0] = content[0];
display[1] = content[1];
display[2] = content[2];
if (content.Length == 6 && (content[5] != null || content[5].Length > 2))
display[3] = ((await ServerCom.ReadTextFromURL(content[5])).Count + 1).ToString();
else
display[3] = "1";
if (Config.PluginConfig.Contains(content[0]) || Config.PluginConfig.Contains(content[0]))
display[4] = "✓";
else
display[4] = "X";
display[3] =
(await ServerCom.GetVersionOfPackageFromWeb(content[0]) ?? new VersionString("0.0.0"))
.ToShortString();
data.Add(display);
}
}
@@ -73,25 +70,22 @@ public class PluginsManager
display[0] = content[0];
display[1] = content[1];
display[2] = content[2];
if (content.Length == 6 && (content[5] != null || content[5].Length > 2))
display[3] = ((await ServerCom.ReadTextFromURL(content[5])).Count + 1).ToString();
if (Config.PluginConfig.Contains(content[0]) || Config.PluginConfig.Contains(content[0]))
display[4] = "✓";
else
display[4] = "X";
display[3] =
(await ServerCom.GetVersionOfPackageFromWeb(content[0]) ?? new VersionString("0.0.0"))
.ToShortString();
data.Add(display);
}
}
}
data.Add(new[] { "-", "-", "-", "-", "-" });
data.Add(new[] { "-", "-", "-", "-" });
Console_Utilities.FormatAndAlignTable(data);
Utilities.FormatAndAlignTable(data, TableFormat.CENTER_EACH_COLUMN_BASED);
}
catch (Exception exception)
{
Console.WriteLine("Failed to execute command: listplugs\nReason: " + exception.Message);
Functions.WriteErrFile(exception.ToString());
Logger.WriteLine("Failed to execute command: listplugs\nReason: " + exception.Message);
Logger.WriteErrFile(exception.ToString());
}
}
@@ -122,8 +116,8 @@ public class PluginsManager
}
catch (Exception exception)
{
Console.WriteLine("Failed to execute command: listplugs\nReason: " + exception.Message);
Functions.WriteErrFile(exception.ToString());
Logger.WriteLine("Failed to execute command: listplugs\nReason: " + exception.Message);
Logger.WriteErrFile(exception.ToString());
}
return new string[] { null!, null!, null! };

View File

@@ -1,16 +1,18 @@
using PluginManager.Online.Helpers;
using System;
using System.Collections.Generic;
using System;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
using PluginManager.Online.Helpers;
using PluginManager.Others;
namespace PluginManager.Online
namespace PluginManager.Online;
public static class ServerCom
{
public static class ServerCom
{
/// <summary>
/// Read all lines from a file async
/// </summary>
@@ -18,8 +20,8 @@ namespace PluginManager.Online
/// <returns></returns>
public static async Task<List<string>> ReadTextFromURL(string link)
{
string response = await OnlineFunctions.DownloadStringAsync(link);
string[] lines = response.Split('\n');
var response = await OnlineFunctions.DownloadStringAsync(link);
var lines = response.Split('\n');
return lines.ToList();
}
@@ -28,11 +30,12 @@ namespace PluginManager.Online
/// </summary>
/// <param name="URL">The url to the file</param>
/// <param name="location">The location where to store the downloaded data</param>
/// <param name="progress">The <see cref="IProgress{T}"/> to track the download</param>
/// <param name="progress">The <see cref="IProgress{T}" /> to track the download</param>
/// <returns></returns>
public static async Task DownloadFileAsync(string URL, string location, IProgress<float> progress, IProgress<long>? downloadedBytes = null)
public static async Task DownloadFileAsync(string URL, string location, IProgress<float> progress,
IProgress<long>? downloadedBytes = null)
{
using (var client = new System.Net.Http.HttpClient())
using (var client = new HttpClient())
{
client.Timeout = TimeSpan.FromMinutes(5);
@@ -51,15 +54,15 @@ namespace PluginManager.Online
/// <returns></returns>
public static async Task DownloadFileAsync(string URL, string location)
{
bool isDownloading = true;
var isDownloading = true;
float c_progress = 0;
Console_Utilities.ProgressBar pbar = new Console_Utilities.ProgressBar { Max = 100f, NoColor = true };
var pbar = new Utilities.ProgressBar(ProgressBarType.NORMAL) { Max = 100f, NoColor = true };
IProgress<float> progress = new Progress<float>(percent => { c_progress = percent; });
Task updateProgressBarTask = new Task(() =>
var updateProgressBarTask = new Task(() =>
{
while (isDownloading)
{
@@ -79,5 +82,33 @@ namespace PluginManager.Online
pbar.Update(100f);
isDownloading = false;
}
public static async Task DownloadFileNoProgressAsync(string URL, string location)
{
IProgress<float> progress = new Progress<float>();
await DownloadFileAsync(URL, location, progress);
}
public static VersionString? GetVersionOfPackage(string pakName)
{
if (Config.Plugins.GetVersion(pakName) is null)
return null;
return new VersionString(Config.Plugins.GetVersion(pakName));
}
public static async Task<VersionString?> GetVersionOfPackageFromWeb(string pakName)
{
var url = "https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/Versions";
var data = await ReadTextFromURL(url);
foreach (var item in data)
{
if (item.StartsWith("#"))
continue;
string[] split = item.Split(',');
if (split[0] == pakName)
return new VersionString(split[1]);
}
return null;
}
}

View File

@@ -1,21 +1,20 @@
using PluginManager.Items;
using PluginManager.Online.Helpers;
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using PluginManager.Items;
using PluginManager.Others;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace PluginManager.Online.Updates;
namespace PluginManager.Online.Updates
public class PluginUpdater
{
public class PluginUpdater
{
public static async Task<bool> CheckForUpdates(string pakName)
{
try
{
var webV = await VersionString.GetVersionOfPackageFromWeb(pakName);
var local = VersionString.GetVersionOfPackage(pakName);
var webV = await ServerCom.GetVersionOfPackageFromWeb(pakName);
var local = ServerCom.GetVersionOfPackage(pakName);
if (local is null) return true;
if (webV is null) return false;
@@ -23,29 +22,31 @@ namespace PluginManager.Online.Updates
if (webV == local) return false;
if (webV > local) return true;
}
catch (Exception ex) { Console.WriteLine(ex.Message); }
catch (Exception ex)
{
Logger.LogError(ex);
}
return false;
}
public static async Task<Update> DownloadUpdateInfo(string pakName)
public static async Task<List<string>> GetInfo(string pakName)
{
string url = "https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/Versions";
List<string> info = await ServerCom.ReadTextFromURL(url);
VersionString? version = await VersionString.GetVersionOfPackageFromWeb(pakName);
if (version is null) return Update.Empty;
Update update = new Update(pakName, string.Join('\n', info), version);
return update;
Utilities.WriteColorText("An update was found for &g" + pakName + "&c. Version: &r" +
(await ServerCom.GetVersionOfPackageFromWeb(pakName))?.ToShortString() +
"&c. Current Version: &y" +
ServerCom.GetVersionOfPackage(pakName)?.ToShortString());
List<string> fileInfo = await ServerCom.ReadTextFromURL("");
return fileInfo;
}
public static async Task Download(string pakName)
{
Console_Utilities.WriteColorText("An update was found for &g" + pakName + "&c. Version: &r" + (await VersionString.GetVersionOfPackageFromWeb(pakName))?.ToShortString() + "&c. Current Version: &y" + VersionString.GetVersionOfPackage(pakName)?.ToShortString());
var pakUpdateInfo = await GetInfo(pakName);
Logger.Log(string.Join("\n", pakUpdateInfo));
await ConsoleCommandsHandler.ExecuteCommad("dwplug " + pakName);
}
}
}

View File

@@ -1,36 +0,0 @@
using PluginManager.Online.Helpers;
namespace PluginManager.Online.Updates
{
public class Update
{
public static Update Empty = new Update(null, null, null);
public string pakName;
public string UpdateMessage;
public VersionString newVersion;
private bool isEmpty;
public Update(string pakName, string updateMessage, VersionString newVersion)
{
this.pakName = pakName;
UpdateMessage = updateMessage;
this.newVersion = newVersion;
if (pakName is null && updateMessage is null && newVersion is null)
isEmpty = true;
}
public override string ToString()
{
if (isEmpty)
throw new System.Exception("The update is EMPTY. Can not print information about an empty update !");
return $"Package Name: {this.pakName}\n" +
$"Update Message: {UpdateMessage}\n" +
$"Version: {newVersion.ToString()}";
}
}
}

View File

@@ -0,0 +1,139 @@
using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Threading.Tasks;
namespace PluginManager.Others
{
public static class ArchiveManager
{
public static bool isInitialized { get; private set; }
private static string archiveFolder;
public static void Initialize()
{
if (isInitialized) throw new Exception("ArchiveManager is already initialized");
if (!Config.Variables.Exists("ArchiveFolder"))
Config.Variables.Add("ArchiveFolder", "./Data/PAKS/");
isInitialized = true;
archiveFolder = Config.Variables.GetValue("ArchiveFolder");
}
/// <summary>
/// Read data from a file that is inside an archive (ZIP format)
/// </summary>
/// <param name="FileName">The file name that is inside the archive or its full path</param>
/// <param name="archFile">The archive location from the PAKs folder</param>
/// <returns>A string that represents the content of the file or null if the file does not exists or it has no content</returns>
public static async Task<string> ReadFromPakAsync(string FileName, string archFile)
{
if (!isInitialized) throw new Exception("ArchiveManager is not initialized");
archFile = archiveFolder + archFile;
if (!File.Exists(archFile))
throw new Exception("Failed to load file !");
try
{
string textValue = null;
using (var fs = new FileStream(archFile, FileMode.Open))
using (var zip = new ZipArchive(fs, ZipArchiveMode.Read))
{
foreach (var entry in zip.Entries)
if (entry.Name == FileName || entry.FullName == FileName)
using (var s = entry.Open())
using (var reader = new StreamReader(s))
{
textValue = await reader.ReadToEndAsync();
reader.Close();
s.Close();
fs.Close();
}
}
return textValue;
}
catch
{
await Task.Delay(100);
return await ReadFromPakAsync(FileName, archFile);
}
}
/// <summary>
/// Extract zip to location
/// </summary>
/// <param name="zip">The zip location</param>
/// <param name="folder">The target location</param>
/// <param name="progress">The progress that is updated as a file is processed</param>
/// <param name="type">The type of progress</param>
/// <returns></returns>
public static async Task ExtractArchive(string zip, string folder, IProgress<float> progress,
UnzipProgressType type)
{
if (!isInitialized) throw new Exception("ArchiveManager is not initialized");
Directory.CreateDirectory(folder);
using (var archive = ZipFile.OpenRead(zip))
{
if (type == UnzipProgressType.PercentageFromNumberOfFiles)
{
var totalZIPFiles = archive.Entries.Count();
var currentZIPFile = 0;
foreach (var entry in archive.Entries)
{
if (entry.FullName.EndsWith("/")) // it is a folder
Directory.CreateDirectory(Path.Combine(folder, entry.FullName));
else
try
{
entry.ExtractToFile(Path.Combine(folder, entry.FullName), true);
}
catch (Exception ex)
{
Logger.WriteLine($"Failed to extract {entry.Name}. Exception: {ex.Message}");
}
currentZIPFile++;
await Task.Delay(10);
if (progress != null)
progress.Report((float)currentZIPFile / totalZIPFiles * 100);
}
}
else if (type == UnzipProgressType.PercentageFromTotalSize)
{
ulong zipSize = 0;
foreach (var entry in archive.Entries)
zipSize += (ulong)entry.CompressedLength;
ulong currentSize = 0;
foreach (var entry in archive.Entries)
{
if (entry.FullName.EndsWith("/"))
{
Directory.CreateDirectory(Path.Combine(folder, entry.FullName));
continue;
}
try
{
entry.ExtractToFile(Path.Combine(folder, entry.FullName), true);
currentSize += (ulong)entry.CompressedLength;
}
catch (Exception ex)
{
Logger.WriteLine($"Failed to extract {entry.Name}. Exception: {ex.Message}");
}
await Task.Delay(10);
if (progress != null)
progress.Report((float)currentSize / zipSize * 100);
}
}
}
}
}
}

View File

@@ -1,60 +0,0 @@
using System.Threading.Tasks;
using Discord;
namespace PluginManager.Others;
/// <summary>
/// A class that handles the sending of messages to the user.
/// </summary>
public static class ChannelManagement
{
/// <summary>
/// Get the text channel by name from server
/// </summary>
/// <param name="server">The server</param>
/// <param name="name">The channel name</param>
/// <returns>
/// <see cref="IGuildChannel" />
/// </returns>
public static IGuildChannel GetTextChannel(this IGuild server, string name)
{
return server.GetTextChannel(name);
}
/// <summary>
/// Get the voice channel by name from server
/// </summary>
/// <param name="server">The server</param>
/// <param name="name">The channel name</param>
/// <returns>
/// <see cref="IGuildChannel" />
/// </returns>
public static IGuildChannel GetVoiceChannel(this IGuild server, string name)
{
return server.GetVoiceChannel(name);
}
/// <summary>
/// Get the DM channel between <see cref="Discord.WebSocket.DiscordSocketClient" /> and <see cref="IGuildUser" />
/// </summary>
/// <param name="user"></param>
/// <returns>
/// <see cref="IDMChannel" />
/// </returns>
public static async Task<IDMChannel> GetDMChannel(IGuildUser user)
{
return await user.CreateDMChannelAsync();
}
/// <summary>
/// Get the channel where the message was sent
/// </summary>
/// <param name="message">The message</param>
/// <returns>
/// <see cref="IChannel" />
/// </returns>
public static IChannel GetChannel(IMessage message)
{
return message.Channel;
}
}

View File

@@ -0,0 +1,19 @@
using Discord.Commands;
using Discord.WebSocket;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PluginManager.Others
{
public class CmdArgs
{
public SocketCommandContext context { get; init; }
public string cleanContent { get; init; }
public string commandUsed { get;init; }
public string[] arguments { get;init; }
}
}

View File

@@ -1,139 +1,83 @@
using Discord;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace PluginManager.Others
namespace PluginManager.Others;
public static class Utilities
{
public static class Console_Utilities
{
public static void Initialize()
{
if (!Config.ContainsKey("TableVariables"))
Config.AddValueToVariables("TableVariables", new Dictionary<string, string> { { "DefaultSpace", "3" } }, false);
if (!Config.ContainsKey("ColorDataBase"))
Config.AddValueToVariables("ColorDataBase", new Dictionary<char, ConsoleColor>()
private static Dictionary<char, ConsoleColor> Colors = new()
{
{ 'g', ConsoleColor.Green },
{ 'b', ConsoleColor.Blue },
{ 'r', ConsoleColor.Red },
{ 'm', ConsoleColor.Magenta },
{ 'y', ConsoleColor.Yellow },
}, false
);
{ 'y', ConsoleColor.Yellow }
};
if (!Config.ContainsKey("ColorPrefix"))
Config.AddValueToVariables("ColorPrefix", '&', false);
}
private static char ColorPrefix = '&';
/// <summary>
/// Progress bar object
/// </summary>
public class ProgressBar
private static bool CanAproximateTo(this float f, float y)
{
public float Max { get; init; }
public ConsoleColor Color { get; init; }
public bool NoColor { get; init; }
public void Update(float progress, double speed = -1, string? unit = null)
{
Console.CursorLeft = 0;
Console.Write("[");
Console.CursorLeft = 32;
Console.Write("]");
Console.CursorLeft = 1;
float onechunk = 30.0f / Max;
int position = 1;
for (int i = 0; i < onechunk * progress; i++)
{
Console.BackgroundColor = NoColor ? ConsoleColor.Black : this.Color;
Console.CursorLeft = position++;
Console.Write("#");
return MathF.Abs(f - y) < 0.000001;
}
for (int i = position; i <= 31; i++)
{
Console.BackgroundColor = NoColor ? ConsoleColor.Black : ConsoleColor.DarkGray;
Console.CursorLeft = position++;
Console.Write(" ");
}
Console.CursorLeft = 35;
Console.BackgroundColor = ConsoleColor.Black;
if (speed is -1 || unit == null)
{
if (progress.CanAproximateTo(Max))
Console.Write(progress + " % ✓");
else
Console.Write(MathF.Round(progress, 2) + " % ");
}
else
Console.Write(progress + $"{speed} {unit}/s ");
}
}
private static bool CanAproximateTo(this float f, float y) => (MathF.Abs(f - y) < 0.000001);
/// <summary>
/// A way to create a table based on input data
/// </summary>
/// <param name="data">The List of arrays of strings that represent the rows.</param>
public static void FormatAndAlignTable(List<string[]> data, TableFormat format = TableFormat.CENTER_EACH_COLUMN_BASED)
public static void FormatAndAlignTable(List<string[]> data, TableFormat format)
{
if (format == TableFormat.CENTER_EACH_COLUMN_BASED)
{
char tableLine = '-';
char tableCross = '+';
char tableWall = '|';
var tableLine = '-';
var tableCross = '+';
var tableWall = '|';
int[] len = new int[data[0].Length];
var len = new int[data[0].Length];
foreach (var line in data)
for (int i = 0; i < line.Length; i++)
for (var i = 0; i < line.Length; i++)
if (line[i].Length > len[i])
len[i] = line[i].Length;
foreach (string[] row in data)
foreach (var row in data)
{
if (row[0][0] == tableLine)
Console.Write(tableCross);
Logger.Write(tableCross);
else
Console.Write(tableWall);
for (int l = 0; l < row.Length; l++)
Logger.Write(tableWall);
for (var l = 0; l < row.Length; l++)
{
if (row[l][0] == tableLine)
{
for (int i = 0; i < len[l] + 4; ++i)
Console.Write(tableLine);
for (var i = 0; i < len[l] + 4; ++i)
Logger.Write(tableLine);
}
else if (row[l].Length == len[l])
{
Console.Write(" ");
Console.Write(row[l]);
Console.Write(" ");
Logger.Write(" ");
Logger.Write(row[l]);
Logger.Write(" ");
}
else
{
int lenHalf = row[l].Length / 2;
for (int i = 0; i < ((len[l] + 4) / 2 - lenHalf); ++i)
Console.Write(" ");
Console.Write(row[l]);
for (int i = (len[l] + 4) / 2 + lenHalf + 1; i < len[l] + 4; ++i)
Console.Write(" ");
var lenHalf = row[l].Length / 2;
for (var i = 0; i < (len[l] + 4) / 2 - lenHalf; ++i)
Logger.Write(" ");
Logger.Write(row[l]);
for (var i = (len[l] + 4) / 2 + lenHalf + 1; i < len[l] + 4; ++i)
Logger.Write(" ");
if (row[l].Length % 2 == 0)
Console.Write(" ");
Logger.Write(" ");
}
Console.Write(row[l][0] == tableLine ? tableCross : tableWall);
Logger.Write(row[l][0] == tableLine ? tableCross : tableWall);
}
Console.WriteLine(); //end line
Logger.WriteLine(); //end line
}
return;
@@ -141,54 +85,54 @@ namespace PluginManager.Others
if (format == TableFormat.CENTER_OVERALL_LENGTH)
{
int maxLen = 0;
foreach (string[] row in data)
foreach (string s in row)
var maxLen = 0;
foreach (var row in data)
foreach (var s in row)
if (s.Length > maxLen)
maxLen = s.Length;
int div = (maxLen + 4) / 2;
var div = (maxLen + 4) / 2;
foreach (string[] row in data)
foreach (var row in data)
{
Console.Write("\t");
Logger.Write("\t");
if (row[0] == "-")
Console.Write("+");
Logger.Write("+");
else
Console.Write("|");
Logger.Write("|");
foreach (string s in row)
foreach (var s in row)
{
if (s == "-")
{
for (int i = 0; i < maxLen + 4; ++i)
Console.Write("-");
for (var i = 0; i < maxLen + 4; ++i)
Logger.Write("-");
}
else if (s.Length == maxLen)
{
Console.Write(" ");
Console.Write(s);
Console.Write(" ");
Logger.Write(" ");
Logger.Write(s);
Logger.Write(" ");
}
else
{
int lenHalf = s.Length / 2;
for (int i = 0; i < div - lenHalf; ++i)
Console.Write(" ");
Console.Write(s);
for (int i = div + lenHalf + 1; i < maxLen + 4; ++i)
Console.Write(" ");
var lenHalf = s.Length / 2;
for (var i = 0; i < div - lenHalf; ++i)
Logger.Write(" ");
Logger.Write(s);
for (var i = div + lenHalf + 1; i < maxLen + 4; ++i)
Logger.Write(" ");
if (s.Length % 2 == 0)
Console.Write(" ");
Logger.Write(" ");
}
if (s == "-")
Console.Write("+");
Logger.Write("+");
else
Console.Write("|");
Logger.Write("|");
}
Console.WriteLine(); //end line
Logger.WriteLine(); //end line
}
return;
@@ -196,29 +140,25 @@ namespace PluginManager.Others
if (format == TableFormat.DEFAULT)
{
int[] widths = new int[data[0].Length];
int space_between_columns = int.Parse(Config.GetValue<Dictionary<string, string>>("TableVariables")?["DefaultSpace"]!);
for (int i = 0; i < data.Count; i++)
{
for (int j = 0; j < data[i].Length; j++)
{
var widths = new int[data[0].Length];
var space_between_columns = 3;
for (var i = 0; i < data.Count; i++)
for (var j = 0; j < data[i].Length; j++)
if (data[i][j].Length > widths[j])
widths[j] = data[i][j].Length;
}
}
for (int i = 0; i < data.Count; i++)
for (var i = 0; i < data.Count; i++)
{
for (int j = 0; j < data[i].Length; j++)
for (var j = 0; j < data[i].Length; j++)
{
if (data[i][j] == "-")
data[i][j] = " ";
Console.Write(data[i][j]);
for (int k = 0; k < widths[j] - data[i][j].Length + 1 + space_between_columns; k++)
Console.Write(" ");
Logger.Write(data[i][j]);
for (var k = 0; k < widths[j] - data[i][j].Length + 1 + space_between_columns; k++)
Logger.Write(" ");
}
Console.WriteLine();
Logger.WriteLine();
}
return;
@@ -229,17 +169,26 @@ namespace PluginManager.Others
public static void WriteColorText(string text, bool appendNewLineAtEnd = true)
{
ConsoleColor initialForeGround = Console.ForegroundColor;
char[] input = text.ToCharArray();
for (int i = 0; i < input.Length; i++)
if (!Logger.isConsole)
{
if (input[i] == Config.GetValue<char>("ColorPrefix"))
foreach (var item in Colors)
text = text.Replace($"{ColorPrefix}{item.Key}", "").Replace("&c", "");
Logger.Write(text);
if (appendNewLineAtEnd)
Logger.WriteLine();
return;
}
var initialForeGround = Console.ForegroundColor;
var input = text.ToCharArray();
for (var i = 0; i < input.Length; i++)
if (input[i] == ColorPrefix)
{
if (i + 1 < input.Length)
{
if (Config.GetValue<Dictionary<char, ConsoleColor>>("ColorDataBase")!.ContainsKey(input[i + 1]))
if (Colors.ContainsKey(input[i + 1]))
{
Console.ForegroundColor = Config.GetValue<Dictionary<char, ConsoleColor>>("ColorDataBase")![input[i + 1]];
Console.ForegroundColor = Colors[input[i + 1]];
i++;
}
else if (input[i + 1] == 'c')
@@ -250,12 +199,170 @@ namespace PluginManager.Others
}
}
else
Console.Write(input[i]);
{
Logger.Write(input[i]);
}
Console.ForegroundColor = initialForeGround;
if (appendNewLineAtEnd)
Console.WriteLine();
Logger.WriteLine();
}
/// <summary>
/// Progress bar object
/// </summary>
public class ProgressBar
{
private readonly int BarLength = 32;
private bool isRunning;
private int position = 1;
private bool positive = true;
public ProgressBar(ProgressBarType type)
{
if (!Logger.isConsole)
throw new Exception("This class (or function) can be used with console only. For UI please use another approach.");
this.type = type;
}
public float Max { get; init; }
public ConsoleColor Color { get; init; }
public bool NoColor { get; init; }
public ProgressBarType type { get; set; }
public int TotalLength { get; private set; }
public async void Start()
{
if (type != ProgressBarType.NO_END)
throw new Exception("Only NO_END progress bar can use this method");
if (isRunning)
throw new Exception("This progress bar is already running");
isRunning = true;
while (isRunning)
{
UpdateNoEnd();
await Task.Delay(100);
}
}
public async void Start(string message)
{
if (type != ProgressBarType.NO_END)
throw new Exception("Only NO_END progress bar can use this method");
if (isRunning)
throw new Exception("This progress bar is already running");
isRunning = true;
TotalLength = message.Length + BarLength + 5;
while (isRunning)
{
UpdateNoEnd(message);
await Task.Delay(100);
}
}
public void Stop()
{
if (type != ProgressBarType.NO_END)
throw new Exception("Only NO_END progress bar can use this method");
if (!isRunning)
throw new Exception("Can not stop a progressbar that did not start");
isRunning = false;
}
public void Stop(string message)
{
Stop();
if (message is not null)
{
Console.CursorLeft = 0;
for (var i = 0; i < BarLength + message.Length + 1; i++)
Logger.Write(" ");
Console.CursorLeft = 0;
Logger.WriteLine(message);
}
}
public void Update(float progress)
{
if (type == ProgressBarType.NO_END)
throw new Exception("This function is for progress bars with end");
UpdateNormal(progress);
}
private void UpdateNoEnd(string message)
{
Console.CursorLeft = 0;
Logger.Write("[");
for (var i = 1; i <= position; i++)
Logger.Write(" ");
Logger.Write("<==()==>");
position += positive ? 1 : -1;
for (var i = position; i <= BarLength - 1 - (positive ? 0 : 2); i++)
Logger.Write(" ");
Logger.Write("] " + message);
if (position == BarLength - 1 || position == 1)
positive = !positive;
}
private void UpdateNoEnd()
{
Console.CursorLeft = 0;
Logger.Write("[");
for (var i = 1; i <= position; i++)
Logger.Write(" ");
Logger.Write("<==()==>");
position += positive ? 1 : -1;
for (var i = position; i <= BarLength - 1 - (positive ? 0 : 2); i++)
Logger.Write(" ");
Logger.Write("]");
if (position == BarLength - 1 || position == 1)
positive = !positive;
}
private void UpdateNormal(float progress)
{
Console.CursorLeft = 0;
Logger.Write("[");
Console.CursorLeft = BarLength;
Logger.Write("]");
Console.CursorLeft = 1;
var onechunk = 30.0f / Max;
var position = 1;
for (var i = 0; i < onechunk * progress; i++)
{
Console.BackgroundColor = NoColor ? ConsoleColor.Black : Color;
Console.CursorLeft = position++;
Logger.Write("#");
}
for (var i = position; i < BarLength; i++)
{
Console.BackgroundColor = NoColor ? ConsoleColor.Black : ConsoleColor.DarkGray;
Console.CursorLeft = position++;
Logger.Write(" ");
}
Console.CursorLeft = BarLength + 4;
Console.BackgroundColor = ConsoleColor.Black;
if (progress.CanAproximateTo(Max))
Logger.Write(progress + " % ✓");
else
Logger.Write(MathF.Round(progress, 2) + " % ");
}
}
}

View File

@@ -1,13 +1,14 @@
using PluginManager.Interfaces;
namespace PluginManager.Others;
namespace PluginManager.Others;
/// <summary>
/// A list of operating systems
/// </summary>
public enum OperatingSystem
{
WINDOWS, LINUX, MAC_OS, UNKNOWN
WINDOWS,
LINUX,
MAC_OS,
UNKNOWN
}
/// <summary>
@@ -15,19 +16,47 @@ public enum OperatingSystem
/// </summary>
public enum Error
{
UNKNOWN_ERROR, GUILD_NOT_FOUND, STREAM_NOT_FOUND, INVALID_USER, INVALID_CHANNEL, INVALID_PERMISSIONS
UNKNOWN_ERROR,
GUILD_NOT_FOUND,
STREAM_NOT_FOUND,
INVALID_USER,
INVALID_CHANNEL,
INVALID_PERMISSIONS
}
/// <summary>
/// The output log type
/// </summary>
public enum OutputLogLevel { NONE, INFO, WARNING, ERROR, CRITICAL }
public enum OutputLogLevel
{
NONE,
INFO,
WARNING,
ERROR,
CRITICAL
}
/// <summary>
/// Plugin Type
/// </summary>
public enum PluginType { Command, Event, Unknown }
public enum UnzipProgressType
{
PercentageFromNumberOfFiles,
PercentageFromTotalSize
}
public enum UnzipProgressType { PercentageFromNumberOfFiles, PercentageFromTotalSize }
public enum TableFormat
{
CENTER_EACH_COLUMN_BASED,
CENTER_OVERALL_LENGTH,
DEFAULT
}
public enum TableFormat { CENTER_EACH_COLUMN_BASED, CENTER_OVERALL_LENGTH, DEFAULT }
public enum SaveType
{
NORMAL,
BACKUP
}
public enum ProgressBarType
{
NORMAL,
NO_END
}

View File

@@ -1,148 +1,65 @@
using System.IO.Compression;
using System.IO;
using System;
using System.Threading.Tasks;
using System.Linq;
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using Discord.WebSocket;
using PluginManager.Items;
using System.Threading;
using System.Text.Json;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
namespace PluginManager.Others
using Discord.WebSocket;
using PluginManager.Items;
namespace PluginManager.Others;
/// <summary>
/// A special class with functions
/// </summary>
public static class Functions
{
/// <summary>
/// A special class with functions
/// </summary>
public static class Functions
{
/// <summary>
/// The location for the Resources folder
/// </summary>
public static readonly string dataFolder = @"./Data/Resources/";
/// <summary>
/// The location for all logs
/// </summary>
public static readonly string logFolder = @"./Output/Logs/";
/// <summary>
/// The location for all errors
/// </summary>
public static readonly string errFolder = @"./Output/Errors/";
/// <summary>
/// Archives folder
/// </summary>
public static readonly string pakFolder = @"./Data/Resources/PAK/";
/// <summary>
/// Beta testing folder
/// </summary>
public static readonly string betaFolder = @"./Data/BetaTest/";
/// <summary>
/// Read data from a file that is inside an archive (ZIP format)
/// </summary>
/// <param name="FileName">The file name that is inside the archive or its full path</param>
/// <param name="archFile">The archive location from the PAKs folder</param>
/// <returns>A string that represents the content of the file or null if the file does not exists or it has no content</returns>
public static Stream? ReadFromPakAsync(string FileName, string archFile)
{
archFile = pakFolder + archFile;
Directory.CreateDirectory(pakFolder);
if (!File.Exists(archFile)) throw new FileNotFoundException("Failed to load file !");
using ZipArchive archive = ZipFile.OpenRead(archFile);
ZipArchiveEntry? entry = archive.GetEntry(FileName);
return entry?.Open();
}
/// <summary>
/// Write logs to file
/// </summary>
/// <param name="LogMessage">The message to be wrote</param>
public static void WriteLogFile(string LogMessage)
{
string logsPath = logFolder + $"{DateTime.Today.ToShortDateString().Replace("/", "-").Replace("\\", "-")} Log.txt";
Directory.CreateDirectory(logFolder);
File.AppendAllText(logsPath, LogMessage + " \n");
}
/// <summary>
/// Write error to file
/// </summary>
/// <param name="ErrMessage">The message to be wrote</param>
public static void WriteErrFile(string ErrMessage)
{
string errPath = errFolder + $"{DateTime.Today.ToShortDateString().Replace("/", "-").Replace("\\", "-")} Error.txt";
Directory.CreateDirectory(errFolder);
File.AppendAllText(errPath, ErrMessage + " \n");
}
/// <summary>
/// Merge one array of strings into one string
/// </summary>
/// <param name="s">The array of strings</param>
/// <param name="indexToStart">The index from where the merge should start (included)</param>
/// <returns>A string built based on the array</returns>
public static string MergeStrings(this string[] s, int indexToStart)
{
string r = "";
int len = s.Length;
if (len <= indexToStart) return "";
for (int i = indexToStart; i < len - 1; ++i)
{
r += s[i] + " ";
}
r += s[len - 1];
return r;
}
/// <summary>
/// Get the Operating system you are runnin on
/// </summary>
/// <returns>An Operating system</returns>
public static OperatingSystem GetOperatingSystem()
{
if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) return OperatingSystem.WINDOWS;
if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Linux)) return OperatingSystem.LINUX;
if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.OSX)) return OperatingSystem.MAC_OS;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) return OperatingSystem.WINDOWS;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) return OperatingSystem.LINUX;
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) return OperatingSystem.MAC_OS;
return OperatingSystem.UNKNOWN;
}
public static List<string> GetArguments(SocketMessage message)
{
Command command = new Command(message);
return command.Arguments;
}
/// <summary>
/// Copy one Stream to another <see langword="async"/>
/// Copy one Stream to another <see langword="async" />
/// </summary>
/// <param name="stream">The base stream</param>
/// <param name="destination">The destination stream</param>
/// <param name="bufferSize">The buffer to read</param>
/// <param name="progress">The progress</param>
/// <param name="cancellationToken">The cancellation token</param>
/// <exception cref="ArgumentNullException">Triggered if any <see cref="Stream"/> is empty</exception>
/// <exception cref="ArgumentOutOfRangeException">Triggered if <paramref name="bufferSize"/> is less then or equal to 0</exception>
/// <exception cref="InvalidOperationException">Triggered if <paramref name="stream"/> is not readable</exception>
/// <exception cref="ArgumentException">Triggered in <paramref name="destination"/> is not writable</exception>
public static async Task CopyToOtherStreamAsync(this Stream stream, Stream destination, int bufferSize, IProgress<long>? progress = null, CancellationToken cancellationToken = default)
/// <exception cref="ArgumentNullException">Triggered if any <see cref="Stream" /> is empty</exception>
/// <exception cref="ArgumentOutOfRangeException">Triggered if <paramref name="bufferSize" /> is less then or equal to 0</exception>
/// <exception cref="InvalidOperationException">Triggered if <paramref name="stream" /> is not readable</exception>
/// <exception cref="ArgumentException">Triggered in <paramref name="destination" /> is not writable</exception>
public static async Task CopyToOtherStreamAsync(this Stream stream, Stream destination, int bufferSize,
IProgress<long>? progress = null,
CancellationToken cancellationToken = default)
{
if (stream == null) throw new ArgumentNullException(nameof(stream));
if (destination == null) throw new ArgumentNullException(nameof(destination));
if (bufferSize <= 0) throw new ArgumentOutOfRangeException(nameof(bufferSize));
if (!stream.CanRead) throw new InvalidOperationException("The stream is not readable.");
if (!destination.CanWrite) throw new ArgumentException("Destination stream is not writable", nameof(destination));
if (!destination.CanWrite)
throw new ArgumentException("Destination stream is not writable", nameof(destination));
byte[] buffer = new byte[bufferSize];
var buffer = new byte[bufferSize];
long totalBytesRead = 0;
int bytesRead;
while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0)
@@ -151,105 +68,6 @@ namespace PluginManager.Others
totalBytesRead += bytesRead;
progress?.Report(totalBytesRead);
}
}
/// <summary>
/// Extract zip to location
/// </summary>
/// <param name="zip">The zip location</param>
/// <param name="folder">The target location</param>
/// <param name="progress">The progress that is updated as a file is processed</param>
/// <param name="type">The type of progress</param>
/// <returns></returns>
public static async Task ExtractArchive(string zip, string folder, IProgress<float> progress, UnzipProgressType type)
{
if (!Directory.Exists(folder)) Directory.CreateDirectory(folder);
using (ZipArchive archive = ZipFile.OpenRead(zip))
{
if (type == UnzipProgressType.PercentageFromNumberOfFiles)
{
int totalZIPFiles = archive.Entries.Count();
int currentZIPFile = 0;
foreach (ZipArchiveEntry entry in archive.Entries)
{
if (entry.FullName.EndsWith("/")) // it is a folder
Directory.CreateDirectory(Path.Combine(folder, entry.FullName));
else
try
{
entry.ExtractToFile(Path.Combine(folder, entry.FullName), true);
}
catch (Exception ex)
{
Console.WriteLine($"Failed to extract {entry.Name}. Exception: {ex.Message}");
}
currentZIPFile++;
await Task.Delay(10);
progress.Report((float)currentZIPFile / totalZIPFiles * 100);
}
}
else if (type == UnzipProgressType.PercentageFromTotalSize)
{
ulong zipSize = 0;
foreach (ZipArchiveEntry entry in archive.Entries)
zipSize += (ulong)entry.CompressedLength;
ulong currentSize = 0;
foreach (ZipArchiveEntry entry in archive.Entries)
{
if (entry.FullName.EndsWith("/"))
{
Directory.CreateDirectory(Path.Combine(folder, entry.FullName));
continue;
}
try
{
entry.ExtractToFile(Path.Combine(folder, entry.FullName), true);
currentSize += (ulong)entry.CompressedLength;
}
catch (Exception ex)
{
Console.WriteLine($"Failed to extract {entry.Name}. Exception: {ex.Message}");
}
await Task.Delay(10);
progress.Report((float)currentSize / zipSize * 100);
}
}
}
}
/// <summary>
/// Convert Bytes to highest measurement unit possible
/// </summary>
/// <param name="bytes">The amount of bytes</param>
/// <returns></returns>
public static (double, string) ConvertBytes(long bytes)
{
List<string> units = new List<string>()
{
"B",
"KB",
"MB",
"GB",
"TB"
};
int i = 0;
while (bytes >= 1024)
{
i++;
bytes /= 1024;
}
return (bytes, units[i]);
}
/// <summary>
@@ -261,10 +79,11 @@ namespace PluginManager.Others
/// <returns></returns>
public static async Task SaveToJsonFile<T>(string file, T Data)
{
File.Delete(file);
var s = File.Open(file, FileMode.OpenOrCreate);
await JsonSerializer.SerializeAsync(s, Data, typeof(T), new JsonSerializerOptions { WriteIndented = true });
s.Close();
var str = new MemoryStream();
await JsonSerializer.SerializeAsync(str, Data, typeof(T), new JsonSerializerOptions { WriteIndented = true });
await File.WriteAllBytesAsync(file, str.ToArray());
await str.FlushAsync();
str.Close();
}
/// <summary>
@@ -277,68 +96,13 @@ namespace PluginManager.Others
{
Stream text;
if (File.Exists(input))
text = File.OpenRead(input);
text = new MemoryStream(await File.ReadAllBytesAsync(input));
else
text = new MemoryStream(Encoding.ASCII.GetBytes(input));
text.Position = 0;
var obj = await JsonSerializer.DeserializeAsync<T>(text);
await text.FlushAsync();
text.Close();
return (obj ?? default)!;
}
/// <summary>
/// Check if all words from <paramref name="str"/> are in <paramref name="baseString"/><br/>
/// This function returns true if<br/>
/// 1. The <paramref name="str"/> is part of <paramref name="baseString"/><br/>
/// 2. The words (split by a space) of <paramref name="str"/> are located (separately) in <paramref name="baseString"/> <br/>
/// <example>
/// The following example will return <see langword="TRUE"/><br/>
/// <c>STRContains("Hello World !", "I type word Hello and then i typed word World !")</c><br/>
/// The following example will return <see langword="TRUE"/><br/>
/// <c>STRContains("Hello World !", "I typed Hello World !" </c><br/>
/// The following example will return <see langword="TRUE"/><br/>
/// <c>STRContains("Hello World", "I type World then Hello")</c><br/>
/// The following example will return <see langword="FALSE"/><br/>
/// <c>STRContains("Hello World !", "I typed Hello World")</c><br/>
/// </example>
/// </summary>
/// <param name="str">The string you are checking</param>
/// <param name="baseString">The main string that should contain <paramref name="str"/></param>
/// <returns></returns>
public static bool STRContains(this string str, string baseString)
{
if (baseString.Contains(str)) return true;
string[] array = str.Split(' ');
foreach (var s in array)
if (!baseString.Contains(s))
return false;
return true;
}
public static bool TryReadValueFromJson(string input, string codeName, out JsonElement element)
{
Stream text;
if (File.Exists(input))
text = File.OpenRead(input);
else
text = new MemoryStream(Encoding.ASCII.GetBytes(input));
var jsonObject = JsonDocument.Parse(text);
var data = jsonObject.RootElement.TryGetProperty(codeName, out element);
return data;
}
public static string CreateMD5(string input)
{
using (MD5 md5 = MD5.Create())
{
byte[] inputBytes = Encoding.ASCII.GetBytes(input);
byte[] hashBytes = md5.ComputeHash(inputBytes);
return Convert.ToHexString(hashBytes);
}
}
}
}

View File

@@ -1,4 +1,5 @@
using System.Linq;
using Discord;
using Discord.WebSocket;

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
@@ -16,7 +16,9 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Discord.Net" Version="3.7.2" />
<PackageReference Include="Discord.Net" Version="3.8.1" />
<PackageReference Include="System.Data.SQLite.Core" Version="1.0.117" />
<PackageReference Include="Terminal.Gui" Version="1.8.2" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,17 @@
using PluginManager.Database;
namespace PluginManager
{
public class Settings
{
public static class Variables
{
public static string WebsiteURL = "https://wizzy69.github.io/SethDiscordBot";
public static string UpdaterURL = "https://github.com/Wizzy69/installer/releases/download/release-1-discordbot/Updater.zip";
}
public static SqlDatabase sqlDatabase;
}
}

142
README.md
View File

@@ -15,89 +15,81 @@ This project is based on:
Plugin Types:
1. Commands
2. Events
<!--
Project Structure
![Image](../../blob/gh-pages/Pictures/architecture2.png)-->
3. Slash Commands
### How to create a plugin
First of all, Create a new project (class library) in Visual Studio.
![Imgur Image](https://i.imgur.com/KUqzKsB.png)
Then import the PluginManager.dll as project to your project.
![Imgur Image](https://i.imgur.com/JzpEViR.png)
![Imgur Image](https://i.imgur.com/vtoEepX.png)
![Imgur Image](https://i.imgur.com/ceaVR2R.png)
Now, let's add the PluginManager reference. It can be found inside the bot's main folder under
`DiscordBot/bin/Debug/net6.0/PluginManager.dll` or `PluginManager/bin/Debug/net6.0/PluginManager.dll`
after one successfull build.
![Imgur Image](https://i.imgur.com/UMSitk4.png)
![Imgur Image](https://i.imgur.com/GEjShdl.png)
1. Commands
## 1. Commands
Commands are loaded when all plugins are loaded into memory. When an user executes the command, only then the Execute function is called.
Commands are plugins that allow users to interact with them.
Here is an example of class that is a command class
Here is an example:
```cs
using Discord;
using Discord.Commands;
using Discord.WebSocket;
using PluginManager.Interfaces;
namespace CMD_Utils
namespace LevelingSystem;
internal class LevelCommand : DBCommand
{
class FlipCoin : DBCommand
{
public string Command => "flip";
public string Command => "level";
public string Description => "Flip a coin";
public List<string> Aliases => new() { "lvl" };
public string Usage => "flip";
public string Description => "Display tour current level";
public bool canUseDM => true;
public bool canUseServer => true;
public string Usage => "level";
public bool requireAdmin => false;
public async void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM)
public async void ExecuteServer(SocketCommandContext context)
{
System.Random random = new System.Random();
int r = random.Next(1, 3);
if (r == 1)
await message.Channel.SendMessageAsync("Heads");
else await message.Channel.SendMessageAsync("Tails");
object[] user = await Variables.database.ReadDataArrayAsync($"SELECT * FROM Levels WHERE UserID='{context.Message.Author.Id}'");
if (user is null)
{
await context.Channel.SendMessageAsync("You are now unranked !");
return;
}
int level = (int)user[1];
int exp = (int)user[2];
var builder = new EmbedBuilder();
var r = new Random();
builder.WithColor(r.Next(256), r.Next(256), r.Next(256));
builder.AddField("Current Level", level, true)
.AddField("Current EXP", exp, true)
.AddField("Required Exp", (level * 8 + 24).ToString(), true);
builder.WithTimestamp(DateTimeOffset.Now);
builder.WithAuthor(context.Message.Author.Mention);
await context.Channel.SendMessageAsync(embed: builder.Build());
}
}
```
#### Code description:
- Command - The keyword that triggers the execution for the command. This is what players must type in order to execute your command
- Aliases - The aliases that can be used instead of the full name to execute the command
- Description - The description of your command. Can be anything you like
- Usage - The usage of your command. This is what `help [Command]` command will display
- canUseDM - true if you plan to let users execute this command in DM chat with bot
- canUseServer - true if you plan to let the users execute this command in a server chat
- requireAdmin - true if this command requres an user with Administrator permission in the server
- Execute () - the function of your command.
- ExecuteServer () - the function that is executed only when the command is invoked in a server channel. (optional)
- context - the command context
- ExecuteDM () - the function that is executed only when the command is invoked in a private (DM) channel. (optional)
- context - the command context
- message - the message itself
- client - the discord bot client
- isDM - true if the message was sent from DM chat
From here on, start coding. When your plugin is done, build it as any DLL project then add it to the following path
`{bot_executable}/Data/Plugins/Commands/<optional subfolder>/yourDLLName.dll`
`{bot_executable}/Data/Plugins/<optional subfolder>/[your dll name].dll`
Then, reload bot and execute command `lp` in bot's console. The plugin should be loaded into memory or an error is thrown if not. If an error is thrown, then
there is something wrong in your command's code.
2. Events
## 2. Events
Events are loaded when all plugins are loaded. At the moment when they are loaded, the Start function is called.
Events are used if you want the bot to do something when something happens in server. The following example shows you how to catch when a user joins the server
@@ -130,3 +122,61 @@ public class OnUserJoin : DBEvent
- Start() - The main body of your event. This is executed when the bot loads all plugins
- client - the discord bot client
## 3. Slash Commands
Slash commands are server based commands. They work the same way as normal commands, but they require the `/` prefix as they are integrated
with the UI of Discord.
Here is an example:
```cs
using Discord;
using Discord.WebSocket;
using PluginManager.Interfaces;
namespace SlashCommands
{
public class Random : DBSlashCommand
{
public string Name => "random";
public string Description => "Generates a random nunber between 2 values";
public bool canUseDM => true;
public List<SlashCommandOptionBuilder> Options => new List<SlashCommandOptionBuilder>()
{
new SlashCommandOptionBuilder() {Name = "min-value", Description = "Minimum value", IsRequired=true, Type = ApplicationCommandOptionType.Integer, MinValue = 0, MaxValue = int.MaxValue-1},
new SlashCommandOptionBuilder() {Name="max-value", Description = "Maximum value", IsRequired=true, Type=ApplicationCommandOptionType.Integer,MinValue = 0, MaxValue = int.MaxValue-1}
};
public async void ExecuteServer(SocketSlashCommand command)
{
var rnd = new System.Random();
var options = command.Data.Options.ToArray();
if (options.Count() != 2)
{
await command.RespondAsync("Invalid parameters", ephemeral: true);
return;
}
Int64 numberOne = (Int64)options[0].Value;
Int64 numberTwo = (Int64)options[1].Value;
await command.RespondAsync("Your generated number is " + rnd.Next((int)numberOne, (int)numberTwo), ephemeral: true);
}
}
}
```
#### Code description:
- Name - the command name (execute with /{Name})
- Description - The description of the command
- canUseDM - true id this command can be activated in DM chat, false otherwise
- Options - the arguments of the command
- ExecuteServer() - this function will be called if the command is invoked in a server channel (optional)
- context - the command context
- ExecuteDM() - this function will be called if the command is invoked in a DM channel (optional)
- context - the command context

View File

@@ -1,57 +0,0 @@
using System.IO.Compression;
using System.Runtime.CompilerServices;
using Discord;
using Discord.Commands;
using Discord.Rest;
using Discord.WebSocket;
using Microsoft.Win32.SafeHandles;
using PluginManager.Interfaces;
using PluginManager.Others;
using Roles.Internals;
namespace Roles
{
public class AddRole : DBCommand
{
public string Command => "addrole";
public List<string> Aliases => new() { "ar", "addr", "roleadd" };
public string Description => "Role options";
public string Usage => "addrole [user1] [user2] ... [role1] [role2] ...";
public bool canUseDM => false;
public bool canUseServer => true;
public bool requireAdmin => true;
public async void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM)
{
if (message.MentionedUsers.Count == 0 || message.MentionedRoles.Count == 0)
{
await context.Channel.SendMessageAsync($"Invalid invocation\nUsage:{Usage}");
return;
}
try
{
var users = message.MentionedUsers;
var roles = message.MentionedRoles as IEnumerable<IRole>;
foreach (var user in users)
{
SocketGuildUser? usr = context.Client.GetUser(user.Username, user.Discriminator) as SocketGuildUser;
if (usr is null)
throw new Exception("User is null");
await usr.AddRolesAsync(roles);
}
}
catch (Exception ex)
{
await context.Channel.SendMessageAsync(ex.Message);
}
}
}
}

View File

@@ -1,79 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Discord;
using Discord.WebSocket;
using PluginManager.Others;
namespace Roles.Internals
{
internal static class RoleManagement
{
internal static async void AddRole(this SocketGuildUser user, string roleName)
{
string role = roleName;
IRole? r = user.Guild.Roles.FirstOrDefault(rl => rl.Name == role || rl.Mention == role);
if (r is null)
throw new Exception("The role does not exist");
try
{
await user.AddRoleAsync(r);
}
catch (Exception ex)
{
if (ex.Message.Contains("Permission", StringComparison.CurrentCultureIgnoreCase))
throw new Exception("Insufficient permissions");
}
}
internal static async void AddRole(this SocketGuildUser user, IRole role)
{
try
{
await user.AddRoleAsync(role);
}
catch (Exception ex)
{
if (ex.Message.Contains("Permission", StringComparison.CurrentCultureIgnoreCase))
throw new Exception("Insufficient permissions");
}
}
internal static async void AddRoles(this SocketGuildUser user, string[] roleNames)
{
foreach (string rolename in roleNames)
{
string roleName = rolename;
IRole? r = user.Guild.Roles.FirstOrDefault(rl => rl.Name == roleName || rl.Mention == roleName);
if (r is null)
throw new Exception("The role does not exist");
try
{
await user.AddRoleAsync(r);
}
catch (Exception ex)
{
if (ex.Message.Contains("Permission", StringComparison.CurrentCultureIgnoreCase))
throw new Exception("Insufficient permissions");
}
}
}
internal static async void AddRoles(this SocketGuildUser user, IEnumerable<IRole> roles)
{
try
{
await user.AddRolesAsync(roles);
}
catch (Exception ex)
{
if (ex.Message.Contains("Permission", StringComparison.CurrentCultureIgnoreCase))
throw new Exception("Insufficient permissions");
}
}
}
}

View File

@@ -1,13 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\PluginManager\PluginManager.csproj" />
</ItemGroup>
</Project>

Some files were not shown because too many files have changed in this diff Show More