Adding Entity guides, flowcharts, better sample system. (#2054)
* initial * Interaction glossary entry * Sharded Interaction sample * Renames into solution * Debugging samples * Modify target location for webhookclient * Finalizing docs work, resolving docfx errors. * Adding threaduser to user chart * Add branch info to readme. * Edits to user chart * Resolve format for glossary entries * Patch sln target * Issue with file naming fixed * Patch 1/x for builds * Appending suggestions
This commit is contained in:
231
Discord.Net.sln
231
Discord.Net.sln
@@ -4,43 +4,45 @@ VisualStudioVersion = 17.1.31903.286
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Core", "src\Discord.Net.Core\Discord.Net.Core.csproj", "{91E9E7BD-75C9-4E98-84AA-2C271922E5C2}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Impls", "Impls", "{288C363D-A636-4EAE-9AC1-4698B641B26E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Rest", "src\Discord.Net.Rest\Discord.Net.Rest.csproj", "{BFC6DC28-0351-4573-926A-D4124244C04F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Commands", "src\Discord.Net.Commands\Discord.Net.Commands.csproj", "{078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.WebSocket", "src\Discord.Net.WebSocket\Discord.Net.WebSocket.csproj", "{688FD1D8-7F01-4539-B2E9-F473C5D699C7}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extensions", "Extensions", "{CC3D4B1C-9DE0-448B-8AE7-F3F1F3EC5C3A}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Webhook", "src\Discord.Net.Webhook\Discord.Net.Webhook.csproj", "{9AFAB80E-D2D3-4EDB-B58C-BACA78D1EA30}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{BB59D5B5-E7B0-4BF4-8F82-D14431B2799B}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Examples", "src\Discord.Net.Examples\Discord.Net.Examples.csproj", "{47820065-3CFB-401C-ACEA-862BD564A404}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "01_basic_ping_bot", "samples\01_basic_ping_bot\01_basic_ping_bot.csproj", "{F2FF84FB-F6AD-47E5-9EE5-18206CAE136E}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Interactions", "src\Discord.Net.Interactions\Discord.Net.Interactions.csproj", "{137DB209-B357-4EE8-A6EE-4B6127F6DEE9}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "02_commands_framework", "samples\02_commands_framework\02_commands_framework.csproj", "{4E1F1F40-B1DD-40C9-A4B1-A2046A4C9C76}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Analyzers", "src\Discord.Net.Analyzers\Discord.Net.Analyzers.csproj", "{24C231FD-8CF3-444A-9E7C-45C18BAD4A0D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "03_sharded_client", "samples\03_sharded_client\03_sharded_client.csproj", "{9B4C4AFB-3D15-44C6-9E36-12ED625AAA26}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Analyzers.Tests", "test\Discord.Net.Analyzers.Tests\Discord.Net.Analyzers.Tests.csproj", "{FC67057C-E92F-4E1C-98BE-46F839C8AD71}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Tests.Unit", "test\Discord.Net.Tests.Unit\Discord.Net.Tests.Unit.csproj", "{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Tests.Integration", "test\Discord.Net.Tests.Integration\Discord.Net.Tests.Integration.csproj", "{E169E15A-E82C-45BF-8C24-C2CADB7093AA}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_BasicBot", "samples\BasicBot\_BasicBot.csproj", "{F2FF84FB-F6AD-47E5-9EE5-18206CAE136E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_TextCommandFramework", "samples\TextCommandFramework\_TextCommandFramework.csproj", "{4E1F1F40-B1DD-40C9-A4B1-A2046A4C9C76}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_ShardedClient", "samples\ShardedClient\_ShardedClient.csproj", "{9B4C4AFB-3D15-44C6-9E36-12ED625AAA26}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_InteractionFramework", "samples\InteractionFramework\_InteractionFramework.csproj", "{A23E46D2-1610-4AE5-820F-422D34810887}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_WebhookClient", "samples\WebhookClient\_WebhookClient.csproj", "{B61AAE66-15CC-40E4-873A-C23E697C3411}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IDN", "samples\idn\idn.csproj", "{4A03840B-9EBE-47E3-89AB-E0914DF21AFB}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{C7CF5621-7D36-433B-B337-5A2E3C101A71}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Analyzers.Tests", "test\Discord.Net.Analyzers.Tests\Discord.Net.Analyzers.Tests.csproj", "{FC67057C-E92F-4E1C-98BE-46F839C8AD71}"
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Impls", "Impls", "{288C363D-A636-4EAE-9AC1-4698B641B26E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Examples", "src\Discord.Net.Examples\Discord.Net.Examples.csproj", "{47820065-3CFB-401C-ACEA-862BD564A404}"
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extensions", "Extensions", "{CC3D4B1C-9DE0-448B-8AE7-F3F1F3EC5C3A}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "idn", "samples\idn\idn.csproj", "{4A03840B-9EBE-47E3-89AB-E0914DF21AFB}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Interactions", "src\Discord.Net.Interactions\Discord.Net.Interactions.csproj", "{137DB209-B357-4EE8-A6EE-4B6127F6DEE9}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "04_interactions_framework", "samples\04_interactions_framework\04_interactions_framework.csproj", "{A23E46D2-1610-4AE5-820F-422D34810887}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Analyzers", "src\Discord.Net.Analyzers\Discord.Net.Analyzers.csproj", "{24C231FD-8CF3-444A-9E7C-45C18BAD4A0D}"
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{BB59D5B5-E7B0-4BF4-8F82-D14431B2799B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@@ -112,6 +114,78 @@ Global
|
||||
{9AFAB80E-D2D3-4EDB-B58C-BACA78D1EA30}.Release|x64.Build.0 = Release|Any CPU
|
||||
{9AFAB80E-D2D3-4EDB-B58C-BACA78D1EA30}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{9AFAB80E-D2D3-4EDB-B58C-BACA78D1EA30}.Release|x86.Build.0 = Release|Any CPU
|
||||
{47820065-3CFB-401C-ACEA-862BD564A404}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{47820065-3CFB-401C-ACEA-862BD564A404}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{47820065-3CFB-401C-ACEA-862BD564A404}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{47820065-3CFB-401C-ACEA-862BD564A404}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{47820065-3CFB-401C-ACEA-862BD564A404}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{47820065-3CFB-401C-ACEA-862BD564A404}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{47820065-3CFB-401C-ACEA-862BD564A404}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{47820065-3CFB-401C-ACEA-862BD564A404}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{47820065-3CFB-401C-ACEA-862BD564A404}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{47820065-3CFB-401C-ACEA-862BD564A404}.Release|x64.Build.0 = Release|Any CPU
|
||||
{47820065-3CFB-401C-ACEA-862BD564A404}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{47820065-3CFB-401C-ACEA-862BD564A404}.Release|x86.Build.0 = Release|Any CPU
|
||||
{137DB209-B357-4EE8-A6EE-4B6127F6DEE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{137DB209-B357-4EE8-A6EE-4B6127F6DEE9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{137DB209-B357-4EE8-A6EE-4B6127F6DEE9}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{137DB209-B357-4EE8-A6EE-4B6127F6DEE9}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{137DB209-B357-4EE8-A6EE-4B6127F6DEE9}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{137DB209-B357-4EE8-A6EE-4B6127F6DEE9}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{137DB209-B357-4EE8-A6EE-4B6127F6DEE9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{137DB209-B357-4EE8-A6EE-4B6127F6DEE9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{137DB209-B357-4EE8-A6EE-4B6127F6DEE9}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{137DB209-B357-4EE8-A6EE-4B6127F6DEE9}.Release|x64.Build.0 = Release|Any CPU
|
||||
{137DB209-B357-4EE8-A6EE-4B6127F6DEE9}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{137DB209-B357-4EE8-A6EE-4B6127F6DEE9}.Release|x86.Build.0 = Release|Any CPU
|
||||
{24C231FD-8CF3-444A-9E7C-45C18BAD4A0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{24C231FD-8CF3-444A-9E7C-45C18BAD4A0D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{24C231FD-8CF3-444A-9E7C-45C18BAD4A0D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{24C231FD-8CF3-444A-9E7C-45C18BAD4A0D}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{24C231FD-8CF3-444A-9E7C-45C18BAD4A0D}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{24C231FD-8CF3-444A-9E7C-45C18BAD4A0D}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{24C231FD-8CF3-444A-9E7C-45C18BAD4A0D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{24C231FD-8CF3-444A-9E7C-45C18BAD4A0D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{24C231FD-8CF3-444A-9E7C-45C18BAD4A0D}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{24C231FD-8CF3-444A-9E7C-45C18BAD4A0D}.Release|x64.Build.0 = Release|Any CPU
|
||||
{24C231FD-8CF3-444A-9E7C-45C18BAD4A0D}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{24C231FD-8CF3-444A-9E7C-45C18BAD4A0D}.Release|x86.Build.0 = Release|Any CPU
|
||||
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Release|x64.Build.0 = Release|Any CPU
|
||||
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Release|x86.Build.0 = Release|Any CPU
|
||||
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Release|x64.Build.0 = Release|Any CPU
|
||||
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Release|x86.Build.0 = Release|Any CPU
|
||||
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Release|x64.Build.0 = Release|Any CPU
|
||||
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Release|x86.Build.0 = Release|Any CPU
|
||||
{F2FF84FB-F6AD-47E5-9EE5-18206CAE136E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F2FF84FB-F6AD-47E5-9EE5-18206CAE136E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F2FF84FB-F6AD-47E5-9EE5-18206CAE136E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
@@ -148,78 +222,6 @@ Global
|
||||
{9B4C4AFB-3D15-44C6-9E36-12ED625AAA26}.Release|x64.Build.0 = Release|Any CPU
|
||||
{9B4C4AFB-3D15-44C6-9E36-12ED625AAA26}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{9B4C4AFB-3D15-44C6-9E36-12ED625AAA26}.Release|x86.Build.0 = Release|Any CPU
|
||||
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Release|x64.Build.0 = Release|Any CPU
|
||||
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Release|x86.Build.0 = Release|Any CPU
|
||||
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Release|x64.Build.0 = Release|Any CPU
|
||||
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Release|x86.Build.0 = Release|Any CPU
|
||||
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Release|x64.Build.0 = Release|Any CPU
|
||||
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Release|x86.Build.0 = Release|Any CPU
|
||||
{47820065-3CFB-401C-ACEA-862BD564A404}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{47820065-3CFB-401C-ACEA-862BD564A404}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{47820065-3CFB-401C-ACEA-862BD564A404}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{47820065-3CFB-401C-ACEA-862BD564A404}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{47820065-3CFB-401C-ACEA-862BD564A404}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{47820065-3CFB-401C-ACEA-862BD564A404}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{47820065-3CFB-401C-ACEA-862BD564A404}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{47820065-3CFB-401C-ACEA-862BD564A404}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{47820065-3CFB-401C-ACEA-862BD564A404}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{47820065-3CFB-401C-ACEA-862BD564A404}.Release|x64.Build.0 = Release|Any CPU
|
||||
{47820065-3CFB-401C-ACEA-862BD564A404}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{47820065-3CFB-401C-ACEA-862BD564A404}.Release|x86.Build.0 = Release|Any CPU
|
||||
{4A03840B-9EBE-47E3-89AB-E0914DF21AFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4A03840B-9EBE-47E3-89AB-E0914DF21AFB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4A03840B-9EBE-47E3-89AB-E0914DF21AFB}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4A03840B-9EBE-47E3-89AB-E0914DF21AFB}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{4A03840B-9EBE-47E3-89AB-E0914DF21AFB}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{4A03840B-9EBE-47E3-89AB-E0914DF21AFB}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{4A03840B-9EBE-47E3-89AB-E0914DF21AFB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4A03840B-9EBE-47E3-89AB-E0914DF21AFB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4A03840B-9EBE-47E3-89AB-E0914DF21AFB}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4A03840B-9EBE-47E3-89AB-E0914DF21AFB}.Release|x64.Build.0 = Release|Any CPU
|
||||
{4A03840B-9EBE-47E3-89AB-E0914DF21AFB}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4A03840B-9EBE-47E3-89AB-E0914DF21AFB}.Release|x86.Build.0 = Release|Any CPU
|
||||
{137DB209-B357-4EE8-A6EE-4B6127F6DEE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{137DB209-B357-4EE8-A6EE-4B6127F6DEE9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{137DB209-B357-4EE8-A6EE-4B6127F6DEE9}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{137DB209-B357-4EE8-A6EE-4B6127F6DEE9}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{137DB209-B357-4EE8-A6EE-4B6127F6DEE9}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{137DB209-B357-4EE8-A6EE-4B6127F6DEE9}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{137DB209-B357-4EE8-A6EE-4B6127F6DEE9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{137DB209-B357-4EE8-A6EE-4B6127F6DEE9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{137DB209-B357-4EE8-A6EE-4B6127F6DEE9}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{137DB209-B357-4EE8-A6EE-4B6127F6DEE9}.Release|x64.Build.0 = Release|Any CPU
|
||||
{137DB209-B357-4EE8-A6EE-4B6127F6DEE9}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{137DB209-B357-4EE8-A6EE-4B6127F6DEE9}.Release|x86.Build.0 = Release|Any CPU
|
||||
{A23E46D2-1610-4AE5-820F-422D34810887}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A23E46D2-1610-4AE5-820F-422D34810887}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A23E46D2-1610-4AE5-820F-422D34810887}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
@@ -232,18 +234,30 @@ Global
|
||||
{A23E46D2-1610-4AE5-820F-422D34810887}.Release|x64.Build.0 = Release|Any CPU
|
||||
{A23E46D2-1610-4AE5-820F-422D34810887}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{A23E46D2-1610-4AE5-820F-422D34810887}.Release|x86.Build.0 = Release|Any CPU
|
||||
{24C231FD-8CF3-444A-9E7C-45C18BAD4A0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{24C231FD-8CF3-444A-9E7C-45C18BAD4A0D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{24C231FD-8CF3-444A-9E7C-45C18BAD4A0D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{24C231FD-8CF3-444A-9E7C-45C18BAD4A0D}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{24C231FD-8CF3-444A-9E7C-45C18BAD4A0D}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{24C231FD-8CF3-444A-9E7C-45C18BAD4A0D}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{24C231FD-8CF3-444A-9E7C-45C18BAD4A0D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{24C231FD-8CF3-444A-9E7C-45C18BAD4A0D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{24C231FD-8CF3-444A-9E7C-45C18BAD4A0D}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{24C231FD-8CF3-444A-9E7C-45C18BAD4A0D}.Release|x64.Build.0 = Release|Any CPU
|
||||
{24C231FD-8CF3-444A-9E7C-45C18BAD4A0D}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{24C231FD-8CF3-444A-9E7C-45C18BAD4A0D}.Release|x86.Build.0 = Release|Any CPU
|
||||
{B61AAE66-15CC-40E4-873A-C23E697C3411}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B61AAE66-15CC-40E4-873A-C23E697C3411}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B61AAE66-15CC-40E4-873A-C23E697C3411}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{B61AAE66-15CC-40E4-873A-C23E697C3411}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{B61AAE66-15CC-40E4-873A-C23E697C3411}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{B61AAE66-15CC-40E4-873A-C23E697C3411}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{B61AAE66-15CC-40E4-873A-C23E697C3411}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B61AAE66-15CC-40E4-873A-C23E697C3411}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B61AAE66-15CC-40E4-873A-C23E697C3411}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{B61AAE66-15CC-40E4-873A-C23E697C3411}.Release|x64.Build.0 = Release|Any CPU
|
||||
{B61AAE66-15CC-40E4-873A-C23E697C3411}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{B61AAE66-15CC-40E4-873A-C23E697C3411}.Release|x86.Build.0 = Release|Any CPU
|
||||
{4A03840B-9EBE-47E3-89AB-E0914DF21AFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4A03840B-9EBE-47E3-89AB-E0914DF21AFB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4A03840B-9EBE-47E3-89AB-E0914DF21AFB}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4A03840B-9EBE-47E3-89AB-E0914DF21AFB}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{4A03840B-9EBE-47E3-89AB-E0914DF21AFB}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{4A03840B-9EBE-47E3-89AB-E0914DF21AFB}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{4A03840B-9EBE-47E3-89AB-E0914DF21AFB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4A03840B-9EBE-47E3-89AB-E0914DF21AFB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4A03840B-9EBE-47E3-89AB-E0914DF21AFB}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4A03840B-9EBE-47E3-89AB-E0914DF21AFB}.Release|x64.Build.0 = Release|Any CPU
|
||||
{4A03840B-9EBE-47E3-89AB-E0914DF21AFB}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4A03840B-9EBE-47E3-89AB-E0914DF21AFB}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -253,17 +267,18 @@ Global
|
||||
{078DD7E6-943D-4D09-AFC2-D2BA58B76C9C} = {CC3D4B1C-9DE0-448B-8AE7-F3F1F3EC5C3A}
|
||||
{688FD1D8-7F01-4539-B2E9-F473C5D699C7} = {288C363D-A636-4EAE-9AC1-4698B641B26E}
|
||||
{9AFAB80E-D2D3-4EDB-B58C-BACA78D1EA30} = {CC3D4B1C-9DE0-448B-8AE7-F3F1F3EC5C3A}
|
||||
{47820065-3CFB-401C-ACEA-862BD564A404} = {BB59D5B5-E7B0-4BF4-8F82-D14431B2799B}
|
||||
{137DB209-B357-4EE8-A6EE-4B6127F6DEE9} = {CC3D4B1C-9DE0-448B-8AE7-F3F1F3EC5C3A}
|
||||
{24C231FD-8CF3-444A-9E7C-45C18BAD4A0D} = {CC3D4B1C-9DE0-448B-8AE7-F3F1F3EC5C3A}
|
||||
{FC67057C-E92F-4E1C-98BE-46F839C8AD71} = {C7CF5621-7D36-433B-B337-5A2E3C101A71}
|
||||
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4} = {C7CF5621-7D36-433B-B337-5A2E3C101A71}
|
||||
{E169E15A-E82C-45BF-8C24-C2CADB7093AA} = {C7CF5621-7D36-433B-B337-5A2E3C101A71}
|
||||
{F2FF84FB-F6AD-47E5-9EE5-18206CAE136E} = {BB59D5B5-E7B0-4BF4-8F82-D14431B2799B}
|
||||
{4E1F1F40-B1DD-40C9-A4B1-A2046A4C9C76} = {BB59D5B5-E7B0-4BF4-8F82-D14431B2799B}
|
||||
{9B4C4AFB-3D15-44C6-9E36-12ED625AAA26} = {BB59D5B5-E7B0-4BF4-8F82-D14431B2799B}
|
||||
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4} = {C7CF5621-7D36-433B-B337-5A2E3C101A71}
|
||||
{E169E15A-E82C-45BF-8C24-C2CADB7093AA} = {C7CF5621-7D36-433B-B337-5A2E3C101A71}
|
||||
{FC67057C-E92F-4E1C-98BE-46F839C8AD71} = {C7CF5621-7D36-433B-B337-5A2E3C101A71}
|
||||
{47820065-3CFB-401C-ACEA-862BD564A404} = {BB59D5B5-E7B0-4BF4-8F82-D14431B2799B}
|
||||
{4A03840B-9EBE-47E3-89AB-E0914DF21AFB} = {BB59D5B5-E7B0-4BF4-8F82-D14431B2799B}
|
||||
{137DB209-B357-4EE8-A6EE-4B6127F6DEE9} = {CC3D4B1C-9DE0-448B-8AE7-F3F1F3EC5C3A}
|
||||
{A23E46D2-1610-4AE5-820F-422D34810887} = {BB59D5B5-E7B0-4BF4-8F82-D14431B2799B}
|
||||
{24C231FD-8CF3-444A-9E7C-45C18BAD4A0D} = {CC3D4B1C-9DE0-448B-8AE7-F3F1F3EC5C3A}
|
||||
{B61AAE66-15CC-40E4-873A-C23E697C3411} = {BB59D5B5-E7B0-4BF4-8F82-D14431B2799B}
|
||||
{4A03840B-9EBE-47E3-89AB-E0914DF21AFB} = {BB59D5B5-E7B0-4BF4-8F82-D14431B2799B}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {D2404771-EEC8-45F2-9D71-F3373F6C1495}
|
||||
|
||||
19
README.md
19
README.md
@@ -81,3 +81,22 @@ Due to the nature of the Discord API, we will oftentimes need to add a property
|
||||
Furthermore, while we will never break the API (outside of interface changes) on minor builds, we will occasionally need to break the ABI, by introducing parameters to a method to match changes upstream with Discord. As such, a minor version increment may require you to recompile your code, and dependencies, such as addons, may also need to be recompiled and republished on the newer version. When a binary breaking change is made, the change will be noted in the release notes.
|
||||
|
||||
An increment of the MAJOR component indicates that breaking changes have been made to the library; consumers should check the release notes to determine what changes need to be made.
|
||||
|
||||
## Branches
|
||||
|
||||
### Release/X.X
|
||||
|
||||
Release branch following Major.Minor. Upon release, patches will be pushed to these branches.
|
||||
New NuGet releases will be tagged on these branches.
|
||||
|
||||
### Dev
|
||||
|
||||
Development branch, available on MyGet. This branch is what pull requests are targetted to.
|
||||
|
||||
### Feature/X
|
||||
|
||||
Branches that target Dev, adding new features. Feel free to explore these branches and give feedback where necessary.
|
||||
|
||||
### Docs/X
|
||||
|
||||
Usually targets Dev. These branches are used to update documentation with either new features or existing feature rework.
|
||||
|
||||
@@ -53,7 +53,7 @@ able to message.
|
||||
You may check the message channel type. Visit [Glossary] to see the
|
||||
various types of channels.
|
||||
|
||||
[glossary]: xref:FAQ.Glossary#message-channels
|
||||
[Glossary]: xref:Guides.Entities.Glossary#channels
|
||||
|
||||
## How can I get the guild from a message?
|
||||
|
||||
|
||||
@@ -24,6 +24,6 @@ Visit the repo's [release tag] to see the latest public pre-release.
|
||||
|
||||
The `DependencyMap` has been replaced with Microsoft's
|
||||
[DependencyInjection] Abstractions. An example usage can be seen
|
||||
[here](https://github.com/foxbot/DiscordBotBase/blob/csharp/src/DiscordBot/Program.cs#L36).
|
||||
[here](https://github.com/Discord-Net-Labs/Discord.Net-Labs/blob/release/3.x/samples/InteractionFramework/Program.cs#L66).
|
||||
|
||||
[DependencyInjection]: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection
|
||||
|
||||
@@ -16,7 +16,5 @@
|
||||
topicUid: FAQ.Commands.Interactions
|
||||
- name: Dependency Injection
|
||||
topicUid: FAQ.Commands.DI
|
||||
- name: Glossary
|
||||
topicUid: FAQ.Glossary
|
||||
- name: Legacy or Upgrade
|
||||
topicUid: FAQ.Legacy
|
||||
|
||||
68
docs/guides/entities/casting.md
Normal file
68
docs/guides/entities/casting.md
Normal file
@@ -0,0 +1,68 @@
|
||||
---
|
||||
uid: Guides.Entities.Casting
|
||||
title: Casting & Unboxing
|
||||
---
|
||||
|
||||
# Casting
|
||||
|
||||
Casting can be done in many ways, and is the only method to box and unbox types to/from their base definition.
|
||||
Casting only works for types that inherit the base type that you want to unbox from.
|
||||
`IUser` cannot be cast to `IMessage`.
|
||||
|
||||
> [!NOTE]
|
||||
> Interfaces **can** be cast to other interfaces, as long as they inherit each other.
|
||||
> The same goes for reverse casting. As long as some entity can be simplified into what it inherits, your cast will pass.
|
||||
|
||||
## Boxing
|
||||
|
||||
A boxed object is the definition of an object that was simplified (or trimmed) by incoming traffic,
|
||||
but still owns the data of the originally constructed type. Boxing is an implicit operation.
|
||||
|
||||
Through casting, we can **unbox** this type, and access the properties that were unaccessible before.
|
||||
|
||||
## Unboxing
|
||||
|
||||
Unboxing is the most direct way to access the real definition of an object.
|
||||
If we want to return a type from its interface, we can unbox it directly.
|
||||
|
||||
[!code-csharp[Unboxing](samples/unboxing.cs)]
|
||||
|
||||
## Regular casting
|
||||
|
||||
In 'regular' casting, we use the `as` keyword to assign the given type to the object.
|
||||
If the boxed type can indeed be cast into given type,
|
||||
it will become said type, and its properties can be accessed.
|
||||
[!code-csharp[Casting](samples/casting.cs)]
|
||||
|
||||
> [!WARNING]
|
||||
> If the type you're casting to is null, a `NullReferenceException` will be thrown when it's called.
|
||||
> This makes safety casting much more interesting to use, as it prevents this exception from being thrown.
|
||||
|
||||
## Safety casting
|
||||
|
||||
Safety casting makes sure that the type you're trying to cast to can never be null, as it passes checks upon calling them.
|
||||
|
||||
There are 3 different ways to safety cast an object:
|
||||
|
||||
### Basic safety casting:
|
||||
|
||||
To safety cast an object, all we need to do is check if it is of the member type in a statement.
|
||||
If this check fails, it will continue below, making sure we don't try to access null.
|
||||
[!code-csharp[Base](samples/safety-cast.cs)]
|
||||
|
||||
### Object declaration:
|
||||
|
||||
Here we declare the object we are casting to,
|
||||
making it so that you can immediately work with its properties without reassigning through regular casting.
|
||||
[!code-csharp[Declare](samples/safety-cast-var.cs)]
|
||||
|
||||
### Reverse passage:
|
||||
|
||||
In previous examples, we want to let code continue running after the check, or if the check fails.
|
||||
In this example, the cast will return the entire method (ignoring the latter) upon failure,
|
||||
and declare the variable for further use into the method:
|
||||
[!code-csharp[Pass](samples/safety-cast-pass.cs)]
|
||||
|
||||
> [!NOTE]
|
||||
> Usage of `is`, `not` and `as` is required in cast assignment and/or type checks. `==`, `!=` and `=` are invalid assignment,
|
||||
> as these operators only apply to initialized objects and not their types.
|
||||
@@ -1,29 +1,19 @@
|
||||
---
|
||||
uid: FAQ.Glossary
|
||||
title: Common Terminologies / Glossary
|
||||
uid: Guides.Entities.Glossary
|
||||
title: Glossary & Flowcharts
|
||||
---
|
||||
|
||||
# Glossary
|
||||
# Entity Types
|
||||
|
||||
This is an additional chapter for quick references to various common
|
||||
types that you may see within Discord.Net. To see more information
|
||||
regarding each type of object, click on the object to navigate
|
||||
to our API documentation page where you might find more explanation
|
||||
about it.
|
||||
A list of all Discord.Net entities, what they can be cast to and what their properties are.
|
||||
|
||||
## Common Types
|
||||
> [!NOTE]
|
||||
> All interfaces have the same inheritance tree for both `Socket` and `Rest` entities.
|
||||
> Entities with that have been marked red are exclusive to the project they source from.
|
||||
|
||||
* A **Guild** ([IGuild]) is an isolated collection of users and
|
||||
channels, and are often referred to as "servers".
|
||||
- Example: [Discord API](https://discord.gg/jkrBmQR)
|
||||
* A **Channel** ([IChannel]) represents a generic channel.
|
||||
- Example: #dotnet_discord-net
|
||||
- See [Channel Types](#channel-types)
|
||||
## Channels
|
||||
|
||||
[IGuild]: xref:Discord.IGuild
|
||||
[IChannel]: xref:Discord.IChannel
|
||||
|
||||
## Channel Types
|
||||

|
||||
|
||||
### Message Channels
|
||||
* A **Text Channel** ([ITextChannel]) is a message channel from a Guild.
|
||||
@@ -40,14 +30,11 @@ channels, and are often referred to as "servers".
|
||||
- This can be any channels that may exist in a guild.
|
||||
* A **Voice Channel** ([IVoiceChannel]) is a voice channel in a guild.
|
||||
* A **Stage Channel** ([IStageChannel]) is a stage channel in a guild.
|
||||
* A **Category Channel** ([ICategoryChannel]) (2.0+) is a category that
|
||||
* A **Category Channel** ([ICategoryChannel]) is a category that
|
||||
holds one or more sub-channels.
|
||||
* A **Nested Channel** ([INestedChannel]) (2.0+) is a channel that can
|
||||
* A **Nested Channel** ([INestedChannel]) is a channel that can
|
||||
exist under a category.
|
||||
|
||||
> [!NOTE]
|
||||
> A Channel ([IChannel]) can be all types of channels.
|
||||
|
||||
[INestedChannel]: xref:Discord.INestedChannel
|
||||
[IGuildChannel]: xref:Discord.IGuildChannel
|
||||
[IMessageChannel]: xref:Discord.IMessageChannel
|
||||
@@ -62,17 +49,27 @@ exist under a category.
|
||||
[IStageChannel]: xref:Discord.IStageChannel
|
||||
[INewsChannel]: xref:Discord.INewsChannel
|
||||
|
||||
## Message Types
|
||||
## Messages
|
||||
|
||||

|
||||
|
||||
* A **Rest Followup Message** ([RestFollowupMessage]) is a message returned by followup on on an interaction.
|
||||
* A **Rest Interaction Message** ([RestInteractionMessage]) is a message returned by the interaction's original response.
|
||||
* A **Rest User Message** ([RestUserMessage]) is a message sent over rest; it can be any of the above.
|
||||
* An **User Message** ([IUserMessage]) is a message sent by a user.
|
||||
* A **System Message** ([ISystemMessage]) is a message sent by Discord itself.
|
||||
* A **Message** ([IMessage]) can be any of the above.
|
||||
|
||||
[RestFollowupMessage]: xref:Discord.Rest.RestFollowupMessage
|
||||
[RestInteractionMessage]: xref:Discord.Rest.RestInteractionMessage
|
||||
[RestUserMEssage]: xref:Discord.Rest.RestUserMessage
|
||||
[IUserMessage]: xref:Discord.IUserMessage
|
||||
[ISystemMessage]: xref:Discord.ISystemMessage
|
||||
[IMessage]: xref:Discord.IMessage
|
||||
|
||||
## User Types
|
||||
## Users
|
||||
|
||||

|
||||
|
||||
* A **Guild User** ([IGuildUser]) is a user available inside a guild.
|
||||
* A **Group User** ([IGroupUser]) is a user available inside a group.
|
||||
@@ -85,7 +82,29 @@ exist under a category.
|
||||
[ISelfUser]: xref:Discord.ISelfUser
|
||||
[IUser]: xref:Discord.IUser
|
||||
|
||||
## Emoji Types
|
||||
## Interactions
|
||||
|
||||

|
||||
|
||||
* A **Slash command** ([ISlashCommandInteraction]) is an application command executed in the text box, with provided parameters.
|
||||
* A **Message Command** ([IMessageCommandInteraction]) is an application command targetting a message.
|
||||
* An **User Command** ([IUserCommandInteraction]) is an application command targetting a user.
|
||||
* An **Application Command** ([IApplicationCommandInteraction]) is any of the above.
|
||||
* A **Message component** ([IMessageComponent]) is the interaction of a button being clicked/dropdown option(s) entered.
|
||||
* An **Autocomplete Interaction** ([IAutocompleteinteraction]) is an interaction that has been automatically completed.
|
||||
* An **Interaction** ([IDiscordInteraction]) is any of the above.
|
||||
|
||||
[ISlashCommandInteraction]: xref:Discord.ISlashCommandInteraction
|
||||
[IMessageCommandInteraction]: xref:Discord.IMessageCommandInteraction
|
||||
[IUserCommandInteraction]: xref:Discord.IUserCommandInteraction
|
||||
[IApplicationCommandInteraction]: xref:Discord.IApplicationCommandInteraction
|
||||
[IMessageComponent]: xref:Discord.IMessageComponent
|
||||
[IAutocompleteinteraction]: xref:Discord.IAutocompleteInteraction
|
||||
[IDiscordInteraction]: xref:Discord.IDiscordInteraction
|
||||
|
||||
## Other types:
|
||||
|
||||
### Emoji
|
||||
|
||||
* An **Emote** ([Emote]) is a custom emote from a guild.
|
||||
- Example: `<:dotnet:232902710280716288>`
|
||||
@@ -95,8 +114,7 @@ exist under a category.
|
||||
[Emote]: xref:Discord.Emote
|
||||
[Emoji]: xref:Discord.Emoji
|
||||
|
||||
|
||||
## Sticker Types
|
||||
### Stickers
|
||||
|
||||
* A **Sticker** ([ISticker]) is a standard Discord sticker.
|
||||
* A **Custom Sticker ([ICustomSticker]) is a Guild-unique sticker.
|
||||
@@ -104,7 +122,7 @@ exist under a category.
|
||||
[ISticker]: xref:Discord.ISticker
|
||||
[ICustomSticker]: xref:Discord.ICustomSticker
|
||||
|
||||
## Activity Types
|
||||
### Activity
|
||||
|
||||
* A **Game** ([Game]) refers to a user's game activity.
|
||||
* A **Rich Presence** ([RichGame]) refers to a user's detailed
|
||||
BIN
docs/guides/entities/images/IChannel.png
Normal file
BIN
docs/guides/entities/images/IChannel.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 58 KiB |
BIN
docs/guides/entities/images/IInteraction.png
Normal file
BIN
docs/guides/entities/images/IInteraction.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 37 KiB |
BIN
docs/guides/entities/images/IMessage.png
Normal file
BIN
docs/guides/entities/images/IMessage.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
BIN
docs/guides/entities/images/IUser.png
Normal file
BIN
docs/guides/entities/images/IUser.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 62 KiB |
@@ -1,26 +1,41 @@
|
||||
---
|
||||
uid: Guides.Concepts.Entities
|
||||
title: Entities
|
||||
uid: Guides.Entities.Intro
|
||||
title: Introduction
|
||||
---
|
||||
|
||||
# Entities in Discord.Net
|
||||
|
||||
> [!NOTE]
|
||||
> This article is written with the Socket variants of entities in mind,
|
||||
> not the general interfaces or Rest entities.
|
||||
|
||||
Discord.Net provides a versatile entity system for navigating the
|
||||
Discord API.
|
||||
|
||||
> [!TIP]
|
||||
> It is **vital** that you use the proper IDs for an entity when using
|
||||
> a `GetXXX` method. It is recommended that you enable Discord's
|
||||
> _developer mode_ to allow easy access to entity IDs, found in
|
||||
> Settings > Appearance > Advanced. Read more about it in the
|
||||
> [FAQ](xref:FAQ.Basics.GetStarted) page.
|
||||
|
||||
## Inheritance
|
||||
|
||||
Due to the nature of the Discord API, some entities are designed with
|
||||
multiple variants; for example, `SocketUser` and `SocketGuildUser`.
|
||||
multiple variants; for example, `IUser` and `IGuildUser`.
|
||||
|
||||
All models will contain the most detailed version of an entity
|
||||
possible, even if the type is less detailed.
|
||||
|
||||
For example, in the case of the `MessageReceived` event, a
|
||||
## Socket & REST
|
||||
|
||||
REST entities are retrieved over REST, and will be disposed after use.
|
||||
It is suggested to limit the amount of REST calls as much as possible,
|
||||
as calls over REST interact with the API, and are thus prone to rate-limits.
|
||||
|
||||
- [Learn more about REST](https://restfulapi.net/)
|
||||
|
||||
Socket entities are created through the gateway,
|
||||
most commonly through `DiscordSocketClient` events.
|
||||
These entities will enter the clients' global cache for later use.
|
||||
|
||||
In the case of the `MessageReceived` event, a
|
||||
`SocketMessage` is passed in with a channel property of type
|
||||
`SocketMessageChannel`. All messages come from channels capable of
|
||||
messaging, so this is the only variant of a channel that can cover
|
||||
@@ -31,7 +46,9 @@ But that doesn't mean a message _can't_ come from a
|
||||
retrieve information about a guild from a message entity, you will
|
||||
need to cast its channel object to a `SocketTextChannel`.
|
||||
|
||||
You can find out various types of entities in the [Glossary page.](xref:FAQ.Glossary)
|
||||
> [!NOTE]
|
||||
> You can find out the inheritance tree & definitions of various entities
|
||||
> [here](xref:Guides.Entities.Glossary)
|
||||
|
||||
## Navigation
|
||||
|
||||
@@ -40,26 +57,31 @@ you to easily navigate to an entity's parent or children. As explained
|
||||
above, you will sometimes need to cast to a more detailed version of
|
||||
an entity to navigate to its parent.
|
||||
|
||||
## Accessing Entities
|
||||
## Accessing Socket Entities
|
||||
|
||||
The most basic forms of entities, `SocketGuild`, `SocketUser`, and
|
||||
`SocketChannel` can be pulled from the DiscordSocketClient's global
|
||||
cache, and can be retrieved using the respective `GetXXX` method on
|
||||
DiscordSocketClient.
|
||||
|
||||
> [!TIP]
|
||||
> It is **vital** that you use the proper IDs for an entity when using
|
||||
> a `GetXXX` method. It is recommended that you enable Discord's
|
||||
> _developer mode_ to allow easy access to entity IDs, found in
|
||||
> Settings > Appearance > Advanced. Read more about it in the
|
||||
> [FAQ](xref:FAQ.Basics.GetStarted) page.
|
||||
|
||||
More detailed versions of entities can be pulled from the basic
|
||||
entities, e.g., `SocketGuild.GetUser`, which returns a
|
||||
`SocketGuildUser`, or `SocketGuild.GetChannel`, which returns a
|
||||
`SocketGuildChannel`. Again, you may need to cast these objects to get
|
||||
a variant of the type that you need.
|
||||
|
||||
## Sample
|
||||
### Sample
|
||||
|
||||
[!code-csharp[Entity Sample](samples/entities.cs)]
|
||||
[!code-csharp[Socket Sample](samples/socketentities.cs)]
|
||||
|
||||
## Accessing REST Entities
|
||||
|
||||
REST entities work almost the same as Socket entities, but are much less frequently used.
|
||||
To access REST entities, the `DiscordSocketClient`'s `Rest` property is required.
|
||||
Another option here is to create your own [DiscordRestClient], independent of the Socket gateway.
|
||||
|
||||
[DiscordRestClient]: xref:Discord.Rest.DiscordRestClient
|
||||
|
||||
### Sample
|
||||
|
||||
[!code-csharp[Rest Sample](samples/restentities.cs)]
|
||||
7
docs/guides/entities/samples/casting.cs
Normal file
7
docs/guides/entities/samples/casting.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
// Say we have an entity; for the simplicity of this example, it will appear from thin air.
|
||||
IChannel channel;
|
||||
|
||||
// If we want this to be an ITextChannel so we can access the properties of a text channel inside of a guild, an approach would be:
|
||||
ITextChannel textChannel = channel as ITextChannel;
|
||||
|
||||
await textChannel.DoSomethingICantWithIChannelAsync();
|
||||
8
docs/guides/entities/samples/restentities.cs
Normal file
8
docs/guides/entities/samples/restentities.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
// RestUser entities expose the accent color and banner of a user.
|
||||
// This being one of the few use-cases for requesting a RestUser instead of depending on the Socket counterpart.
|
||||
public static EmbedBuilder WithUserColor(this EmbedBuilder builder, IUser user)
|
||||
{
|
||||
var restUser = await _client.Rest.GetUserAsync(user.Id);
|
||||
return builder.WithColor(restUser.AccentColor ?? Color.Blue);
|
||||
// The accent color can still be null, so a check for this needs to be done to prevent an exception to be thrown.
|
||||
}
|
||||
10
docs/guides/entities/samples/safety-cast-pass.cs
Normal file
10
docs/guides/entities/samples/safety-cast-pass.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
private void MyFunction(IMessage message)
|
||||
{
|
||||
// Here we do the reverse as in the previous examples, and let it continue the code below if it IS an IUserMessage
|
||||
if (message is not IUserMessage userMessage)
|
||||
return;
|
||||
|
||||
// Because we do the above check inline (don't give the statement a body),
|
||||
// the code will still declare `userMessage` as available outside of the above statement.
|
||||
Console.WriteLine(userMessage.Author);
|
||||
}
|
||||
9
docs/guides/entities/samples/safety-cast-var.cs
Normal file
9
docs/guides/entities/samples/safety-cast-var.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
IUser user;
|
||||
|
||||
// Here we can pre-define the actual declaration of said IGuildUser object,
|
||||
// so we don't need to cast additionally inside of the statement.
|
||||
if (user is IGuildUser guildUser)
|
||||
{
|
||||
Console.WriteLine(guildUser.JoinedAt);
|
||||
}
|
||||
// Check failed.
|
||||
8
docs/guides/entities/samples/safety-cast.cs
Normal file
8
docs/guides/entities/samples/safety-cast.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
IUser user;
|
||||
|
||||
// Here we check if the user is an IGuildUser, if not, let it pass. This ensures its not null.
|
||||
if (user is IGuildUser)
|
||||
{
|
||||
Console.WriteLine("This user is in a guild!");
|
||||
}
|
||||
// Check failed.
|
||||
9
docs/guides/entities/samples/unboxing.cs
Normal file
9
docs/guides/entities/samples/unboxing.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
IUser user;
|
||||
|
||||
// Here we use inline unboxing to make a call to its member (if available) only once.
|
||||
|
||||
// Note that if the entity we're trying to cast to is null, this will throw a NullReferenceException.
|
||||
Console.WriteLine(((IGuildUser)user).Nickname);
|
||||
|
||||
// In case you are certain the entity IS said member, you can also use unboxing to declare variables.
|
||||
IGuildUser guildUser = (IGuildUser)user;
|
||||
@@ -21,8 +21,14 @@
|
||||
topicUid: Guides.Concepts.Events
|
||||
- name: Managing Connections
|
||||
topicUid: Guides.Concepts.ManageConnections
|
||||
- name: Entities
|
||||
topicUid: Guides.Concepts.Entities
|
||||
- name: Entities
|
||||
items:
|
||||
- name: Introduction
|
||||
topicUid: Guides.Entities.Intro
|
||||
- name: Casting
|
||||
topicUid: Guides.Entities.Casting
|
||||
- name: Glossary & Flowcharts
|
||||
topicUid: Guides.Entities.Glossary
|
||||
- name: Working with Text-based Commands
|
||||
items:
|
||||
- name: Introduction
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Discord;
|
||||
using Discord.WebSocket;
|
||||
|
||||
namespace _01_basic_ping_bot
|
||||
{
|
||||
// This is a minimal, bare-bones example of using Discord.Net
|
||||
//
|
||||
// If writing a bot with commands, we recommend using the Discord.Net.Commands
|
||||
// framework, rather than handling commands yourself, like we do in this sample.
|
||||
//
|
||||
// You can find samples of using the command framework:
|
||||
// - Here, under the 02_commands_framework sample
|
||||
// - https://github.com/foxbot/DiscordBotBase - a bare-bones bot template
|
||||
// - https://github.com/foxbot/patek - a more feature-filled bot, utilizing more aspects of the library
|
||||
class Program
|
||||
{
|
||||
private readonly DiscordSocketClient _client;
|
||||
|
||||
// Discord.Net heavily utilizes TAP for async, so we create
|
||||
// an asynchronous context from the beginning.
|
||||
static void Main(string[] args)
|
||||
{
|
||||
new Program().MainAsync().GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
public Program()
|
||||
{
|
||||
// It is recommended to Dispose of a client when you are finished
|
||||
// using it, at the end of your app's lifetime.
|
||||
_client = new DiscordSocketClient();
|
||||
|
||||
_client.Log += LogAsync;
|
||||
_client.Ready += ReadyAsync;
|
||||
_client.MessageReceived += MessageReceivedAsync;
|
||||
}
|
||||
|
||||
public async Task MainAsync()
|
||||
{
|
||||
// Tokens should be considered secret data, and never hard-coded.
|
||||
await _client.LoginAsync(TokenType.Bot, Environment.GetEnvironmentVariable("token"));
|
||||
await _client.StartAsync();
|
||||
|
||||
// Block the program until it is closed.
|
||||
await Task.Delay(Timeout.Infinite);
|
||||
}
|
||||
|
||||
private Task LogAsync(LogMessage log)
|
||||
{
|
||||
Console.WriteLine(log.ToString());
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
// The Ready event indicates that the client has opened a
|
||||
// connection and it is now safe to access the cache.
|
||||
private Task ReadyAsync()
|
||||
{
|
||||
Console.WriteLine($"{_client.CurrentUser} is connected!");
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
// This is not the recommended way to write a bot - consider
|
||||
// reading over the Commands Framework sample.
|
||||
private async Task MessageReceivedAsync(SocketMessage message)
|
||||
{
|
||||
// The bot should never respond to itself.
|
||||
if (message.Author.Id == _client.CurrentUser.Id)
|
||||
return;
|
||||
|
||||
if (message.Content == "!ping")
|
||||
await message.Channel.SendMessageAsync("pong!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _04_interactions_framework
|
||||
{
|
||||
public enum ExampleEnum
|
||||
{
|
||||
First,
|
||||
Second,
|
||||
Third,
|
||||
Fourth
|
||||
}
|
||||
}
|
||||
112
samples/BasicBot/Program.cs
Normal file
112
samples/BasicBot/Program.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Discord;
|
||||
using Discord.WebSocket;
|
||||
|
||||
namespace BasicBot
|
||||
{
|
||||
// This is a minimal, bare-bones example of using Discord.Net.
|
||||
//
|
||||
// If writing a bot with commands/interactions, we recommend using the Discord.Net.Commands/Discord.Net.Interactions
|
||||
// framework, rather than handling them yourself, like we do in this sample.
|
||||
//
|
||||
// You can find samples of using the command framework:
|
||||
// - Here, under the TextCommandFramework sample
|
||||
// - At the guides: https://discordnet.dev/guides/text_commands/intro.html
|
||||
//
|
||||
// You can find samples of using the interaction framework:
|
||||
// - Here, under the InteractionFramework sample
|
||||
// - At the guides: https://discordnet.dev/guides/int_framework/intro.html
|
||||
class Program
|
||||
{
|
||||
// Non-static readonly fields can only be assigned in a constructor.
|
||||
// If you want to assign it elsewhere, consider removing the readonly keyword.
|
||||
private readonly DiscordSocketClient _client;
|
||||
|
||||
// Discord.Net heavily utilizes TAP for async, so we create
|
||||
// an asynchronous context from the beginning.
|
||||
static void Main(string[] args)
|
||||
=> new Program()
|
||||
.MainAsync()
|
||||
.GetAwaiter()
|
||||
.GetResult();
|
||||
|
||||
public Program()
|
||||
{
|
||||
// It is recommended to Dispose of a client when you are finished
|
||||
// using it, at the end of your app's lifetime.
|
||||
_client = new DiscordSocketClient();
|
||||
|
||||
// Subscribing to client events, so that we may receive them whenever they're invoked.
|
||||
_client.Log += LogAsync;
|
||||
_client.Ready += ReadyAsync;
|
||||
_client.MessageReceived += MessageReceivedAsync;
|
||||
_client.InteractionCreated += InteractionCreatedAsync;
|
||||
}
|
||||
|
||||
public async Task MainAsync()
|
||||
{
|
||||
// Tokens should be considered secret data, and never hard-coded.
|
||||
await _client.LoginAsync(TokenType.Bot, Environment.GetEnvironmentVariable("token"));
|
||||
// Different approaches to making your token a secret is by putting them in local .json, .yaml, .xml or .txt files, then reading them on startup.
|
||||
|
||||
await _client.StartAsync();
|
||||
|
||||
// Block the program until it is closed.
|
||||
await Task.Delay(Timeout.Infinite);
|
||||
}
|
||||
|
||||
private Task LogAsync(LogMessage log)
|
||||
{
|
||||
Console.WriteLine(log.ToString());
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
// The Ready event indicates that the client has opened a
|
||||
// connection and it is now safe to access the cache.
|
||||
private Task ReadyAsync()
|
||||
{
|
||||
Console.WriteLine($"{_client.CurrentUser} is connected!");
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
// This is not the recommended way to write a bot - consider
|
||||
// reading over the Commands Framework sample.
|
||||
private async Task MessageReceivedAsync(SocketMessage message)
|
||||
{
|
||||
// The bot should never respond to itself.
|
||||
if (message.Author.Id == _client.CurrentUser.Id)
|
||||
return;
|
||||
|
||||
|
||||
if (message.Content == "!ping")
|
||||
{
|
||||
// Create a new componentbuilder, in which dropdowns & buttons can be created.
|
||||
var cb = new ComponentBuilder()
|
||||
.WithButton("Click me!", "unique-id", ButtonStyle.Primary);
|
||||
|
||||
// Send a message with content 'pong', including a button.
|
||||
// This button needs to be build by calling .Build() before being passed into the call.
|
||||
await message.Channel.SendMessageAsync("pong!", components: cb.Build());
|
||||
}
|
||||
}
|
||||
|
||||
// For better functionality & a more developer-friendly approach to handling any kind of interaction, refer to:
|
||||
// https://discordnet.dev/guides/int_framework/intro.html
|
||||
private async Task InteractionCreatedAsync(SocketInteraction interaction)
|
||||
{
|
||||
// safety-casting is the best way to prevent something being cast from being null.
|
||||
// If this check does not pass, it could not be cast to said type.
|
||||
if (interaction is SocketMessageComponent component)
|
||||
{
|
||||
// Check for the ID created in the button mentioned above.
|
||||
if (component.Data.CustomId == "unique-id")
|
||||
await interaction.RespondAsync("Thank you for clicking my button!");
|
||||
|
||||
else Console.WriteLine("An ID has been received that has no handler!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using Discord;
|
||||
using Discord.Interactions;
|
||||
using Discord.WebSocket;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace InteractionFramework.Attributes
|
||||
{
|
||||
internal class DoUserCheck : PreconditionAttribute
|
||||
{
|
||||
public override Task<PreconditionResult> CheckRequirementsAsync(IInteractionContext context, ICommandInfo commandInfo, IServiceProvider services)
|
||||
{
|
||||
// Check if the component matches the target properly.
|
||||
if (context.Interaction is not SocketMessageComponent componentContext)
|
||||
return Task.FromResult(PreconditionResult.FromError("Context unrecognized as component context."));
|
||||
|
||||
else
|
||||
{
|
||||
// The approach here entirely depends on how you construct your custom ID. In this case, the format is:
|
||||
// unique-name:*,*
|
||||
|
||||
// here the name and wildcards are split by ':'
|
||||
var param = componentContext.Data.CustomId.Split(':');
|
||||
|
||||
// here we determine that we should always check for the first ',' present.
|
||||
// This will deal with additional wildcards by always selecting the first wildcard present.
|
||||
if (param.Length > 1 && ulong.TryParse(param[1].Split(',')[0], out ulong id))
|
||||
return (context.User.Id == id)
|
||||
// If the user ID
|
||||
? Task.FromResult(PreconditionResult.FromSuccess())
|
||||
: Task.FromResult(PreconditionResult.FromError("User ID does not match component ID!"));
|
||||
|
||||
else return Task.FromResult(PreconditionResult.FromError("Parse cannot be done if no userID exists."));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _04_interactions_framework
|
||||
namespace InteractionFramework.Attributes
|
||||
{
|
||||
public class RequireOwnerAttribute : PreconditionAttribute
|
||||
{
|
||||
@@ -2,13 +2,10 @@ using Discord;
|
||||
using Discord.Interactions;
|
||||
using Discord.WebSocket;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _04_interactions_framework
|
||||
namespace InteractionFramework
|
||||
{
|
||||
public class CommandHandler
|
||||
{
|
||||
@@ -27,6 +24,9 @@ namespace _04_interactions_framework
|
||||
{
|
||||
// Add the public modules that inherit InteractionModuleBase<T> to the InteractionService
|
||||
await _commands.AddModulesAsync(Assembly.GetEntryAssembly(), _services);
|
||||
// Another approach to get the assembly of a specific type is:
|
||||
// typeof(CommandHandler).Assembly
|
||||
|
||||
|
||||
// Process the InteractionCreated payloads to execute Interactions commands
|
||||
_client.InteractionCreated += HandleInteraction;
|
||||
@@ -37,6 +37,8 @@ namespace _04_interactions_framework
|
||||
_commands.ComponentCommandExecuted += ComponentCommandExecuted;
|
||||
}
|
||||
|
||||
# region Error Handling
|
||||
|
||||
private Task ComponentCommandExecuted (ComponentCommandInfo arg1, Discord.IInteractionContext arg2, IResult arg3)
|
||||
{
|
||||
if (!arg3.IsSuccess)
|
||||
@@ -123,6 +125,9 @@ namespace _04_interactions_framework
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
# endregion
|
||||
|
||||
# region Execution
|
||||
|
||||
private async Task HandleInteraction (SocketInteraction arg)
|
||||
{
|
||||
@@ -142,5 +147,6 @@ namespace _04_interactions_framework
|
||||
await arg.GetOriginalResponseAsync().ContinueWith(async (msg) => await msg.Result.DeleteAsync());
|
||||
}
|
||||
}
|
||||
# endregion
|
||||
}
|
||||
}
|
||||
10
samples/InteractionFramework/ExampleEnum.cs
Normal file
10
samples/InteractionFramework/ExampleEnum.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace InteractionFramework
|
||||
{
|
||||
public enum ExampleEnum
|
||||
{
|
||||
First,
|
||||
Second,
|
||||
Third,
|
||||
Fourth
|
||||
}
|
||||
}
|
||||
18
samples/InteractionFramework/Modules/ComponentModule.cs
Normal file
18
samples/InteractionFramework/Modules/ComponentModule.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using Discord.Interactions;
|
||||
using Discord.WebSocket;
|
||||
using InteractionFramework.Attributes;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace InteractionFramework
|
||||
{
|
||||
// As with all other modules, we create the context by defining what type of interaction this module is supposed to target.
|
||||
internal class ComponentModule : InteractionModuleBase<SocketInteractionContext<SocketMessageComponent>>
|
||||
{
|
||||
// With the Attribute DoUserCheck you can make sure that only the user this button targets can click it. This is defined by the first wildcard: *.
|
||||
// See Attributes/DoUserCheckAttribute.cs for elaboration.
|
||||
[DoUserCheck]
|
||||
[ComponentInteraction("myButton:*")]
|
||||
public async Task ClickButtonAsync(string userId)
|
||||
=> await RespondAsync(text: ":thumbsup: Clicked!");
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,11 @@
|
||||
using Discord;
|
||||
using Discord.Interactions;
|
||||
using Discord.WebSocket;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _04_interactions_framework.Modules
|
||||
namespace InteractionFramework.Modules
|
||||
{
|
||||
// Interation modules must be public and inherit from an IInterationModuleBase
|
||||
public class UtilityModule : InteractionModuleBase<SocketInteractionContext>
|
||||
public class GeneralModule : InteractionModuleBase<SocketInteractionContext>
|
||||
{
|
||||
// Dependencies can be accessed through Property injection, public properties with public setters will be set by the service provider
|
||||
public InteractionService Commands { get; set; }
|
||||
@@ -18,7 +13,7 @@ namespace _04_interactions_framework.Modules
|
||||
private CommandHandler _handler;
|
||||
|
||||
// Constructor injection is also a valid way to access the dependecies
|
||||
public UtilityModule ( CommandHandler handler )
|
||||
public GeneralModule(CommandHandler handler)
|
||||
{
|
||||
_handler = handler;
|
||||
}
|
||||
@@ -65,7 +60,7 @@ namespace _04_interactions_framework.Modules
|
||||
|
||||
// Message Commands can only have one parameter, which must be a type of SocketMessage
|
||||
[MessageCommand("Delete")]
|
||||
[RequireOwner]
|
||||
[Attributes.RequireOwner]
|
||||
public async Task DeleteMesage(IMessage message)
|
||||
{
|
||||
await message.DeleteAsync();
|
||||
30
samples/InteractionFramework/Modules/MessageCommandModule.cs
Normal file
30
samples/InteractionFramework/Modules/MessageCommandModule.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using Discord;
|
||||
using Discord.Interactions;
|
||||
using Discord.WebSocket;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace InteractionFramework.Modules
|
||||
{
|
||||
// A transient module for executing commands. This module will NOT keep any information after the command is executed.
|
||||
internal class MessageCommandModule : InteractionModuleBase<SocketInteractionContext<SocketMessageCommand>>
|
||||
{
|
||||
// Pins a message in the channel it is in.
|
||||
[MessageCommand("pin")]
|
||||
public async Task PinMessageAsync(IMessage message)
|
||||
{
|
||||
// make a safety cast to check if the message is ISystem- or IUserMessage
|
||||
if (message is not IUserMessage userMessage)
|
||||
await RespondAsync(text: ":x: You cant pin system messages!");
|
||||
|
||||
// if the pins in this channel are equal to or above 50, no more messages can be pinned.
|
||||
else if ((await Context.Channel.GetPinnedMessagesAsync()).Count >= 50)
|
||||
await RespondAsync(text: ":x: You cant pin any more messages, the max has already been reached in this channel!");
|
||||
|
||||
else
|
||||
{
|
||||
await userMessage.PinAsync();
|
||||
await RespondAsync(":white_check_mark: Successfully pinned message!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
51
samples/InteractionFramework/Modules/SlashCommandModule.cs
Normal file
51
samples/InteractionFramework/Modules/SlashCommandModule.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using Discord;
|
||||
using Discord.Interactions;
|
||||
using Discord.WebSocket;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace InteractionFramework.Modules
|
||||
{
|
||||
public enum Hobby
|
||||
{
|
||||
Gaming,
|
||||
|
||||
Art,
|
||||
|
||||
Reading
|
||||
}
|
||||
|
||||
// A transient module for executing commands. This module will NOT keep any information after the command is executed.
|
||||
class SlashCommandModule : InteractionModuleBase<SocketInteractionContext<SocketSlashCommand>>
|
||||
{
|
||||
// Will be called before execution. Here you can populate several entities you may want to retrieve before executing a command.
|
||||
// I.E. database objects
|
||||
public override void BeforeExecute(ICommandInfo command)
|
||||
{
|
||||
// Anything
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
// Will be called after execution
|
||||
public override void AfterExecute(ICommandInfo command)
|
||||
{
|
||||
// Anything
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
[SlashCommand("ping", "Pings the bot and returns its latency.")]
|
||||
public async Task GreetUserAsync()
|
||||
=> await RespondAsync(text: $":ping_pong: It took me {Context.Client.Latency}ms to respond to you!", ephemeral: true);
|
||||
|
||||
[SlashCommand("hobby", "Choose your hobby from the list!")]
|
||||
public async Task ChooseAsync(Hobby hobby)
|
||||
=> await RespondAsync(text: $":thumbsup: Your hobby is: {hobby}.");
|
||||
|
||||
[SlashCommand("bitrate", "Gets the bitrate of a specific voice channel.")]
|
||||
public async Task GetBitrateAsync([ChannelTypes(ChannelType.Voice, ChannelType.Stage)] IChannel channel)
|
||||
{
|
||||
var voiceChannel = channel as IVoiceChannel;
|
||||
await RespondAsync(text: $"This voice channel has a bitrate of {voiceChannel.Bitrate}");
|
||||
}
|
||||
}
|
||||
}
|
||||
17
samples/InteractionFramework/Modules/UserCommandModule.cs
Normal file
17
samples/InteractionFramework/Modules/UserCommandModule.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using Discord;
|
||||
using Discord.Interactions;
|
||||
using Discord.WebSocket;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace InteractionFramework.Modules
|
||||
{
|
||||
// A transient module for executing commands. This module will NOT keep any information after the command is executed.
|
||||
class UserCommandModule : InteractionModuleBase<SocketInteractionContext<SocketUserCommand>>
|
||||
{
|
||||
// This command will greet target user in the channel this was executed in.
|
||||
[UserCommand("greet")]
|
||||
public async Task GreetUserAsync(IUser user)
|
||||
=> await RespondAsync(text: $":wave: {Context.User} said hi to you, <@{user.Id}>!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,14 +4,14 @@ using Discord.WebSocket;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _04_interactions_framework
|
||||
namespace InteractionFramework
|
||||
{
|
||||
class Program
|
||||
{
|
||||
// Entry point of the program.
|
||||
static void Main ( string[] args )
|
||||
{
|
||||
// One of the more flexable ways to access the configuration data is to use the Microsoft's Configuration model,
|
||||
@@ -24,7 +24,7 @@ namespace _04_interactions_framework
|
||||
RunAsync(config).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
static async Task RunAsync (IConfiguration configuration )
|
||||
static async Task RunAsync (IConfiguration configuration)
|
||||
{
|
||||
// Dependency injection is a key part of the Interactions framework but it needs to be disposed at the end of the app's lifetime.
|
||||
using var services = ConfigureServices(configuration);
|
||||
@@ -64,14 +64,12 @@ namespace _04_interactions_framework
|
||||
}
|
||||
|
||||
static ServiceProvider ConfigureServices ( IConfiguration configuration )
|
||||
{
|
||||
return new ServiceCollection()
|
||||
=> new ServiceCollection()
|
||||
.AddSingleton(configuration)
|
||||
.AddSingleton<DiscordSocketClient>()
|
||||
.AddSingleton(x => new InteractionService(x.GetRequiredService<DiscordSocketClient>()))
|
||||
.AddSingleton<CommandHandler>()
|
||||
.BuildServiceProvider();
|
||||
}
|
||||
|
||||
static bool IsDebug ( )
|
||||
{
|
||||
@@ -3,7 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<RootNamespace>_04_interactions_framework</RootNamespace>
|
||||
<RootNamespace>InteractionFramework</RootNamespace>
|
||||
<StartupObject></StartupObject>
|
||||
</PropertyGroup>
|
||||
|
||||
18
samples/ShardedClient/Modules/InteractionModule.cs
Normal file
18
samples/ShardedClient/Modules/InteractionModule.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using Discord.Interactions;
|
||||
using Discord.WebSocket;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ShardedClient.Modules
|
||||
{
|
||||
// A display of portability, which shows how minimal the difference between the 2 frameworks is.
|
||||
public class InteractionModule : InteractionModuleBase<ShardedInteractionContext<SocketSlashCommand>>
|
||||
{
|
||||
[SlashCommand("info", "Information about this shard.")]
|
||||
public async Task InfoAsync()
|
||||
{
|
||||
var msg = $@"Hi {Context.User}! There are currently {Context.Client.Shards.Count} shards!
|
||||
This guild is being served by shard number {Context.Client.GetShardFor(Context.Guild).ShardId}";
|
||||
await RespondAsync(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Threading.Tasks;
|
||||
using Discord.Commands;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _03_sharded_client.Modules
|
||||
namespace ShardedClient.Modules
|
||||
{
|
||||
// Remember to make your module reference the ShardedCommandContext
|
||||
public class PublicModule : ModuleBase<ShardedCommandContext>
|
||||
@@ -1,13 +1,14 @@
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.Interactions;
|
||||
using Discord.WebSocket;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using ShardedClient.Services;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using _03_sharded_client.Services;
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace _03_sharded_client
|
||||
namespace ShardedClient
|
||||
{
|
||||
// This is a minimal example of using Discord.Net's Sharded Client
|
||||
// The provided DiscordShardedClient class simplifies having multiple
|
||||
@@ -15,7 +16,11 @@ namespace _03_sharded_client
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
=> new Program().MainAsync().GetAwaiter().GetResult();
|
||||
=> new Program()
|
||||
.MainAsync()
|
||||
.GetAwaiter()
|
||||
.GetResult();
|
||||
|
||||
public async Task MainAsync()
|
||||
{
|
||||
// You specify the amount of shards you'd like to have with the
|
||||
@@ -40,6 +45,7 @@ namespace _03_sharded_client
|
||||
client.ShardReady += ReadyAsync;
|
||||
client.Log += LogAsync;
|
||||
|
||||
await services.GetRequiredService<InteractionHandlingService>().InitializeAsync();
|
||||
await services.GetRequiredService<CommandHandlingService>().InitializeAsync();
|
||||
|
||||
// Tokens should be considered secret data, and never hard-coded.
|
||||
@@ -51,13 +57,13 @@ namespace _03_sharded_client
|
||||
}
|
||||
|
||||
private ServiceProvider ConfigureServices(DiscordSocketConfig config)
|
||||
{
|
||||
return new ServiceCollection()
|
||||
=> new ServiceCollection()
|
||||
.AddSingleton(new DiscordShardedClient(config))
|
||||
.AddSingleton<CommandService>()
|
||||
.AddSingleton(x => new InteractionService(x.GetRequiredService<DiscordShardedClient>()))
|
||||
.AddSingleton<CommandHandlingService>()
|
||||
.AddSingleton<InteractionHandlingService>()
|
||||
.BuildServiceProvider();
|
||||
}
|
||||
|
||||
|
||||
private Task ReadyAsync(DiscordSocketClient shard)
|
||||
@@ -1,12 +1,12 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _03_sharded_client.Services
|
||||
namespace ShardedClient.Services
|
||||
{
|
||||
public class CommandHandlingService
|
||||
{
|
||||
@@ -33,7 +33,7 @@ namespace _03_sharded_client.Services
|
||||
public async Task MessageReceivedAsync(SocketMessage rawMessage)
|
||||
{
|
||||
// Ignore system messages, or messages from other bots
|
||||
if (!(rawMessage is SocketUserMessage message))
|
||||
if (rawMessage is not SocketUserMessage message)
|
||||
return;
|
||||
if (message.Source != MessageSource.User)
|
||||
return;
|
||||
@@ -59,7 +59,7 @@ namespace _03_sharded_client.Services
|
||||
return;
|
||||
|
||||
// the command failed, let's notify the user that something happened.
|
||||
await context.Channel.SendMessageAsync($"error: {result.ToString()}");
|
||||
await context.Channel.SendMessageAsync($"error: {result}");
|
||||
}
|
||||
|
||||
private Task LogAsync(LogMessage log)
|
||||
57
samples/ShardedClient/Services/InteractionHandlingService.cs
Normal file
57
samples/ShardedClient/Services/InteractionHandlingService.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using Discord;
|
||||
using Discord.Interactions;
|
||||
using Discord.WebSocket;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ShardedClient.Services
|
||||
{
|
||||
public class InteractionHandlingService
|
||||
{
|
||||
private readonly InteractionService _service;
|
||||
private readonly DiscordShardedClient _client;
|
||||
private readonly IServiceProvider _provider;
|
||||
|
||||
public InteractionHandlingService(IServiceProvider services)
|
||||
{
|
||||
_service = services.GetRequiredService<InteractionService>();
|
||||
_client = services.GetRequiredService<DiscordShardedClient>();
|
||||
_provider = services;
|
||||
|
||||
_service.Log += LogAsync;
|
||||
_client.InteractionCreated += OnInteractionAsync;
|
||||
// For examples on how to handle post execution,
|
||||
// see the InteractionFramework samples.
|
||||
}
|
||||
|
||||
// Register all modules, and add the commands from these modules to either guild or globally depending on the build state.
|
||||
public async Task InitializeAsync()
|
||||
{
|
||||
await _service.AddModulesAsync(typeof(InteractionHandlingService).Assembly, _provider);
|
||||
#if DEBUG
|
||||
await _service.AddCommandsToGuildAsync(_client.Guilds.First(x => x.Id == 1));
|
||||
#else
|
||||
await _service.AddCommandsGloballyAsync();
|
||||
#endif
|
||||
}
|
||||
|
||||
private async Task OnInteractionAsync(SocketInteraction interaction)
|
||||
{
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
var context = new ShardedInteractionContext(_client, interaction);
|
||||
await _service.ExecuteCommandAsync(context, _provider);
|
||||
});
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Task LogAsync(LogMessage log)
|
||||
{
|
||||
Console.WriteLine(log.ToString());
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<RootNamespace>ShardedClient</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -11,6 +12,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Discord.Net.Commands\Discord.Net.Commands.csproj" />
|
||||
<ProjectReference Include="..\..\src\Discord.Net.Interactions\Discord.Net.Interactions.csproj" />
|
||||
<ProjectReference Include="..\..\src\Discord.Net.WebSocket\Discord.Net.WebSocket.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using _02_commands_framework.Services;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using TextCommandFramework.Services;
|
||||
|
||||
namespace _02_commands_framework.Modules
|
||||
namespace TextCommandFramework.Modules
|
||||
{
|
||||
// Modules must be public and inherit from an IModuleBase
|
||||
public class PublicModule : ModuleBase<SocketCommandContext>
|
||||
@@ -1,14 +1,14 @@
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Discord;
|
||||
using Discord.WebSocket;
|
||||
using Discord.Commands;
|
||||
using _02_commands_framework.Services;
|
||||
using TextCommandFramework.Services;
|
||||
|
||||
namespace _02_commands_framework
|
||||
namespace TextCommandFramework
|
||||
{
|
||||
// This is a minimal example of using Discord.Net's command
|
||||
// framework - by no means does it show everything the framework
|
||||
@@ -1,12 +1,12 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _02_commands_framework.Services
|
||||
namespace TextCommandFramework.Services
|
||||
{
|
||||
public class CommandHandlingService
|
||||
{
|
||||
@@ -36,21 +36,24 @@ namespace _02_commands_framework.Services
|
||||
public async Task MessageReceivedAsync(SocketMessage rawMessage)
|
||||
{
|
||||
// Ignore system messages, or messages from other bots
|
||||
if (!(rawMessage is SocketUserMessage message)) return;
|
||||
if (message.Source != MessageSource.User) return;
|
||||
if (!(rawMessage is SocketUserMessage message))
|
||||
return;
|
||||
if (message.Source != MessageSource.User)
|
||||
return;
|
||||
|
||||
// This value holds the offset where the prefix ends
|
||||
var argPos = 0;
|
||||
// Perform prefix check. You may want to replace this with
|
||||
// (!message.HasCharPrefix('!', ref argPos))
|
||||
// for a more traditional command format like !help.
|
||||
if (!message.HasMentionPrefix(_discord.CurrentUser, ref argPos)) return;
|
||||
if (!message.HasMentionPrefix(_discord.CurrentUser, ref argPos))
|
||||
return;
|
||||
|
||||
var context = new SocketCommandContext(_discord, message);
|
||||
// Perform the execution of the command. In this method,
|
||||
// the command service will perform precondition and parsing check
|
||||
// then execute the command if one is matched.
|
||||
await _commands.ExecuteAsync(context, argPos, _services);
|
||||
await _commands.ExecuteAsync(context, argPos, _services);
|
||||
// Note that normally a result will be returned by this format, but here
|
||||
// we will handle the result in CommandExecutedAsync,
|
||||
}
|
||||
@@ -2,7 +2,7 @@ using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _02_commands_framework.Services
|
||||
namespace TextCommandFramework.Services
|
||||
{
|
||||
public class PictureService
|
||||
{
|
||||
@@ -3,7 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<RootNamespace>_03_sharded_client</RootNamespace>
|
||||
<RootNamespace>TextCommandFramework</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -2,7 +2,7 @@ using Discord;
|
||||
using Discord.Webhook;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _04_webhook_client
|
||||
namespace WebHookClient
|
||||
{
|
||||
// This is a minimal example of using Discord.Net's Webhook Client
|
||||
// Webhooks are send-only components of Discord that allow you to make a POST request
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
<RootNamespace>_04_webhook_client</RootNamespace>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<RootNamespace>WebHookClient</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
74
samples/_idn/Inspector.cs
Normal file
74
samples/_idn/Inspector.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace Idn
|
||||
{
|
||||
public static class Inspector
|
||||
{
|
||||
public static string Inspect(object value)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
if (value != null)
|
||||
{
|
||||
var type = value.GetType().GetTypeInfo();
|
||||
builder.AppendLine($"[{type.Namespace}.{type.Name}]");
|
||||
builder.AppendLine($"{InspectProperty(value)}");
|
||||
|
||||
if (value is IEnumerable)
|
||||
{
|
||||
var items = (value as IEnumerable).Cast<object>().ToArray();
|
||||
if (items.Length > 0)
|
||||
{
|
||||
builder.AppendLine();
|
||||
foreach (var item in items)
|
||||
builder.AppendLine($"- {InspectProperty(item)}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var groups = type.GetProperties(BindingFlags.Instance | BindingFlags.Public)
|
||||
.Where(x => x.GetIndexParameters().Length == 0)
|
||||
.GroupBy(x => x.Name)
|
||||
.OrderBy(x => x.Key)
|
||||
.ToArray();
|
||||
if (groups.Length > 0)
|
||||
{
|
||||
builder.AppendLine();
|
||||
int pad = groups.Max(x => x.Key.Length) + 1;
|
||||
foreach (var group in groups)
|
||||
builder.AppendLine($"{group.Key.PadRight(pad, ' ')}{InspectProperty(group.First().GetValue(value))}");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
builder.AppendLine("null");
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
private static string InspectProperty(object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
return "null";
|
||||
|
||||
var type = obj.GetType();
|
||||
|
||||
var debuggerDisplay = type.GetProperty("DebuggerDisplay", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
if (debuggerDisplay != null)
|
||||
return debuggerDisplay.GetValue(obj).ToString();
|
||||
|
||||
var toString = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
|
||||
.Where(x => x.Name == "ToString" && x.DeclaringType != typeof(object))
|
||||
.FirstOrDefault();
|
||||
if (toString != null)
|
||||
return obj.ToString();
|
||||
|
||||
var count = type.GetProperty("Count", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
if (count != null)
|
||||
return $"[{count.GetValue(obj)} Items]";
|
||||
|
||||
return obj.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
152
samples/_idn/Program.cs
Normal file
152
samples/_idn/Program.cs
Normal file
@@ -0,0 +1,152 @@
|
||||
using Discord;
|
||||
using Discord.WebSocket;
|
||||
using Microsoft.CodeAnalysis.CSharp.Scripting;
|
||||
using Microsoft.CodeAnalysis.Scripting;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Idn
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static readonly string[] Imports =
|
||||
{
|
||||
"System",
|
||||
"System.Collections.Generic",
|
||||
"System.Linq",
|
||||
"System.Threading.Tasks",
|
||||
"System.Diagnostics",
|
||||
"System.IO",
|
||||
"Discord",
|
||||
"Discord.Rest",
|
||||
"Discord.WebSocket",
|
||||
"idn"
|
||||
};
|
||||
|
||||
static async Task Main(string[] args)
|
||||
{
|
||||
var token = File.ReadAllText("token.ignore");
|
||||
var client = new DiscordSocketClient(new DiscordSocketConfig { LogLevel = LogSeverity.Debug });
|
||||
var logQueue = new ConcurrentQueue<LogMessage>();
|
||||
var logCancelToken = new CancellationTokenSource();
|
||||
int presenceUpdates = 0;
|
||||
|
||||
client.Log += msg =>
|
||||
{
|
||||
logQueue.Enqueue(msg);
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
Console.CancelKeyPress += (_ev, _s) =>
|
||||
{
|
||||
logCancelToken.Cancel();
|
||||
};
|
||||
|
||||
var logTask = Task.Run(async () =>
|
||||
{
|
||||
var fs = new FileStream("idn.log", FileMode.Append);
|
||||
var logStringBuilder = new StringBuilder(200);
|
||||
string logString = "";
|
||||
|
||||
byte[] helloBytes = Encoding.UTF8.GetBytes($"### new log session: {DateTime.Now} ###\n\n");
|
||||
await fs.WriteAsync(helloBytes);
|
||||
|
||||
while (!logCancelToken.IsCancellationRequested)
|
||||
{
|
||||
if (logQueue.TryDequeue(out var msg))
|
||||
{
|
||||
if (msg.Message?.IndexOf("PRESENCE_UPDATE)") > 0)
|
||||
{
|
||||
presenceUpdates++;
|
||||
continue;
|
||||
}
|
||||
|
||||
_ = msg.ToString(builder: logStringBuilder);
|
||||
logStringBuilder.AppendLine();
|
||||
logString = logStringBuilder.ToString();
|
||||
|
||||
Debug.Write(logString, "DNET");
|
||||
await fs.WriteAsync(Encoding.UTF8.GetBytes(logString));
|
||||
}
|
||||
await fs.FlushAsync();
|
||||
try
|
||||
{
|
||||
await Task.Delay(100, logCancelToken.Token);
|
||||
}
|
||||
finally { }
|
||||
}
|
||||
|
||||
byte[] goodbyeBytes = Encoding.UTF8.GetBytes($"#!! end log session: {DateTime.Now} !!#\n\n\n");
|
||||
await fs.WriteAsync(goodbyeBytes);
|
||||
await fs.DisposeAsync();
|
||||
});
|
||||
|
||||
await client.LoginAsync(TokenType.Bot, token);
|
||||
await client.StartAsync();
|
||||
|
||||
var options = ScriptOptions.Default
|
||||
.AddReferences(GetAssemblies().ToArray())
|
||||
.AddImports(Imports);
|
||||
|
||||
var globals = new ScriptGlobals
|
||||
{
|
||||
Client = client,
|
||||
PUCount = -1,
|
||||
};
|
||||
|
||||
while (true)
|
||||
{
|
||||
Console.Write("> ");
|
||||
string input = Console.ReadLine();
|
||||
|
||||
if (input == "quit!")
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
object eval;
|
||||
try
|
||||
{
|
||||
globals.PUCount = presenceUpdates;
|
||||
eval = await CSharpScript.EvaluateAsync(input, options, globals);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
eval = e;
|
||||
}
|
||||
Console.WriteLine(Inspector.Inspect(eval));
|
||||
}
|
||||
|
||||
await client.StopAsync();
|
||||
client.Dispose();
|
||||
logCancelToken.Cancel();
|
||||
try
|
||||
{ await logTask; }
|
||||
finally { Console.WriteLine("goodbye!"); }
|
||||
}
|
||||
|
||||
static IEnumerable<Assembly> GetAssemblies()
|
||||
{
|
||||
var Assemblies = Assembly.GetEntryAssembly().GetReferencedAssemblies();
|
||||
foreach (var a in Assemblies)
|
||||
{
|
||||
var asm = Assembly.Load(a);
|
||||
yield return asm;
|
||||
}
|
||||
yield return Assembly.GetEntryAssembly();
|
||||
}
|
||||
|
||||
public class ScriptGlobals
|
||||
{
|
||||
public DiscordSocketClient Client { get; set; }
|
||||
public int PUCount { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
16
samples/_idn/idn.csproj
Normal file
16
samples/_idn/idn.csproj
Normal file
@@ -0,0 +1,16 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="3.11.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Discord.Net.WebSocket\Discord.Net.WebSocket.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
1
samples/_idn/logview.ps1
Normal file
1
samples/_idn/logview.ps1
Normal file
@@ -0,0 +1 @@
|
||||
Get-Content .\bin\Debug\netcoreapp3.1\idn.log -Tail 3 -Wait
|
||||
@@ -1,17 +1,17 @@
|
||||
using Discord;
|
||||
using Discord.WebSocket;
|
||||
using Microsoft.CodeAnalysis.CSharp.Scripting;
|
||||
using Microsoft.CodeAnalysis.Scripting;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.CodeAnalysis.CSharp.Scripting;
|
||||
using Microsoft.CodeAnalysis.Scripting;
|
||||
using Discord;
|
||||
using Discord.WebSocket;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading;
|
||||
using System.Text;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Idn
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using JetBrains.Annotations;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace Discord.Net.Examples.Core.Entities.Channels
|
||||
{
|
||||
@@ -11,8 +11,10 @@ namespace Discord.Net.Examples.Core.Entities.Channels
|
||||
|
||||
public async Task MuteRoleAsync(IRole role, IGuildChannel channel)
|
||||
{
|
||||
if (role == null) throw new ArgumentNullException(nameof(role));
|
||||
if (channel == null) throw new ArgumentNullException(nameof(channel));
|
||||
if (role == null)
|
||||
throw new ArgumentNullException(nameof(role));
|
||||
if (channel == null)
|
||||
throw new ArgumentNullException(nameof(channel));
|
||||
|
||||
// Fetches the previous overwrite and bail if one is found
|
||||
var previousOverwrite = channel.GetPermissionOverwrite(role);
|
||||
@@ -29,8 +31,10 @@ namespace Discord.Net.Examples.Core.Entities.Channels
|
||||
|
||||
public async Task MuteUserAsync(IGuildUser user, IGuildChannel channel)
|
||||
{
|
||||
if (user == null) throw new ArgumentNullException(nameof(user));
|
||||
if (channel == null) throw new ArgumentNullException(nameof(channel));
|
||||
if (user == null)
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
if (channel == null)
|
||||
throw new ArgumentNullException(nameof(channel));
|
||||
|
||||
// Fetches the previous overwrite and bail if one is found
|
||||
var previousOverwrite = channel.GetPermissionOverwrite(user);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using JetBrains.Annotations;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace Discord.Net.Examples.Core.Entities.Channels
|
||||
{
|
||||
@@ -90,7 +90,7 @@ namespace Discord.Net.Examples.Core.Entities.Channels
|
||||
#region SendFileAsync.FilePath.EmbeddedImage
|
||||
|
||||
await channel.SendFileAsync("b1nzy.jpg",
|
||||
embed: new EmbedBuilder {ImageUrl = "attachment://b1nzy.jpg"}.Build());
|
||||
embed: new EmbedBuilder { ImageUrl = "attachment://b1nzy.jpg" }.Build());
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -99,13 +99,14 @@ namespace Discord.Net.Examples.Core.Entities.Channels
|
||||
|
||||
using (var b1nzyStream = await httpClient.GetStreamAsync("https://example.com/b1nzy"))
|
||||
await channel.SendFileAsync(b1nzyStream, "b1nzy.jpg",
|
||||
embed: new EmbedBuilder {ImageUrl = "attachment://b1nzy.jpg"}.Build());
|
||||
embed: new EmbedBuilder { ImageUrl = "attachment://b1nzy.jpg" }.Build());
|
||||
|
||||
#endregion
|
||||
|
||||
#region EnterTypingState
|
||||
|
||||
using (channel.EnterTypingState()) await LongRunningAsync();
|
||||
using (channel.EnterTypingState())
|
||||
await LongRunningAsync();
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using JetBrains.Annotations;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace Discord.Net.Examples.Core.Entities.Users
|
||||
{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using Discord.WebSocket;
|
||||
using JetBrains.Annotations;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Discord.WebSocket;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace Discord.Net.Examples.WebSocket
|
||||
{
|
||||
@@ -74,7 +74,7 @@ namespace Discord.Net.Examples.WebSocket
|
||||
|
||||
#region MessageReceived
|
||||
|
||||
private readonly ulong[] _targetUserIds = {168693960628371456, 53905483156684800};
|
||||
private readonly ulong[] _targetUserIds = { 168693960628371456, 53905483156684800 };
|
||||
|
||||
public void HookMessageReceived(BaseSocketClient client)
|
||||
=> client.MessageReceived += HandleMessageReceived;
|
||||
@@ -82,9 +82,11 @@ namespace Discord.Net.Examples.WebSocket
|
||||
public Task HandleMessageReceived(SocketMessage message)
|
||||
{
|
||||
// check if the message is a user message as opposed to a system message (e.g. Clyde, pins, etc.)
|
||||
if (!(message is SocketUserMessage userMessage)) return Task.CompletedTask;
|
||||
if (!(message is SocketUserMessage userMessage))
|
||||
return Task.CompletedTask;
|
||||
// check if the message origin is a guild message channel
|
||||
if (!(userMessage.Channel is SocketTextChannel textChannel)) return Task.CompletedTask;
|
||||
if (!(userMessage.Channel is SocketTextChannel textChannel))
|
||||
return Task.CompletedTask;
|
||||
// check if the target user was mentioned
|
||||
var targetUsers = userMessage.MentionedUsers.Where(x => _targetUserIds.Contains(x.Id));
|
||||
foreach (var targetUser in targetUsers)
|
||||
@@ -103,7 +105,8 @@ namespace Discord.Net.Examples.WebSocket
|
||||
public async Task HandleMessageDelete(Cacheable<IMessage, ulong> cachedMessage, Cacheable<IMessageChannel, ulong> cachedChannel)
|
||||
{
|
||||
// check if the message exists in cache; if not, we cannot report what was removed
|
||||
if (!cachedMessage.HasValue) return;
|
||||
if (!cachedMessage.HasValue)
|
||||
return;
|
||||
// gets or downloads the channel if it's not in the cache
|
||||
IMessageChannel channel = await cachedChannel.GetOrDownloadAsync();
|
||||
var message = cachedMessage.Value;
|
||||
|
||||
Reference in New Issue
Block a user