├── .gitignore
├── Discord.Net-Example.sln
├── README.md
├── example.png
└── src
├── Discord.Net-Example.csproj
├── Modules
├── ExampleModule.cs
├── MathModule.cs
└── ModeratorModule.cs
├── Program.cs
├── Services
├── DiscordStartupService.cs
└── InteractionHandlingService.cs
└── Utility
└── LogHelper.cs
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | bld/
21 | [Bb]in/
22 | [Oo]bj/
23 | [Ll]og/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | artifacts/
46 |
47 | *_i.c
48 | *_p.c
49 | *_i.h
50 | *.ilk
51 | *.meta
52 | *.obj
53 | *.pch
54 | *.pdb
55 | *.pgc
56 | *.pgd
57 | *.rsp
58 | *.sbr
59 | *.tlb
60 | *.tli
61 | *.tlh
62 | *.tmp
63 | *.tmp_proj
64 | *.log
65 | *.vspscc
66 | *.vssscc
67 | .builds
68 | *.pidb
69 | *.svclog
70 | *.scc
71 |
72 | # Chutzpah Test files
73 | _Chutzpah*
74 |
75 | # Visual C++ cache files
76 | ipch/
77 | *.aps
78 | *.ncb
79 | *.opendb
80 | *.opensdf
81 | *.sdf
82 | *.cachefile
83 | *.VC.db
84 | *.VC.VC.opendb
85 |
86 | # Visual Studio profiler
87 | *.psess
88 | *.vsp
89 | *.vspx
90 | *.sap
91 |
92 | # TFS 2012 Local Workspace
93 | $tf/
94 |
95 | # Guidance Automation Toolkit
96 | *.gpState
97 |
98 | # ReSharper is a .NET coding add-in
99 | _ReSharper*/
100 | *.[Rr]e[Ss]harper
101 | *.DotSettings.user
102 |
103 | # JustCode is a .NET coding add-in
104 | .JustCode
105 |
106 | # TeamCity is a build add-in
107 | _TeamCity*
108 |
109 | # DotCover is a Code Coverage Tool
110 | *.dotCover
111 |
112 | # NCrunch
113 | _NCrunch_*
114 | .*crunch*.local.xml
115 | nCrunchTemp_*
116 |
117 | # MightyMoose
118 | *.mm.*
119 | AutoTest.Net/
120 |
121 | # Web workbench (sass)
122 | .sass-cache/
123 |
124 | # Installshield output folder
125 | [Ee]xpress/
126 |
127 | # DocProject is a documentation generator add-in
128 | DocProject/buildhelp/
129 | DocProject/Help/*.HxT
130 | DocProject/Help/*.HxC
131 | DocProject/Help/*.hhc
132 | DocProject/Help/*.hhk
133 | DocProject/Help/*.hhp
134 | DocProject/Help/Html2
135 | DocProject/Help/html
136 |
137 | # Click-Once directory
138 | publish/
139 |
140 | # Publish Web Output
141 | *.[Pp]ublish.xml
142 | *.azurePubxml
143 | # TODO: Comment the next line if you want to checkin your web deploy settings
144 | # but database connection strings (with potential passwords) will be unencrypted
145 | *.pubxml
146 | *.publishproj
147 |
148 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
149 | # checkin your Azure Web App publish settings, but sensitive information contained
150 | # in these scripts will be unencrypted
151 | PublishScripts/
152 |
153 | # NuGet Packages
154 | *.nupkg
155 | # The packages folder can be ignored because of Package Restore
156 | **/packages/*
157 | # except build/, which is used as an MSBuild target.
158 | !**/packages/build/
159 | # Uncomment if necessary however generally it will be regenerated when needed
160 | #!**/packages/repositories.config
161 | # NuGet v3's project.json files produces more ignoreable files
162 | *.nuget.props
163 | *.nuget.targets
164 |
165 | # Microsoft Azure Build Output
166 | csx/
167 | *.build.csdef
168 |
169 | # Microsoft Azure Emulator
170 | ecf/
171 | rcf/
172 |
173 | # Windows Store app package directories and files
174 | AppPackages/
175 | BundleArtifacts/
176 | Package.StoreAssociation.xml
177 | _pkginfo.txt
178 |
179 | # Visual Studio cache files
180 | # files ending in .cache can be ignored
181 | *.[Cc]ache
182 | # but keep track of directories ending in .cache
183 | !*.[Cc]ache/
184 |
185 | # Others
186 | ClientBin/
187 | ~$*
188 | *~
189 | *.dbmdl
190 | *.dbproj.schemaview
191 | *.pfx
192 | *.publishsettings
193 | node_modules/
194 | orleans.codegen.cs
195 |
196 | # Since there are multiple workflows, uncomment next line to ignore bower_components
197 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
198 | #bower_components/
199 |
200 | # RIA/Silverlight projects
201 | Generated_Code/
202 |
203 | # Backup & report files from converting an old project file
204 | # to a newer Visual Studio version. Backup files are not needed,
205 | # because we have git ;-)
206 | _UpgradeReport_Files/
207 | Backup*/
208 | UpgradeLog*.XML
209 | UpgradeLog*.htm
210 |
211 | # SQL Server files
212 | *.mdf
213 | *.ldf
214 |
215 | # Business Intelligence projects
216 | *.rdl.data
217 | *.bim.layout
218 | *.bim_*.settings
219 |
220 | # Microsoft Fakes
221 | FakesAssemblies/
222 |
223 | # GhostDoc plugin setting file
224 | *.GhostDoc.xml
225 |
226 | # Node.js Tools for Visual Studio
227 | .ntvs_analysis.dat
228 |
229 | # Visual Studio 6 build log
230 | *.plg
231 |
232 | # Visual Studio 6 workspace options file
233 | *.opt
234 |
235 | # Visual Studio LightSwitch build output
236 | **/*.HTMLClient/GeneratedArtifacts
237 | **/*.DesktopClient/GeneratedArtifacts
238 | **/*.DesktopClient/ModelManifest.xml
239 | **/*.Server/GeneratedArtifacts
240 | **/*.Server/ModelManifest.xml
241 | _Pvt_Extensions
242 |
243 | # Paket dependency manager
244 | .paket/paket.exe
245 | paket-files/
246 |
247 | # FAKE - F# Make
248 | .fake/
249 |
250 | # JetBrains Rider
251 | .idea/
252 | *.sln.iml
253 |
--------------------------------------------------------------------------------
/Discord.Net-Example.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.4.33213.308
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net-Example", "src\Discord.Net-Example.csproj", "{8F39F095-C020-496B-A0E8-ACBD70D39A7C}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A0D75958-6C7C-45ED-9254-A671CE25A8E9}"
9 | ProjectSection(SolutionItems) = preProject
10 | .gitignore = .gitignore
11 | README.md = README.md
12 | EndProjectSection
13 | EndProject
14 | Global
15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
16 | Debug|Any CPU = Debug|Any CPU
17 | Debug|x64 = Debug|x64
18 | Debug|x86 = Debug|x86
19 | Release|Any CPU = Release|Any CPU
20 | Release|x64 = Release|x64
21 | Release|x86 = Release|x86
22 | EndGlobalSection
23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
24 | {8F39F095-C020-496B-A0E8-ACBD70D39A7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25 | {8F39F095-C020-496B-A0E8-ACBD70D39A7C}.Debug|Any CPU.Build.0 = Debug|Any CPU
26 | {8F39F095-C020-496B-A0E8-ACBD70D39A7C}.Debug|x64.ActiveCfg = Debug|Any CPU
27 | {8F39F095-C020-496B-A0E8-ACBD70D39A7C}.Debug|x64.Build.0 = Debug|Any CPU
28 | {8F39F095-C020-496B-A0E8-ACBD70D39A7C}.Debug|x86.ActiveCfg = Debug|Any CPU
29 | {8F39F095-C020-496B-A0E8-ACBD70D39A7C}.Debug|x86.Build.0 = Debug|Any CPU
30 | {8F39F095-C020-496B-A0E8-ACBD70D39A7C}.Release|Any CPU.ActiveCfg = Release|Any CPU
31 | {8F39F095-C020-496B-A0E8-ACBD70D39A7C}.Release|Any CPU.Build.0 = Release|Any CPU
32 | {8F39F095-C020-496B-A0E8-ACBD70D39A7C}.Release|x64.ActiveCfg = Release|Any CPU
33 | {8F39F095-C020-496B-A0E8-ACBD70D39A7C}.Release|x64.Build.0 = Release|Any CPU
34 | {8F39F095-C020-496B-A0E8-ACBD70D39A7C}.Release|x86.ActiveCfg = Release|Any CPU
35 | {8F39F095-C020-496B-A0E8-ACBD70D39A7C}.Release|x86.Build.0 = Release|Any CPU
36 | EndGlobalSection
37 | GlobalSection(SolutionProperties) = preSolution
38 | HideSolutionNode = FALSE
39 | EndGlobalSection
40 | GlobalSection(ExtensibilityGlobals) = postSolution
41 | SolutionGuid = {332350DE-ED2F-42E1-92F1-A8B85545307F}
42 | EndGlobalSection
43 | EndGlobal
44 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Last updated for `3.10.0`
2 |
3 | ## Discord.Net-Example
4 | An example bot for [Discord.Net](https://github.com/discord-net/Discord.Net). If you would like a more specific example for your use case, ask for help in the [Discord API](https://discordapp.com/invite/discord-api) server with your request or [open a discussion](https://github.com/discord-net/Discord.Net/discussions/categories/q-a).
5 |
6 | This example assumes you have an `_config.yml` file that contains `token: value` saved in the build's root directory.
7 |
8 | ### Other Examples
9 | - [Patek](https://github.com/foxbot/patek) by foxbot
10 | - [Dogey](https://github.com/Aux/Dogey) by Auxesis
11 |
--------------------------------------------------------------------------------
/example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aux/Discord.Net-Example/83ad9128a0765e0ae3d29cdc5f08b338c4dbc743/example.png
--------------------------------------------------------------------------------
/src/Discord.Net-Example.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net7.0
6 | Example
7 | latest
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/Modules/ExampleModule.cs:
--------------------------------------------------------------------------------
1 | using Discord;
2 | using Discord.Interactions;
3 | using Discord.WebSocket;
4 | using System.Threading.Tasks;
5 |
6 | namespace Example.Modules
7 | {
8 | public class ExampleModule : InteractionModuleBase
9 | {
10 | [SlashCommand("say", "Make the bot say something.")]
11 | [RequireUserPermission(GuildPermission.Administrator)]
12 | public Task Say(string text)
13 | => ReplyAsync(text);
14 |
15 | [SlashCommand("nick", "Change a user's nickname to the specified text")]
16 | [RequireContext(ContextType.Guild)]
17 | [RequireUserPermission(GuildPermission.ManageNicknames)]
18 | [RequireBotPermission(GuildPermission.ChangeNickname)]
19 | public async Task Nick(string name, SocketGuildUser user = null)
20 | {
21 | user ??= (SocketGuildUser)Context.User;
22 | await user.ModifyAsync(x => x.Nickname = name);
23 | await RespondAsync($"{user.Mention} I changed your name to **{name}**");
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/Modules/MathModule.cs:
--------------------------------------------------------------------------------
1 | using Discord.Interactions;
2 | using System;
3 | using System.Threading.Tasks;
4 |
5 | namespace Example.Modules
6 | {
7 | public class MathModule : InteractionModuleBase
8 | {
9 | [SlashCommand("isnumber", "Check if the input text is a number.")]
10 | public Task IsNumber(double number)
11 | => RespondAsync($"The text {number} is a number!", ephemeral: true);
12 |
13 | [SlashCommand("multiply", "Get the product of two numbers.")]
14 | public async Task Multiply(int a, int b)
15 | {
16 | long product = Math.BigMul(a, b);
17 | await RespondAsync($"The product of `{a} * {b}` is `{product}`.", ephemeral: true);
18 | }
19 |
20 | [SlashCommand("square", "Get the square root of a number.")]
21 | public async Task Square(double number)
22 | {
23 | double sqrt = Math.Sqrt(number);
24 | await RespondAsync($"The square root of `{number}` is `{sqrt}`.", ephemeral: true);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/Modules/ModeratorModule.cs:
--------------------------------------------------------------------------------
1 | using Discord;
2 | using Discord.Interactions;
3 | using Discord.WebSocket;
4 | using System.Threading.Tasks;
5 |
6 | namespace Example.Modules
7 | {
8 | public class ModeratorModule : InteractionModuleBase
9 | {
10 | [SlashCommand("kick", "Kick the specified user.")]
11 | [RequireUserPermission(GuildPermission.KickMembers)]
12 | [RequireBotPermission(GuildPermission.KickMembers)]
13 | public async Task Kick(SocketGuildUser user)
14 | {
15 | await ReplyAsync($"cya {user.Mention} :wave:");
16 | await user.KickAsync();
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/Program.cs:
--------------------------------------------------------------------------------
1 | using Discord.Interactions;
2 | using Discord.WebSocket;
3 | using Example.Services;
4 | using Microsoft.Extensions.Configuration;
5 | using Microsoft.Extensions.DependencyInjection;
6 | using Microsoft.Extensions.Hosting;
7 |
8 | using IHost host = Host.CreateDefaultBuilder(args)
9 | .ConfigureAppConfiguration(config =>
10 | {
11 | config.AddYamlFile("_config.yml", false); // Add the config file to IConfiguration variables
12 | })
13 | .ConfigureServices(services =>
14 | {
15 | services.AddSingleton(); // Add the discord client to services
16 | services.AddSingleton(); // Add the interaction service to services
17 | services.AddHostedService(); // Add the slash command handler
18 | services.AddHostedService(); // Add the discord startup service
19 | })
20 | .Build();
21 |
22 | await host.RunAsync();
--------------------------------------------------------------------------------
/src/Services/DiscordStartupService.cs:
--------------------------------------------------------------------------------
1 | using Discord;
2 | using Discord.WebSocket;
3 | using Microsoft.Extensions.Configuration;
4 | using Microsoft.Extensions.Hosting;
5 | using Microsoft.Extensions.Logging;
6 | using System.Threading;
7 | using System.Threading.Tasks;
8 |
9 | namespace Example.Services
10 | {
11 | public class DiscordStartupService : IHostedService
12 | {
13 | private readonly DiscordSocketClient _discord;
14 | private readonly IConfiguration _config;
15 | private readonly ILogger _logger;
16 |
17 | public DiscordStartupService(DiscordSocketClient discord, IConfiguration config, ILogger logger)
18 | {
19 | _discord = discord;
20 | _config = config;
21 | _logger = logger;
22 |
23 | _discord.Log += msg => LogHelper.OnLogAsync(_logger, msg);
24 | }
25 |
26 | public async Task StartAsync(CancellationToken cancellationToken)
27 | {
28 | await _discord.LoginAsync(TokenType.Bot, _config["token"]);
29 | await _discord.StartAsync();
30 | }
31 |
32 | public async Task StopAsync(CancellationToken cancellationToken)
33 | {
34 | await _discord.LogoutAsync();
35 | await _discord.StopAsync();
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/Services/InteractionHandlingService.cs:
--------------------------------------------------------------------------------
1 | using Discord;
2 | using Discord.Interactions;
3 | using Discord.WebSocket;
4 | using Microsoft.Extensions.Configuration;
5 | using Microsoft.Extensions.Hosting;
6 | using Microsoft.Extensions.Logging;
7 | using System;
8 | using System.Reflection;
9 | using System.Threading;
10 | using System.Threading.Tasks;
11 |
12 | namespace Example.Services
13 | {
14 | public class InteractionHandlingService : IHostedService
15 | {
16 | private readonly DiscordSocketClient _discord;
17 | private readonly InteractionService _interactions;
18 | private readonly IServiceProvider _services;
19 | private readonly IConfiguration _config;
20 | private readonly ILogger _logger;
21 |
22 | public InteractionHandlingService(
23 | DiscordSocketClient discord,
24 | InteractionService interactions,
25 | IServiceProvider services,
26 | IConfiguration config,
27 | ILogger logger)
28 | {
29 | _discord = discord;
30 | _interactions = interactions;
31 | _services = services;
32 | _config = config;
33 | _logger = logger;
34 |
35 | _interactions.Log += msg => LogHelper.OnLogAsync(_logger, msg);
36 | }
37 |
38 | public async Task StartAsync(CancellationToken cancellationToken)
39 | {
40 | _discord.Ready += () => _interactions.RegisterCommandsGloballyAsync(true);
41 | _discord.InteractionCreated += OnInteractionAsync;
42 |
43 | await _interactions.AddModulesAsync(Assembly.GetEntryAssembly(), _services);
44 | }
45 |
46 | public Task StopAsync(CancellationToken cancellationToken)
47 | {
48 | _interactions.Dispose();
49 | return Task.CompletedTask;
50 | }
51 |
52 | private async Task OnInteractionAsync(SocketInteraction interaction)
53 | {
54 | try
55 | {
56 | var context = new SocketInteractionContext(_discord, interaction);
57 | var result = await _interactions.ExecuteCommandAsync(context, _services);
58 |
59 | if (!result.IsSuccess)
60 | await context.Channel.SendMessageAsync(result.ToString());
61 | }
62 | catch
63 | {
64 | if (interaction.Type == InteractionType.ApplicationCommand)
65 | {
66 | await interaction.GetOriginalResponseAsync()
67 | .ContinueWith(msg => msg.Result.DeleteAsync());
68 | }
69 | }
70 | }
71 | }
72 | }
--------------------------------------------------------------------------------
/src/Utility/LogHelper.cs:
--------------------------------------------------------------------------------
1 | using Discord;
2 | using Microsoft.Extensions.Logging;
3 | using System.Threading.Tasks;
4 |
5 | namespace Example
6 | {
7 | public static class LogHelper
8 | {
9 | public static Task OnLogAsync(ILogger logger, LogMessage msg)
10 | {
11 | switch (msg.Severity)
12 | {
13 | case LogSeverity.Verbose:
14 | logger.LogInformation(msg.ToString());
15 | break;
16 |
17 | case LogSeverity.Info:
18 | logger.LogInformation(msg.ToString());
19 | break;
20 |
21 | case LogSeverity.Warning:
22 | logger.LogWarning(msg.ToString());
23 | break;
24 |
25 | case LogSeverity.Error:
26 | logger.LogError(msg.ToString());
27 | break;
28 |
29 | case LogSeverity.Critical:
30 | logger.LogCritical(msg.ToString());
31 | break;
32 | }
33 | return Task.CompletedTask;
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------