Initial commit
please bro
This commit is contained in:
commit
7920f56eb3
4
.editorconfig
Normal file
4
.editorconfig
Normal file
@ -0,0 +1,4 @@
|
||||
[*.cs]
|
||||
|
||||
# CS0618: Type or member is obsolete
|
||||
dotnet_diagnostic.CS0618.severity = silent
|
||||
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
11
.gitignore
vendored
Normal file
11
.gitignore
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
# visual studio files
|
||||
/Nerd's Teaser Bot/bin
|
||||
/Nerd's Teaser Bot/obj
|
||||
/.vs
|
||||
|
||||
*.csproj
|
||||
*.sln
|
||||
|
||||
# personal stuff
|
||||
/Nerd's Teaser Bot/Imports
|
||||
/Nerd's Teaser Bot/Misc/Hidden.cs
|
||||
7
Changelog.md
Normal file
7
Changelog.md
Normal file
@ -0,0 +1,7 @@
|
||||
# Nerd's Teaser Bot - Changelog
|
||||
## Version v3.05
|
||||
|
||||
+ Added `n;level rank` command
|
||||
+ Made a Github Repo for Nerd's Teaser Bot
|
||||
+ Newlines now are also interpreted by the changelog version detector as a version end
|
||||
+ Setting a user's level or xp no longer looks weird
|
||||
BIN
Nerd's Teaser Bot/Icon.ico
Normal file
BIN
Nerd's Teaser Bot/Icon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.1 MiB |
161
Nerd's Teaser Bot/Internals.cs
Normal file
161
Nerd's Teaser Bot/Internals.cs
Normal file
@ -0,0 +1,161 @@
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NerdsTeaserBot.Misc;
|
||||
using NerdsTeaserBot.Modules;
|
||||
using NerdsTeaserBot.Modules.Commands;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using static NerdsTeaserBot.Const;
|
||||
|
||||
namespace NerdsTeaserBot
|
||||
{
|
||||
public class Internals
|
||||
{
|
||||
internal static DiscordSocketClient client;
|
||||
internal static CommandService commands;
|
||||
internal static SocketCommandContext context;
|
||||
internal static SocketUserMessage message;
|
||||
internal static ServiceProvider services;
|
||||
|
||||
internal static DateTime upTime;
|
||||
|
||||
public static void Main() => RunBotAsync().GetAwaiter().GetResult();
|
||||
|
||||
public static async Task RunBotAsync()
|
||||
{
|
||||
if (File.Exists(Data.consts.Path)) Data.consts.Load();
|
||||
|
||||
commands = new(new()
|
||||
{
|
||||
CaseSensitiveCommands = false,
|
||||
DefaultRunMode = RunMode.Async,
|
||||
IgnoreExtraArgs = false,
|
||||
LogLevel = LogSeverity.Info,
|
||||
SeparatorChar = ' ',
|
||||
ThrowOnError = true,
|
||||
});
|
||||
client = new(new()
|
||||
{
|
||||
AlwaysAcknowledgeInteractions = true,
|
||||
AlwaysDownloadUsers = true,
|
||||
ConnectionTimeout = 10000,
|
||||
DefaultRetryMode = RetryMode.AlwaysFail,
|
||||
ExclusiveBulkDelete = true,
|
||||
GuildSubscriptions = true,
|
||||
LargeThreshold = 250,
|
||||
LogLevel = LogSeverity.Info,
|
||||
MaxWaitBetweenGuildAvailablesBeforeReady = 250,
|
||||
MessageCacheSize = 50,
|
||||
RateLimitPrecision = RateLimitPrecision.Millisecond,
|
||||
UseSystemClock = false,
|
||||
});
|
||||
services = new ServiceCollection().AddSingleton(client).AddSingleton(commands).BuildServiceProvider();
|
||||
|
||||
LoadBackground();
|
||||
LoadHandles();
|
||||
|
||||
await commands.AddModulesAsync(Assembly.GetEntryAssembly(), services);
|
||||
|
||||
await client.LoginAsync(TokenType.Bot, Hidden.token);
|
||||
await client.StartAsync();
|
||||
|
||||
upTime = DateTime.Now;
|
||||
|
||||
await Task.Delay(-1);
|
||||
}
|
||||
|
||||
internal static void LoadHandles()
|
||||
{
|
||||
// client.ChannelCreated += LogModule.ChannelCreatedHandler;
|
||||
|
||||
// client.ChannelDestroyed += LogModule.ChannelDeletedHandler;
|
||||
|
||||
// client.ChannelUpdated += LogModule.ChannelModifiedHandler;
|
||||
|
||||
client.InteractionCreated += ButtonModule.ButtonHandler;
|
||||
|
||||
client.JoinedGuild += BotModule.PermittedServerHandler;
|
||||
|
||||
client.Log += LogHandler;
|
||||
|
||||
// client.MessagesBulkDeleted += LogModule.MessagesPurgedHandler;
|
||||
|
||||
// client.MessageDeleted += LogModule.MessageDeletedHandler;
|
||||
|
||||
client.MessageReceived += MessageHandler;
|
||||
client.MessageReceived += ModmailModule.ModmailHandler;
|
||||
|
||||
// client.MessageUpdated += LogModule.MessageEditedHandler;
|
||||
|
||||
// client.RoleCreated += LogModule.RoleCreatedHandler;
|
||||
|
||||
// client.RoleDeleted += LogModule.RoleDeletedHandler;
|
||||
|
||||
// client.RoleUpdated += LogModule.RoleModifiedHandler;
|
||||
|
||||
// client.GuildUpdated += LogModule.GuildModifiedHandler;
|
||||
|
||||
// client.UserBanned += LogModule.UserBannedHandler;
|
||||
|
||||
// client.UserJoined += LogModule.UserJoinedHandler;
|
||||
client.UserJoined += MessagingModule.UserJoinedHandler;
|
||||
|
||||
// client.UserLeft += LogModule.UserLeftHandler;
|
||||
client.UserLeft += MessagingModule.UserLeftHandler;
|
||||
|
||||
// client.UserUnbanned += LogModule.UserUnbannedHandler;
|
||||
|
||||
// client.UserUpdated += LogModule.UserModifiedHandler;
|
||||
|
||||
HandlesModule.OnUserMessageRecieved += LevelModule.LevelHandler;
|
||||
HandlesModule.OnUserMessageRecieved += TagModule.TagHandler;
|
||||
HandlesModule.OnUserMessageRecieved += VariableModule.AutopublishHandler;
|
||||
}
|
||||
|
||||
internal static void LoadBackground()
|
||||
{
|
||||
_ = BackgroundModule.StatusHandler();
|
||||
_ = BackgroundModule.MuteHandler();
|
||||
}
|
||||
|
||||
internal static Task LogHandler(LogMessage arg)
|
||||
{
|
||||
Console.WriteLine(arg);
|
||||
if (arg.Severity != LogSeverity.Warning && arg.Severity != LogSeverity.Info) LogModule.LogMessage(arg);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public static async Task MessageHandler(SocketMessage arg)
|
||||
{
|
||||
if (arg is SocketUserMessage msg)
|
||||
{
|
||||
message = msg;
|
||||
context = new SocketCommandContext(client, message);
|
||||
|
||||
if (message.Author.Id == ID || message.Channel.GetType() == typeof(SocketDMChannel)) return;
|
||||
|
||||
Data.TryLoadAll(context.Guild.Id);
|
||||
|
||||
if (!context.Guild.HasAllMembers) await context.Guild.DownloadUsersAsync();
|
||||
|
||||
int argPos = 0;
|
||||
|
||||
if (message.HasStringPrefix(Data.misc.Data.prefix, ref argPos) || message.HasMentionPrefix(client.CurrentUser, ref argPos))
|
||||
{
|
||||
IResult result = await commands.ExecuteAsync(context, argPos, services);
|
||||
|
||||
if (!result.IsSuccess) await LogHandler(new LogMessage(LogSeverity.Error, "", result.ErrorReason));
|
||||
Log.Write(LogItem(context.User) + " has executed command: '" + message.Content + "'");
|
||||
}
|
||||
|
||||
await HandlesModule.OnUserMessageRecieved.Invoke(message);
|
||||
|
||||
Data.SaveAll(context.Guild.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
99
Nerd's Teaser Bot/Misc/Const.cs
Normal file
99
Nerd's Teaser Bot/Misc/Const.cs
Normal file
@ -0,0 +1,99 @@
|
||||
using Discord;
|
||||
using NerdsTeaserBot.Misc;
|
||||
using System;
|
||||
|
||||
namespace NerdsTeaserBot
|
||||
{
|
||||
public static class Const
|
||||
{
|
||||
public static string Discriminator { get => Internals.client.CurrentUser.Discriminator; }
|
||||
public static string FullName { get => Username + "#" + Discriminator; }
|
||||
public static ulong ID { get => Internals.client.CurrentUser.Id; }
|
||||
public static string Username { get => Internals.client.CurrentUser.Username; }
|
||||
|
||||
public static class Channels
|
||||
{
|
||||
public const ulong BotChangelog = 832234747538833448;
|
||||
public const ulong BotTesting = 778654642967937039;
|
||||
}
|
||||
|
||||
public static class Colors
|
||||
{
|
||||
public static Color DefaultColor
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Internals.client.CurrentUser.Id == 843876640001884230) return new Color(141, 236, 34);
|
||||
else return new Color(42, 137, 236);
|
||||
}
|
||||
}
|
||||
public static Color RandColor
|
||||
{
|
||||
get
|
||||
{
|
||||
Color[] cols = new[]
|
||||
{
|
||||
Color.Blue,
|
||||
Color.DarkBlue,
|
||||
Color.DarkerGrey,
|
||||
Color.DarkGreen,
|
||||
Color.DarkGrey,
|
||||
Color.DarkMagenta,
|
||||
Color.DarkOrange,
|
||||
Color.DarkPurple,
|
||||
Color.DarkRed,
|
||||
Color.DarkTeal,
|
||||
Color.Default,
|
||||
Color.Gold,
|
||||
Color.Green,
|
||||
Color.LighterGrey,
|
||||
Color.LightGrey,
|
||||
Color.LightOrange,
|
||||
Color.Magenta,
|
||||
Color.Orange,
|
||||
Color.Purple,
|
||||
Color.Red,
|
||||
Color.Teal,
|
||||
};
|
||||
|
||||
return cols[new Random().Next(0, cols.Length)];
|
||||
}
|
||||
}
|
||||
public static Color[] SeverityColors
|
||||
{
|
||||
get
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
Color.DarkRed,
|
||||
Color.Red,
|
||||
Color.Gold,
|
||||
Color.LighterGrey,
|
||||
Color.DarkGrey,
|
||||
Color.LightGrey,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Guilds
|
||||
{
|
||||
public const ulong NerdsTeasers = 755153205717106720;
|
||||
public const ulong TestServer = 778362746144030781;
|
||||
}
|
||||
|
||||
public static class Log
|
||||
{
|
||||
public static void Write(string msg = "")
|
||||
{
|
||||
msg = msg.Replace('\n', ' ');
|
||||
Data.log.Data += "[" + DateTime.Now + "]: " + msg + "\n";
|
||||
Console.WriteLine("Logged: " + msg);
|
||||
Data.log.Save();
|
||||
}
|
||||
}
|
||||
|
||||
public static string LogItem() => LogItem(Internals.context.User);
|
||||
public static string LogItem(IUser user) { return user.Username + "#" + user.Discriminator + " (" + user.Id + ")"; }
|
||||
}
|
||||
}
|
||||
55
Nerd's Teaser Bot/Misc/Data.cs
Normal file
55
Nerd's Teaser Bot/Misc/Data.cs
Normal file
@ -0,0 +1,55 @@
|
||||
using NerdsTeaserBot.Modules.Models;
|
||||
using Nerd_STF.File.Saving;
|
||||
using Nerd_STF.Lists;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
||||
namespace NerdsTeaserBot.Misc
|
||||
{
|
||||
public static class Data
|
||||
{
|
||||
internal static readonly string appPath = Assembly.GetExecutingAssembly().Location.Remove(Assembly.GetExecutingAssembly().Location.Length - Assembly.GetExecutingAssembly().GetName().Name.Length - 5);
|
||||
|
||||
internal static TextFile log = new("", "");
|
||||
internal static BinaryFile<ConstData> consts = new(appPath + "/data/constant/const.ntb", new());
|
||||
internal static BinaryFile<MiscData> misc = new("", new());
|
||||
internal static BinaryFile<List<User>> users = new("", new());
|
||||
|
||||
public static void LoadAll(ulong serverID)
|
||||
{
|
||||
consts.Load();
|
||||
|
||||
string folder = appPath + "/data/files-" + serverID;
|
||||
|
||||
log = TextFile.Load(folder + "/log.txt");
|
||||
misc = BinaryFile<MiscData>.Load(folder + "/misc.ntb");
|
||||
users = BinaryFile<List<User>>.Load(folder + "/users.ntb");
|
||||
}
|
||||
public static void SaveAll(ulong serverID)
|
||||
{
|
||||
consts.Save();
|
||||
|
||||
string folder = appPath + "/data/files-" + serverID;
|
||||
Directory.CreateDirectory(folder);
|
||||
|
||||
log.Path = folder + "/log.txt";
|
||||
misc.Path = folder + "/misc.ntb";
|
||||
users.Path = folder + "/users.ntb";
|
||||
if (log.Data != null) log.Save();
|
||||
if (misc.Data != null) misc.Save();
|
||||
if (users.Data is not null) users.Save();
|
||||
}
|
||||
public static void TryLoadAll(ulong serverID)
|
||||
{
|
||||
string folder = appPath + "/data/files-" + serverID;
|
||||
|
||||
log.Path = folder + "/log.txt";
|
||||
misc.Path = folder + "/misc.ntb";
|
||||
users.Path = folder + "/users.ntb";
|
||||
if (File.Exists(consts.Path)) consts.Load();
|
||||
if (File.Exists(log.Path)) log = TextFile.Load(log.Path);
|
||||
if (File.Exists(misc.Path)) misc = BinaryFile<MiscData>.Load(misc.Path);
|
||||
if (File.Exists(users.Path)) users = BinaryFile<List<User>>.Load(users.Path);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NerdsTeaserBot.Modules.Attributes
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
|
||||
public class HiddenFromListAttribute : Attribute { }
|
||||
}
|
||||
106
Nerd's Teaser Bot/Modules/BackgroundModule.cs
Normal file
106
Nerd's Teaser Bot/Modules/BackgroundModule.cs
Normal file
@ -0,0 +1,106 @@
|
||||
using Discord;
|
||||
using Discord.WebSocket;
|
||||
using NerdsTeaserBot.Misc;
|
||||
using NerdsTeaserBot.Modules.Commands;
|
||||
using NerdsTeaserBot.Modules.Extensions;
|
||||
using NerdsTeaserBot.Modules.Models;
|
||||
using Nerd_STF.Lists;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NerdsTeaserBot.Modules
|
||||
{
|
||||
public class BackgroundModule
|
||||
{
|
||||
public static async Task MuteHandler()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
IRole role;
|
||||
foreach (SocketGuild g in Internals.client.Guilds)
|
||||
{
|
||||
role = await GetOrCreateMuteRole(g);
|
||||
await RunInGuild(g);
|
||||
}
|
||||
|
||||
async Task RunInGuild(SocketGuild guild)
|
||||
{
|
||||
if (guild == null) return;
|
||||
|
||||
if (!new List<SocketRole>(guild.Roles).Contains(x => x.Id == role.Id)) role = await GetOrCreateMuteRole(guild);
|
||||
|
||||
List<User> users = Data.users.Data.FindAll(x => x.currentMute != null).FindAll(x => x.currentMute.start != default);
|
||||
|
||||
foreach (SocketGuildUser user in guild.Users)
|
||||
{
|
||||
User userM = users.FindOrDefault(x => x.userID == user.Id);
|
||||
if (userM == default) continue;
|
||||
|
||||
List<IRole> userRoles = new(user.Roles);
|
||||
if (userM.currentMute.IsMuted) { if (!userRoles.Contains(role)) AddRoleAsync(role); }
|
||||
else
|
||||
{
|
||||
if (userM.currentMute.unmute == null) await Unmute();
|
||||
else if (userM.currentMute.unmute.moderator == default) await Unmute();
|
||||
|
||||
if (userRoles.Contains(role)) RemoveRoleAsync(role);
|
||||
|
||||
async Task Unmute()
|
||||
{
|
||||
userM.currentMute.unmute = new()
|
||||
{
|
||||
moderator = Internals.client.CurrentUser.Id,
|
||||
reason = "Mute Timer Expired",
|
||||
time = DateTime.Now,
|
||||
};
|
||||
|
||||
await user.DMUserAsync("", false, ModerationModule.UnmuteDMEmbed(user, "Mute Timer Expired", Internals.client.CurrentUser).Build());
|
||||
}
|
||||
}
|
||||
|
||||
void AddRoleAsync(IRole role) => user.AddRoleAsync(role);
|
||||
void RemoveRoleAsync(IRole role) => user.RemoveRoleAsync(role);
|
||||
}
|
||||
}
|
||||
|
||||
static async Task<IRole> GetOrCreateMuteRole(SocketGuild guild)
|
||||
{
|
||||
List<IRole> roles = new(guild.Roles);
|
||||
|
||||
IRole r = roles.FindOrDefault(x => x.Name.ToLower().Trim().Contains("mute"));
|
||||
|
||||
if (r == default)
|
||||
{
|
||||
r = await guild.CreateRoleAsync("Muted", null, Color.DarkRed, false, false, null);
|
||||
|
||||
OverwritePermissions o = new(addReactions: PermValue.Deny, sendMessages: PermValue.Deny, speak: PermValue.Deny, stream: PermValue.Deny);
|
||||
foreach (IGuildChannel c in guild.Channels) await c.AddPermissionOverwriteAsync(r, o);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
await Task.Delay(2500);
|
||||
}
|
||||
}
|
||||
public static async Task StatusHandler()
|
||||
{
|
||||
(ActivityType, string)[] Statuses = new (ActivityType, string)[]
|
||||
{
|
||||
(ActivityType.Watching, " for n;help"),
|
||||
(ActivityType.Watching, " over Nerd's Teasers"),
|
||||
(ActivityType.Listening, " commands"),
|
||||
(ActivityType.Watching, " for DMs"),
|
||||
};
|
||||
|
||||
while (true)
|
||||
{
|
||||
await Internals.client.SetGameAsync(Statuses[Data.consts.Data.statusNum].Item2, null, Statuses[Data.consts.Data.statusNum].Item1);
|
||||
await Task.Delay(30000);
|
||||
Data.consts.Data.statusNum++;
|
||||
if (Data.consts.Data.statusNum >= Statuses.Length) Data.consts.Data.statusNum = 0;
|
||||
Data.consts.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
72
Nerd's Teaser Bot/Modules/ButtonModule.cs
Normal file
72
Nerd's Teaser Bot/Modules/ButtonModule.cs
Normal file
@ -0,0 +1,72 @@
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.Rest;
|
||||
using Discord.WebSocket;
|
||||
using NerdsTeaserBot.Misc;
|
||||
using NerdsTeaserBot.Modules.Models;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NerdsTeaserBot.Modules
|
||||
{
|
||||
public class ButtonModule
|
||||
{
|
||||
public static Task ButtonHandler(SocketInteraction arg)
|
||||
{
|
||||
if (arg is SocketMessageComponent but)
|
||||
{
|
||||
Internals.context = new(Internals.client, (SocketUserMessage)but.Message);
|
||||
|
||||
string id = but.Data.CustomId;
|
||||
|
||||
string text = id.Trim().ToLower();
|
||||
|
||||
if (text.StartsWith("delete")) DeleteMsg(but);
|
||||
else if (text.StartsWith("poll")) CheckPoll(but);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public static Task DeleteMsg(SocketMessageComponent but)
|
||||
{
|
||||
if (but.Data.CustomId.Length == "delete".Length) but.Message.DeleteAsync();
|
||||
else
|
||||
{
|
||||
string user = but.Data.CustomId["delete".Length..].TrimStart();
|
||||
|
||||
if (user == but.User.Username + "#" + but.User.Discriminator) but.Message.DeleteAsync();
|
||||
else
|
||||
{
|
||||
IUserMessage msg = (IUserMessage)but.Message;
|
||||
if (msg != null) LogModule.LogMessage(LogSeverity.Error, but.User.Mention + ", you are not allowed to delete this message.", reply: msg);
|
||||
else LogModule.LogMessage(LogSeverity.Error, but.User.Mention + ", you are not allowed to delete this message.");
|
||||
}
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public static Task CheckPoll(SocketMessageComponent but)
|
||||
{
|
||||
if (but.Data.CustomId.Length == "poll".Length) return Task.CompletedTask;
|
||||
|
||||
string[] options = but.Data.CustomId["poll".Length..].TrimStart().Split(" ");
|
||||
|
||||
byte option = Convert.ToByte(options[0]);
|
||||
string hash = options[1];
|
||||
|
||||
Poll poll = Data.misc.Data.polls.FindOrDefault(x => x.hash == hash);
|
||||
if (poll == default) return Task.CompletedTask;
|
||||
|
||||
int usr = poll.voters.FindIndex(x => x.id == but.User.Id);
|
||||
|
||||
if (usr == -1) poll.voters.Add(new() { id = but.User.Id, option = option, });
|
||||
else poll.voters[usr].option = option;
|
||||
|
||||
poll.Update(but.Message as SocketUserMessage);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
361
Nerd's Teaser Bot/Modules/Commands/BotModule.cs
Normal file
361
Nerd's Teaser Bot/Modules/Commands/BotModule.cs
Normal file
@ -0,0 +1,361 @@
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.Rest;
|
||||
using Discord.WebSocket;
|
||||
using NerdsTeaserBot.Misc;
|
||||
using NerdsTeaserBot.Modules.Attributes;
|
||||
using NerdsTeaserBot.Modules.Models;
|
||||
using Nerd_STF.Extensions;
|
||||
using Nerd_STF.File.Saving;
|
||||
using Nerd_STF.Lists;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using static Discord.Format;
|
||||
using static NerdsTeaserBot.Const;
|
||||
|
||||
namespace NerdsTeaserBot.Modules.Commands
|
||||
{
|
||||
[Name("Bot")]
|
||||
[Summary("Commands about the bot and it's data")]
|
||||
public class BotModule : ModuleBase<SocketCommandContext>
|
||||
{
|
||||
[Command("commandinfo")]
|
||||
[Summary("Info about a specific command")]
|
||||
public async Task CommandInfo([Summary("The command to show info about")] [Remainder] string command)
|
||||
{
|
||||
CommandService comms = Internals.commands;
|
||||
|
||||
List<CommandInfo> cmds = new List<CommandInfo>(comms.Commands).FindAll(x => !new List<Attribute>(x.Attributes).Contains(y => y.GetType() == typeof(HiddenFromListAttribute)));
|
||||
List<CommandInfo> cmdS = cmds.FindAll(x => x.Name.ToLower() == command.ToLower());
|
||||
|
||||
bool ded = false;
|
||||
if (cmdS is null) ded = true;
|
||||
else if (cmdS.Length == 0) ded = true;
|
||||
|
||||
if (ded)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "There is no command found with that name.");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (CommandInfo cmd in cmdS)
|
||||
{
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Info about n;" + cmd.Name,
|
||||
};
|
||||
|
||||
string summary = "No Summary Provided";
|
||||
if (cmd.Summary != "" && cmd.Summary != null) summary = cmd.Summary;
|
||||
|
||||
e.AddField("Summary", Code(summary), true);
|
||||
e.AddField("Module", Code(cmd.Module.Name), true);
|
||||
|
||||
List<string> aliases = new List<string>(cmd.Aliases).FindAll(x => x.ToLower() != cmd.Name.ToLower());
|
||||
bool pass = false;
|
||||
if (aliases is null) pass = true;
|
||||
else if (aliases.Length == 0) pass = true;
|
||||
|
||||
if (!pass)
|
||||
{
|
||||
string alias = "";
|
||||
foreach (string s in aliases) alias += Code(s) + ", ";
|
||||
e.AddField("Aliases", alias.Remove(alias.Length - 2), true);
|
||||
}
|
||||
|
||||
List<ParameterInfo> param = new List<ParameterInfo>(cmd.Parameters).FindAll(x => !new List<Attribute>(x.Attributes).Contains(y => y.GetType() == typeof(HiddenFromListAttribute)));
|
||||
|
||||
e.AddField("Parameter Count:", Code(param.Length.ToString()));
|
||||
|
||||
foreach (ParameterInfo par in param)
|
||||
{
|
||||
string add = "";
|
||||
|
||||
string summaryP = "No Summary Provided";
|
||||
if (par.Summary != "" && par.Summary != null) summaryP = par.Summary;
|
||||
|
||||
add += "_Summary: _" + Code(summaryP) + "\n";
|
||||
add += "_Optional: _" + "`" + par.IsOptional;
|
||||
if (par.IsOptional)
|
||||
{
|
||||
add += " (Default: ";
|
||||
if (par.Type == typeof(string)) add += '"' + par.DefaultValue.ToString() + '"';
|
||||
else add += par.DefaultValue;
|
||||
add += ")";
|
||||
}
|
||||
add += "`\n";
|
||||
|
||||
add += "_Parameter Type: _" + Code(par.Type.Name);
|
||||
|
||||
e.AddField("Parameter: " + par.Name + "", add);
|
||||
}
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
}
|
||||
|
||||
[Command("commands")]
|
||||
[Summary("List of command modules, or commands of a module")]
|
||||
public async Task Commands([Summary("The module name to show commands for. Leave empty to show all modules.")] string module = "")
|
||||
{
|
||||
CommandService comms = Internals.commands;
|
||||
List<ModuleInfo> modules = new List<ModuleInfo>(comms.Modules).FindAll(x => !new List<Attribute>(x.Attributes).Contains(y => y.GetType() == typeof(HiddenFromListAttribute)));
|
||||
List<CommandInfo> commands = new List<CommandInfo>(comms.Commands).FindAll(x => !new List<Attribute>(x.Attributes).Contains(y => y.GetType() == typeof(HiddenFromListAttribute)));
|
||||
|
||||
if (commands.Contains(x => x.Name.ToLower() == module.ToLower())) LogModule.LogMessage(LogSeverity.Warning, "A command has been found with the name " + Bold(Code(module.ToLower())) + ". Did you mean to use the command " + Code("n;commandinfo " + module.ToLower()) + "?");
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "",
|
||||
};
|
||||
|
||||
if (module == "") ShowModules();
|
||||
else
|
||||
{
|
||||
ModuleInfo info = modules.FindOrDefault(x => x.Name.ToLower() == module.ToLower());
|
||||
if (info == null)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "No module is found with that name.");
|
||||
return;
|
||||
}
|
||||
else ShowCommands(info);
|
||||
}
|
||||
|
||||
void ShowCommands(ModuleInfo module)
|
||||
{
|
||||
List<CommandInfo> cmds = new List<CommandInfo>(module.Commands).FindAll(x => !new List<Attribute>(x.Attributes).Contains(y => y.GetType() == typeof(HiddenFromListAttribute)));
|
||||
|
||||
e.Title = "Showing " + cmds.Length + " Command";
|
||||
if (modules.Length != 1) e.Title += "s";
|
||||
|
||||
bool pass = false;
|
||||
if (cmds is null) pass = true;
|
||||
else if (cmds.Length == 0) pass = true;
|
||||
|
||||
if (pass) e.Description = Italics("There are no commands in this module currently avaliable.");
|
||||
else
|
||||
{
|
||||
foreach (CommandInfo cmd in cmds)
|
||||
{
|
||||
string summary = "No Summary Provided";
|
||||
if (cmd.Summary != "" && cmd.Summary != null) summary = cmd.Summary;
|
||||
e.Description += Bold(Code(cmd.Name)) + " - " + Bold(cmd.Summary) + "\n";
|
||||
}
|
||||
|
||||
e.Description += "\n*" + cmds.Length + " Total Command";
|
||||
if (cmds.Length != 1) e.Description += "s";
|
||||
e.Description += "*";
|
||||
}
|
||||
}
|
||||
void ShowModules()
|
||||
{
|
||||
e.Title = "Showing " + modules.Length + " Command Module";
|
||||
if (modules.Length != 1) e.Title += "s";
|
||||
|
||||
bool pass = false;
|
||||
if (modules is null) pass = true;
|
||||
else if (modules.Length == 0) pass = true;
|
||||
|
||||
if (pass) e.Description = Italics("There are no command modules currently avaliable.");
|
||||
else
|
||||
{
|
||||
int commandsL = 0;
|
||||
|
||||
foreach (ModuleInfo module in modules)
|
||||
{
|
||||
int length = new List<CommandInfo>(module.Commands).Length;
|
||||
|
||||
string summary = "No Summary Provided";
|
||||
if (module.Summary != "" && module.Summary != null) summary = module.Summary;
|
||||
e.Description += "**" + Code(module.Name) + " *(" + length + " cmd";
|
||||
if (length != 1) e.Description += "s)";
|
||||
e.Description += "*** - " + Bold(summary) + "\n";
|
||||
|
||||
commandsL += length;
|
||||
}
|
||||
|
||||
e.Description += "\n*" + commandsL + " Total Command";
|
||||
if (commandsL != 1) e.Description += "s";
|
||||
e.Description += "*";
|
||||
}
|
||||
}
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("credits")]
|
||||
[Summary("The list of people who deserve mentions")]
|
||||
public async Task Credits()
|
||||
{
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = Italics("There are currently " + Code(Static.Credits.Length.ToString()) + " honerable mentions."),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Honerable Mentions for " + Username,
|
||||
};
|
||||
|
||||
foreach (Credit c in Static.Credits)
|
||||
{
|
||||
SocketUser usr = Context.Client.GetUser(c.id);
|
||||
e.AddField(usr.Username + "#" + usr.Discriminator, Code(c.reason));
|
||||
}
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("help")]
|
||||
[Summary("Basic info about the bot")]
|
||||
public async Task Help()
|
||||
{
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Basic Info on " + Username
|
||||
};
|
||||
|
||||
e.AddField("What am I?", "I am a bot used to maintain the backend of a server, Nerd's Teasers.", true);
|
||||
e.AddField("What can I do?", "I can control automod, tags, moderation tools, teaser info, and more.", true);
|
||||
e.AddField("What is my prefix?", "My prefix is " + Code("n;") + ". Use " + Code("n;info") + " for more advanced info, or " + Code("n;commands") + " for a list of command modules.", true);
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("info")]
|
||||
[Summary("In-depth info about the bot")]
|
||||
public async Task Info()
|
||||
{
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
ThumbnailUrl = Context.Client.CurrentUser.GetAvatarUrl(ImageFormat.Auto, 512),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "In-Depth info about " + Username,
|
||||
};
|
||||
|
||||
SocketSelfUser self = Internals.client.CurrentUser;
|
||||
e.AddField("Full Name", Code(FullName), true);
|
||||
e.AddField("Client ID", Code(ID.ToString()), true);
|
||||
e.AddField("Mention", "<@" + ID + ">", true);
|
||||
e.AddField("Created At", Code(self.CreatedAt.DateTime.ToString()), true);
|
||||
e.AddField("Program Language", Code("C-Sharp (C#)"), true);
|
||||
e.AddField("Program APIs", Code(".NET 5.0") + "\n" + Code("Discord.NET (Experimental) v2.3.8 (API v6)"), true);
|
||||
|
||||
string version = "Cannot detect Bot Version (No Changelog Provided)";
|
||||
if (new List<SocketGuildChannel>(Context.Guild.Channels).Contains(x => x.Id == Data.misc.Data.changelogChannel))
|
||||
{
|
||||
IMessage msg = new List<IMessage>(await Internals.client.GetGuild(Context.Guild.Id).GetTextChannel(Data.misc.Data.changelogChannel).GetMessagesAsync(1).FlattenAsync())[0];
|
||||
int start = -1, end = msg.Content.Length;
|
||||
|
||||
for (int i = 0; i < msg.Content.Length; i++)
|
||||
{
|
||||
if (msg.Content[i] == 'v') start = i;
|
||||
else if (start != -1 && (msg.Content[i] == ' ' || msg.Content[i] == '*'))
|
||||
{
|
||||
end = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (start == -1) start = 0;
|
||||
version = msg.Content[start..end];
|
||||
}
|
||||
e.AddField("Version: ", Code(version), true);
|
||||
|
||||
List<SocketRole> roles = new(Context.Guild.GetUser(self.Id).Roles);
|
||||
roles.Remove(Context.Guild.EveryoneRole);
|
||||
|
||||
string roleS = "";
|
||||
foreach (SocketRole role in roles) roleS += role.Mention + ", ";
|
||||
|
||||
e.AddField("Assigned Roles: ", roleS.Remove(roleS.Length - 2));
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("leave")]
|
||||
[RequireOwner]
|
||||
[Summary("Runs through all servers the bot is in and checks them to the list of approved servers.")]
|
||||
public async Task Leave()
|
||||
{
|
||||
List<SocketGuild> left = new();
|
||||
foreach (SocketGuild g in Context.Client.Guilds) if (await PermittedServerHandler(g)) left.Add(g);
|
||||
|
||||
if (left.Length == 0)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "No Servers Left");
|
||||
return;
|
||||
}
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Left " + left.Length + " Unapproved Servers",
|
||||
};
|
||||
|
||||
foreach (SocketGuild g in left) e.Description += Code(g.Name) + " (Owner: <@" + g.Id + ">)";
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("ping")]
|
||||
[Summary("Pings the bot, and returns helpful info about that ping")]
|
||||
public async Task Ping()
|
||||
{
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = Italics("You have just called for the ping time of " + Code(Username)),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = ":ping_pong: Pong",
|
||||
};
|
||||
|
||||
e.AddField("Estimated Server Latency", Code(Context.Client.Latency + " Milliseconds") +
|
||||
"\n" + Italics("Should be around " + Code("100 - 300")), true);
|
||||
e.AddField("Round-Trip Ping Time", Code((DateTime.UtcNow - Context.Message.CreatedAt.UtcDateTime).TotalMilliseconds.ToString("0") + " Milliseconds") +
|
||||
"\n" + Italics("Should be around " + Code("2000 - 4000")), true);
|
||||
e.AddField("Uptime", "This bot has been online since " + Code(Internals.upTime.Humanize(true, true)) +
|
||||
"\n" + Italics("(" + (DateTime.Now - Internals.upTime).Humanize(ignoreMilliseconds: true)) + ")", true);
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("test")]
|
||||
[Summary("Does whatever is currently being tested")]
|
||||
public async Task Test()
|
||||
{
|
||||
await ReplyAsync("eat ass, chump");
|
||||
}
|
||||
|
||||
// end commands
|
||||
|
||||
public static async Task<bool> PermittedServerHandler(SocketGuild guild)
|
||||
{
|
||||
bool not = !Data.misc.Data.allowedServers.Contains(guild.Id);
|
||||
|
||||
if (not)
|
||||
{
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Color.Red,
|
||||
Description = "This server is not a part of the list of approved servers. Please come into contact with <@478210457816006666> to add it",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Server Cannot be Joined",
|
||||
};
|
||||
|
||||
await guild.DefaultChannel.SendMessageAsync("", false, e.Build());
|
||||
await guild.LeaveAsync();
|
||||
}
|
||||
|
||||
return not;
|
||||
}
|
||||
}
|
||||
}
|
||||
408
Nerd's Teaser Bot/Modules/Commands/FunModule.cs
Normal file
408
Nerd's Teaser Bot/Modules/Commands/FunModule.cs
Normal file
@ -0,0 +1,408 @@
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using NerdsTeaserBot.Misc;
|
||||
using NerdsTeaserBot.Modules.Models;
|
||||
using Nerd_STF;
|
||||
using Nerd_STF.Lists;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using static Discord.Format;
|
||||
using static NerdsTeaserBot.Const;
|
||||
|
||||
namespace NerdsTeaserBot.Modules.Commands
|
||||
{
|
||||
[Name("Fun")]
|
||||
[Summary("Commands that can be used for fun")]
|
||||
public class FunModule : ModuleBase<SocketCommandContext>
|
||||
{
|
||||
internal static JArray jokes = null;
|
||||
|
||||
[Command("cate")]
|
||||
[Summary("Finds an image of a cate on the internet and relays it back")]
|
||||
public async Task Cate()
|
||||
{
|
||||
HttpClient client = new();
|
||||
|
||||
JArray array = JArray.Parse(await client.GetStringAsync("https://api.thecatapi.com/v1/images/search?size=full"));
|
||||
|
||||
JObject cate = (JObject)array[0];
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Footer = new() { Text = "Cate found using 'https://thecatapi.com'" },
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Cate Detected",
|
||||
ImageUrl = cate["url"].ToString(),
|
||||
};
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("doge")]
|
||||
[Summary("Finds an image of a doge on the internet and relays it back")]
|
||||
public async Task Doge()
|
||||
{
|
||||
HttpClient client = new();
|
||||
|
||||
JArray array = JArray.Parse(await client.GetStringAsync("https://api.thedogapi.com/v1/images/search?size=full"));
|
||||
|
||||
JObject doge = (JObject)array[0];
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Footer = new() { Text = "Doge found using 'https://thedogapi.com'" },
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Doge Detected",
|
||||
ImageUrl = doge["url"].ToString(),
|
||||
};
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("joke")]
|
||||
[Summary("Gives a random joke to you. Punchline and everything")]
|
||||
public async Task Joke()
|
||||
{
|
||||
if (jokes == null) jokes = JArray.Parse(await new HttpClient().GetStringAsync("https://raw.githubusercontent.com/15Dkatz/official_joke_api/master/jokes/index.json"));
|
||||
|
||||
JObject joke = (JObject)jokes[new Random().Next(0, jokes.Count)];
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = Italics(joke["setup"].ToString()) + "\n" + Spoiler(joke["punchline"].ToString()),
|
||||
Footer = new() { Text = "Joke found using 'https://github.com/15Dkatz/official_joke_api'" },
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Definitely Funny Joke Incoming",
|
||||
};
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("pocketsand")]
|
||||
[Summary("Pocketsands a user")]
|
||||
public async Task Pocketsand([Summary("The user to pocketsand")] IUser user)
|
||||
{
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Color.Orange,
|
||||
Description = Context.User.Mention + " pocketsands " + user.Mention + "! Shi-Shi Sha!",
|
||||
ImageUrl = "https://cdn.discordapp.com/attachments/786036378613710928/851972369941528586/pocketsand.gif",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Pocketsanded!",
|
||||
};
|
||||
|
||||
await ReplyAsync("Hey " + user.Mention + ", you just got...", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("poll")]
|
||||
[Summary("Creates a poll with the specified name and options")]
|
||||
public async Task Poll([Remainder][Summary("The options for the poll. Quote each option with ''. The first option is the title, the next are selections")] string options)
|
||||
{
|
||||
string[] letterEmotes = new[] { "🇦", "🇧", "🇨", "🇩", "🇪", "🇫", "🇬", "🇭", "🇮", "🇯", "🇰", "🇱", "🇲", "🇳", "🇴", "🇵", "🇶", "🇷", "🇸", "🇹", "🇺", "🇻", "🇼", "🇽", "🇾", "🇿" };
|
||||
const string letters = "abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
if (!options.StartsWith("'") || !options.EndsWith("'"))
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "Options must start and end with a '");
|
||||
return;
|
||||
}
|
||||
|
||||
string[] splits = options.Trim()[1..(options.Length - 1)].Split("' '");
|
||||
|
||||
if (splits.Length == 1)
|
||||
{
|
||||
await Poll("'" + splits[0] + "' 'Yes' 'No'");
|
||||
return;
|
||||
}
|
||||
|
||||
if (splits.Length > 21)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "There cannot be more than 21 options (including the title)");
|
||||
return;
|
||||
}
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = ":bar_chart: " + splits[0],
|
||||
};
|
||||
|
||||
for (int i = 1; i < splits.Length; i++) e.Description += ":regional_indicator_" + letters[i - 1] + ": - " + Code(splits[i]) + "\n";
|
||||
|
||||
IUserMessage msg = await ReplyAsync("", false, e.Build());
|
||||
|
||||
for (int i = 1; i < splits.Length; i++) await msg.AddReactionAsync(new Emoji(letterEmotes[i - 1]));
|
||||
}
|
||||
|
||||
[Command("pollbutton")]
|
||||
[Summary("Creates a poll with the specified name and options, and uses buttons to track interactions [NOTE: This is not perfectly stable]")]
|
||||
public async Task Pollbutton([Remainder][Summary("The options for the poll. Quote each option with ''. The first option is the title, the next are selections")] string options)
|
||||
{
|
||||
string[] letterEmotes = new[] { "🇦", "🇧", "🇨", "🇩", "🇪", "🇫", "🇬", "🇭", "🇮", "🇯", "🇰", "🇱", "🇲", "🇳", "🇴", "🇵", "🇶", "🇷", "🇸", "🇹", "🇺", "🇻", "🇼", "🇽", "🇾", "🇿" };
|
||||
const string letters = "abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
if (!options.StartsWith("'") || !options.EndsWith("'"))
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "Options must start and end with a '");
|
||||
return;
|
||||
}
|
||||
|
||||
string[] splits = options.Trim()[1..(options.Length - 1)].Split("' '");
|
||||
|
||||
if (splits.Length == 1)
|
||||
{
|
||||
await Pollbutton("'" + splits[0] + "' 'Yes' 'No'");
|
||||
return;
|
||||
}
|
||||
|
||||
if (splits.Length > 26)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "There cannot be more than 26 options (including the title)");
|
||||
return;
|
||||
}
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = ":bar_chart: " + splits[0],
|
||||
};
|
||||
|
||||
for (int i = 1; i < splits.Length; i++) e.Description += ":regional_indicator_" + letters[i - 1] + ": - " + Code(splits[i]) + "\n";
|
||||
|
||||
int buttons = splits.Length - 1;
|
||||
|
||||
ComponentBuilder c = new() { ActionRows = new(), };
|
||||
|
||||
string hash = Hashes.SHA256(splits[0] + DateTime.Now);
|
||||
|
||||
for (int i = 1; i < splits.Length; i++)
|
||||
{
|
||||
ActionRowBuilder a = new();
|
||||
|
||||
int j = 0;
|
||||
|
||||
for (_ = 0; i < splits.Length; i++)
|
||||
{
|
||||
if (j >= 5)
|
||||
{
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
|
||||
ButtonBuilder b = new()
|
||||
{
|
||||
CustomId = "poll " + i + " " + hash,
|
||||
Emote = new Emoji(letterEmotes[i - 1]),
|
||||
Label = splits[i],
|
||||
Style = ButtonStyle.Primary,
|
||||
};
|
||||
|
||||
a.WithComponent(b.Build());
|
||||
|
||||
j++;
|
||||
}
|
||||
|
||||
c.ActionRows.Add(a);
|
||||
}
|
||||
|
||||
IUserMessage msg = await ReplyAsync("", false, e.Build(), component: c.Build());
|
||||
Data.misc.Data.polls.Add(new Poll() { hash = hash, voters = new(), });
|
||||
}
|
||||
|
||||
[Command("quote")]
|
||||
[Summary("Quotes a user on a message")]
|
||||
public async Task Quote([Summary("The user to quote")] IUser user, [Remainder][Summary("The message you want to quote")] string quote)
|
||||
{
|
||||
ComponentBuilder c = new();
|
||||
ButtonBuilder b = new()
|
||||
{
|
||||
CustomId = "delete " + user.Username + "#" + user.Discriminator,
|
||||
Label = "Delete",
|
||||
Style = ButtonStyle.Danger,
|
||||
};
|
||||
c.WithButton(b);
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = Format.Quote(Italics('"' + quote + '"')) + "\n\n" +
|
||||
Bold("- " + user.Mention),
|
||||
};
|
||||
e.WithFooter("The person this is targeted towards can choose to delete this message.");
|
||||
|
||||
await ReplyAsync("", false, e.Build(), component: c.Build());
|
||||
}
|
||||
|
||||
[Command("randomfact")]
|
||||
[Summary("Shows a random fact found on the internet")]
|
||||
public async Task Randomfact()
|
||||
{
|
||||
HttpClient client = new();
|
||||
|
||||
JObject obj = JObject.Parse(await client.GetStringAsync("https://uselessfacts.jsph.pl/random.json?language=en"));
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = Code(obj["text"].ToString().Replace("`", "'")),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Random Fact by " + obj["source"].ToString(),
|
||||
Url = obj["source_url"].ToString()
|
||||
};
|
||||
e.WithFooter("Fact found using 'https://uselessfacts.jsph.pl'");
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("say")]
|
||||
[Summary("Causes the bot to say what you want it to (Deletes the original message)")]
|
||||
public async Task Say([Remainder][Summary("The message for the bot to say")] string message)
|
||||
{
|
||||
await Context.Message.DeleteAsync();
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = message,
|
||||
};
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("sayfor")]
|
||||
[Summary("Causes the bot to say what you want it to, but as someone else (Deletes the original message)")]
|
||||
public async Task Sayfor([Summary("The user the bot pretends to be")] IUser user, [Remainder][Summary("The message for the bot to say")] string message)
|
||||
{
|
||||
await Context.Message.DeleteAsync();
|
||||
|
||||
ComponentBuilder c = new();
|
||||
ButtonBuilder b = new()
|
||||
{
|
||||
CustomId = "delete " + user.Username + "#" + user.Discriminator,
|
||||
Label = "Delete",
|
||||
Style = ButtonStyle.Danger,
|
||||
};
|
||||
c.WithButton(b);
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = message,
|
||||
Title = "Message from " + user.Username + "#" + user.Discriminator,
|
||||
};
|
||||
e.WithFooter("The person this is targeted towards can choose to delete this message.");
|
||||
|
||||
await ReplyAsync("", false, e.Build(), component: c.Build());
|
||||
}
|
||||
|
||||
[Command("what")]
|
||||
[Summary("Number 7: Student watches porn, and gets naked.")]
|
||||
public async Task What([Remainder][Summary("the")] string msg = "Don't insult Delaware it's fire")
|
||||
{
|
||||
string response;
|
||||
|
||||
response = msg.Trim().ToLower() switch
|
||||
{
|
||||
"ball" or "nut" or "balls" or "nuts" =>
|
||||
"nuts.\n" +
|
||||
"balls, even.",
|
||||
|
||||
"cock" or "dick" =>
|
||||
"dick.\n" +
|
||||
"cock, even.",
|
||||
|
||||
"don't insult delaware it's fire" =>
|
||||
"when you dont change the message",
|
||||
|
||||
"ok" =>
|
||||
"please become funny",
|
||||
|
||||
"penis" =>
|
||||
"𝓹𝓮𝓷𝓲𝓼",
|
||||
|
||||
"testicals" =>
|
||||
"clearly somebody doesnt know how to fucking spell testicles. just use 'balls,' bitch",
|
||||
|
||||
"testicles" =>
|
||||
"𝓽𝓮𝓼𝓽𝓲𝓬𝓵𝓮𝓼",
|
||||
|
||||
_ => "mmm im so hungry",
|
||||
};
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.RandColor,
|
||||
Description = response,
|
||||
Timestamp = DateTime.Now,
|
||||
};
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("8ball")]
|
||||
[Summary("Gives a question, and the bot answers it (pretty badly)")]
|
||||
public async Task Ball8([Remainder][Summary("The question to ask the bot")] string question)
|
||||
{
|
||||
(string, float)[] answers = new[]
|
||||
{
|
||||
("Definitely", 0.9f),
|
||||
("Don't Ask Me", -1),
|
||||
("I Don't Know", -1),
|
||||
("I Don't Really Know", -1),
|
||||
("Maybe", 0.5f),
|
||||
("Maybe?", 0.5f),
|
||||
("Never Happening", 0),
|
||||
("No", 0.2f),
|
||||
("Nope", 0.1f),
|
||||
("Not At All", 0),
|
||||
("Not Sure", -1),
|
||||
("Yes", 0.8f),
|
||||
("100%", 1f),
|
||||
};
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Color.DarkGrey,
|
||||
Description = "",
|
||||
Footer = new() { Text = "Question: " + question },
|
||||
Timestamp = DateTime.Now,
|
||||
};
|
||||
for (int i = 0; i < new Random().Next(1, 4); i++) e.Description += "u";
|
||||
for (int i = 0; i < new Random().Next(1, 8); i++) e.Description += "h";
|
||||
for (int i = 0; i < new Random().Next(1, 6); i++) e.Description += ".";
|
||||
|
||||
IUserMessage msg = await ReplyAsync("", false, e.Build());
|
||||
|
||||
await Task.Delay(new Random().Next(1500, 3000));
|
||||
|
||||
(string, float) response = answers[new Random().Next(0, answers.Length)];
|
||||
|
||||
e.Color = Colors.DefaultColor;
|
||||
e.Description = Bold(response.Item1) + "\n\n";
|
||||
e.Title = "8Ball Question";
|
||||
|
||||
if (response.Item2 >= 0)
|
||||
{
|
||||
e.Description += Code((response.Item2 * 100) + "%") + "\n";
|
||||
|
||||
for (int i = 0; i < (int)(response.Item2 * 10); i++) e.Description += ":green_square:";
|
||||
for (int i = (int)(response.Item2 * 10); i < 10; i++) e.Description += ":white_large_square:";
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Description += Code("?? %") + "\n";
|
||||
for (int i = 0; i < 10; i++) e.Description += ":grey_question:";
|
||||
}
|
||||
|
||||
await msg.ModifyAsync(x => x.Embed = e.Build());
|
||||
}
|
||||
}
|
||||
}
|
||||
508
Nerd's Teaser Bot/Modules/Commands/LevelModule.cs
Normal file
508
Nerd's Teaser Bot/Modules/Commands/LevelModule.cs
Normal file
@ -0,0 +1,508 @@
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.Rest;
|
||||
using Discord.WebSocket;
|
||||
using NerdsTeaserBot.Misc;
|
||||
using NerdsTeaserBot.Modules.Attributes;
|
||||
using NerdsTeaserBot.Modules.Models;
|
||||
using Nerd_STF.Extensions;
|
||||
using Nerd_STF.File.Saving;
|
||||
using Nerd_STF.Lists;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using static Discord.Format;
|
||||
using static NerdsTeaserBot.Const;
|
||||
|
||||
namespace NerdsTeaserBot.Modules.Commands
|
||||
{
|
||||
[Group("level")]
|
||||
[Name("Level")]
|
||||
[Summary("Commands about leveling up and levelup message formatting")]
|
||||
public class LevelModule : ModuleBase<SocketCommandContext>
|
||||
{
|
||||
public static List<User> LevelLeaderboard
|
||||
{
|
||||
get
|
||||
{
|
||||
System.Collections.Generic.List<User> systemL = new(Data.users.Data.FindAll(x => x.level != null).FindAll(x => x.level.TotalXP > 0).ToArray());
|
||||
systemL.Sort((x, y) => x.level.TotalXP - y.level.TotalXP);
|
||||
systemL.Reverse();
|
||||
|
||||
return new(systemL);
|
||||
}
|
||||
}
|
||||
|
||||
[Command("give")]
|
||||
[RequireUserPermission(GuildPermission.ManageGuild)]
|
||||
[Summary("Gives a certain amount of levels or xp to a user")]
|
||||
public async Task Give([Summary("The user to give levels/xp to")] SocketGuildUser user, [Summary("The amount of levels/xp to give")] int value, [Summary("The type to give (levels/xp)")] ModifyType type = ModifyType.Levels)
|
||||
{
|
||||
User usr = Data.users.Data.FindOrDefault(x => x.userID == user.Id);
|
||||
|
||||
if (usr == null)
|
||||
{
|
||||
usr = new() { userID = user.Id };
|
||||
Data.users.Data.Add(usr);
|
||||
}
|
||||
|
||||
Level lvl = usr.level;
|
||||
|
||||
if (lvl == null)
|
||||
{
|
||||
lvl = new();
|
||||
usr.level = lvl;
|
||||
}
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = user.Mention + " has has their " + Code(type.ToString()) + " added to, from ",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = type + " Added",
|
||||
};
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case ModifyType.Level or ModifyType.Levels:
|
||||
e.Description += Code("Level " + lvl.level) + " to " + Code("Level " + (lvl.level + value));
|
||||
lvl.level += value;
|
||||
break;
|
||||
|
||||
case ModifyType.XP:
|
||||
e.Description += Code(lvl.xp + " XP") + " to " + Code(lvl.xp + value + " XP");
|
||||
lvl.xp += value;
|
||||
|
||||
while (lvl.xp >= lvl.MaxXP)
|
||||
{
|
||||
lvl.xp -= lvl.MaxXP;
|
||||
lvl.level++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("leaderboard")]
|
||||
[Summary("Shows the level stats of anyone who has talked in this server")]
|
||||
public async Task Leaderboard()
|
||||
{
|
||||
List<User> users = LevelLeaderboard;
|
||||
|
||||
int countedM = 0, totalM = 0, totalX = 0;
|
||||
string leaderboard = "";
|
||||
for (int i = 0; i < users.Length; i++)
|
||||
{
|
||||
Level lvl = users[i].level;
|
||||
|
||||
countedM += lvl.countedMsgs;
|
||||
totalM += lvl.msgs;
|
||||
totalX += lvl.TotalXP;
|
||||
|
||||
leaderboard += Code(Nerd_STF.Misc.PlaceMaker(i + 1)) + ": <@" + users[i].userID + ">: " + Code("Level " + lvl.level) + " and " + Code(lvl.xp + "/" + lvl.MaxXP + " XP") + " *(" + lvl.msgs + " Message";
|
||||
if (lvl.msgs != 1) leaderboard += "s";
|
||||
leaderboard += ", " + lvl.countedMsgs + " Counted)*\n";
|
||||
}
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "*" + totalM + " Total Message",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Level Leaderboard for " + Context.Guild.Name,
|
||||
};
|
||||
|
||||
if (totalM != 1) e.Description += "s";
|
||||
e.Description += " (" + countedM + " Counted)*\n" + Italics(totalX + " Total XP") + "\n\n" + leaderboard;
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("mention get")]
|
||||
[Summary("Shows if the bot will mention a user when they level up")]
|
||||
public async Task MentionGet()
|
||||
{
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "The bot will mention users when they level up: " + Code(Data.misc.Data.levelMention.ToString()),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Levelup Mention",
|
||||
};
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("mention reset")]
|
||||
[RequireUserPermission(GuildPermission.ManageGuild)]
|
||||
[Summary("Sets the ability to mention when leveling up back to the default value")]
|
||||
public async Task MentionReset()
|
||||
{
|
||||
Data.misc.Data.levelMention = false;
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "Successfully set the ability to mention a user when leveling up to: " + Code("False"),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Reset Levelup Mention",
|
||||
};
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("mention set")]
|
||||
[RequireUserPermission(GuildPermission.ManageGuild)]
|
||||
[Summary("Sets the ability to mention when leveling up")]
|
||||
public async Task MentionSet([Summary("The true/false statement of the ability")] bool mention)
|
||||
{
|
||||
bool old = Data.misc.Data.levelMention;
|
||||
Data.misc.Data.levelMention = mention;
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "Successfully set the ability to mention a user when leveling up to: " + Code(mention.ToString()),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Set Levelup Mention",
|
||||
};
|
||||
e.Description += "\n(Previous: " + Code(old.ToString() + ")");
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("rank")]
|
||||
[Summary("Shows level info on the user executing the command")]
|
||||
public async Task Rank() => await Rank(Context.User);
|
||||
|
||||
[Command("rank")]
|
||||
[Summary("Shows level info on a specific user")]
|
||||
public async Task Rank(SocketUser user)
|
||||
{
|
||||
User usr = Data.users.Data.FindOrDefault(x => x.userID == user.Id);
|
||||
|
||||
if (usr == null)
|
||||
{
|
||||
usr = new() { userID = user.Id };
|
||||
Data.users.Data.Add(usr);
|
||||
}
|
||||
|
||||
Level lvl = usr.level;
|
||||
|
||||
if (lvl == null)
|
||||
{
|
||||
lvl = new();
|
||||
usr.level = lvl;
|
||||
}
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = user.Mention + " " + Code(lvl.TotalXP > 0 ? "IS" : "is NOT") + " on the Leaderboard\n\n" +
|
||||
"Level: " + Code(lvl.level.ToString()) + "\n" +
|
||||
"XP: " + Code(lvl.xp.ToString()) + "\n" +
|
||||
"(Total XP): " + Code(lvl.TotalXP.ToString()) + "\n" +
|
||||
"XP to Level Up: " + Code((lvl.MaxXP - lvl.xp).ToString() + " (" + lvl.MaxXP + " Total)"),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = user.Username + "'s Level Stats",
|
||||
};
|
||||
|
||||
if (lvl.TotalXP > 0) e.Description += "\n" + "Leaderboard Rank: " + Code(Nerd_STF.Misc.PlaceMaker(LevelLeaderboard.FindIndex(x => x.userID == user.Id) + 1));
|
||||
|
||||
await Context.Channel.SendFileAsync(Data.appPath + "/data/constant/level-imgs/" + Math.Clamp(lvl.level, -1, 101) + ".png", "", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("remove")]
|
||||
[RequireUserPermission(GuildPermission.ManageGuild)]
|
||||
[Summary("Removes a certain amount of levels or xp from a user")]
|
||||
public async Task Remove([Summary("The user to remove levels/xp from")] SocketGuildUser user, [Summary("The amount of levels/xp to remove")] int value, [Summary("The type to remove (levels/xp)")] ModifyType type = ModifyType.Levels)
|
||||
{
|
||||
User usr = Data.users.Data.FindOrDefault(x => x.userID == user.Id);
|
||||
|
||||
if (usr == null)
|
||||
{
|
||||
usr = new() { userID = user.Id };
|
||||
Data.users.Data.Add(usr);
|
||||
}
|
||||
|
||||
Level lvl = usr.level;
|
||||
|
||||
if (lvl == null)
|
||||
{
|
||||
lvl = new();
|
||||
usr.level = lvl;
|
||||
}
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = user.Mention + " has has their " + Code(type.ToString()) + " removed, from ",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = type + " Removed",
|
||||
};
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case ModifyType.Level or ModifyType.Levels:
|
||||
if (lvl.level < value)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "User does not have enough levels to remove");
|
||||
return;
|
||||
}
|
||||
|
||||
double percent = lvl.xp / lvl.MaxXP;
|
||||
|
||||
e.Description += Code("Level " + lvl.level) + " to " + Code("Level " + (lvl.level - value));
|
||||
lvl.level -= value;
|
||||
lvl.xp = (int)Math.Round(percent * lvl.MaxXP);
|
||||
break;
|
||||
|
||||
case ModifyType.XP:
|
||||
if (lvl.TotalXP < value)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "User does not have enough xp to remove");
|
||||
return;
|
||||
}
|
||||
|
||||
e.Description += Code(lvl.xp + " XP") + " to " + Code(lvl.xp - value + " XP");
|
||||
|
||||
while (value >= lvl.MaxXP)
|
||||
{
|
||||
value -= lvl.MaxXP;
|
||||
lvl.xp--;
|
||||
}
|
||||
|
||||
lvl.xp -= value;
|
||||
break;
|
||||
}
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("reset")]
|
||||
[RequireUserPermission(GuildPermission.ManageGuild)]
|
||||
[Summary("Resets all levels or xp for a user")]
|
||||
public async Task Reset([Summary("The user to reset levels/xp of")] SocketGuildUser user, [Summary("The type to reset (levels/xp)")] ModifyType type = ModifyType.Levels)
|
||||
{
|
||||
User usr = Data.users.Data.FindOrDefault(x => x.userID == user.Id);
|
||||
|
||||
if (usr == null)
|
||||
{
|
||||
usr = new() { userID = user.Id };
|
||||
Data.users.Data.Add(usr);
|
||||
}
|
||||
|
||||
Level lvl = usr.level;
|
||||
|
||||
if (lvl == null)
|
||||
{
|
||||
lvl = new();
|
||||
usr.level = lvl;
|
||||
}
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = user.Mention + " has has their " + Code(type.ToString()) + " reset to " + Code("0"),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = type + " Reset",
|
||||
};
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case ModifyType.Level or ModifyType.Levels:
|
||||
double percent = lvl.xp / lvl.MaxXP;
|
||||
|
||||
lvl.level = 0;
|
||||
lvl.xp = (int)Math.Round(percent * 200);
|
||||
break;
|
||||
|
||||
case ModifyType.XP:
|
||||
lvl.xp = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("set")]
|
||||
[RequireUserPermission(GuildPermission.ManageGuild)]
|
||||
[Summary("Sets a user's level or xp")]
|
||||
public async Task Set([Summary("The user to set levels/xp of")] SocketGuildUser user, [Summary("The amount of levels/xp to set")] int value, [Summary("The type to set (levels/xp)")] ModifyType type = ModifyType.Levels)
|
||||
{
|
||||
User usr = Data.users.Data.FindOrDefault(x => x.userID == user.Id);
|
||||
|
||||
if (usr == null)
|
||||
{
|
||||
usr = new() { userID = user.Id };
|
||||
Data.users.Data.Add(usr);
|
||||
}
|
||||
|
||||
Level lvl = usr.level;
|
||||
|
||||
if (lvl == null)
|
||||
{
|
||||
lvl = new();
|
||||
usr.level = lvl;
|
||||
}
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = user.Mention + " has has their " + Code(type.ToString()) + " set from ",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = type + " Changed",
|
||||
};
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case ModifyType.Level or ModifyType.Levels:
|
||||
e.Description += Code("Level " + lvl.level) + " to " + Code("Level " + value);
|
||||
|
||||
double xp = lvl.xp;
|
||||
if (value < lvl.level) xp = lvl.xp / lvl.MaxXP;
|
||||
|
||||
lvl.level = value;
|
||||
|
||||
if (value < lvl.level) lvl.xp = (int)Math.Round(xp * lvl.MaxXP);
|
||||
break;
|
||||
|
||||
case ModifyType.XP:
|
||||
e.Description += Code(lvl.xp + " XP") + " to " + Code(value + " XP");
|
||||
lvl.xp += value;
|
||||
|
||||
while (lvl.xp >= lvl.MaxXP)
|
||||
{
|
||||
lvl.xp -= lvl.MaxXP;
|
||||
lvl.level++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("speed get")]
|
||||
[Summary("Shows the current xp cooldown")]
|
||||
public async Task SpeedGet()
|
||||
{
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "The current cooldown between messages is `" + Data.misc.Data.levelCooldown + " Second",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "XP Speed",
|
||||
};
|
||||
if (Data.misc.Data.levelCooldown != 1) e.Description += "s";
|
||||
e.Description += "`";
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("speed reset")]
|
||||
[RequireUserPermission(GuildPermission.ManageGuild)]
|
||||
[Summary("Sets the current xp cooldown to 60 seconds")]
|
||||
public async Task SpeedReset()
|
||||
{
|
||||
Data.misc.Data.levelCooldown = 60;
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "Successfully set the current xp cooldown to: " + Code("60 Seconds"),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Reset xp cooldown",
|
||||
};
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("speed set")]
|
||||
[RequireUserPermission(GuildPermission.ManageGuild)]
|
||||
[Summary("Sets the current xp cooldown")]
|
||||
public async Task SpeedSet([Summary("The time in seconds of the xp cooldown")] int seconds)
|
||||
{
|
||||
int old = Data.misc.Data.levelCooldown;
|
||||
Data.misc.Data.levelCooldown = seconds;
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "Successfully set changelog channel to: `" + seconds + " Second",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Set changelog channel",
|
||||
};
|
||||
if (seconds != 1) e.Description += "s";
|
||||
e.Description += "`\n(Previous: `" + old + " Second";
|
||||
|
||||
if (old != 1) e.Description += "s";
|
||||
e.Description += "`)";
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
// end commands
|
||||
|
||||
public static async Task LevelHandler(SocketUserMessage msg)
|
||||
{
|
||||
User usr = Data.users.Data.FindOrDefault(x => x.userID == msg.Author.Id);
|
||||
Level level = null;
|
||||
if (usr == null)
|
||||
{
|
||||
level = new();
|
||||
|
||||
usr = new()
|
||||
{
|
||||
currentMute = new(),
|
||||
level = level,
|
||||
tickets = 0,
|
||||
userID = msg.Author.Id,
|
||||
warns = new(),
|
||||
};
|
||||
|
||||
Data.users.Data.Add(usr);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (usr.level == null) usr.level = new();
|
||||
level = usr.level;
|
||||
}
|
||||
|
||||
level.msgs++;
|
||||
if (level.lastCountedMsg.AddSeconds(Data.misc.Data.levelCooldown) < msg.Timestamp.DateTime)
|
||||
{
|
||||
level.countedMsgs++;
|
||||
level.lastCountedMsg = msg.Timestamp.DateTime;
|
||||
level.xp += new Random().Next(15, 26);
|
||||
|
||||
if (level.xp >= level.MaxXP)
|
||||
{
|
||||
level.xp -= level.MaxXP;
|
||||
usr.level.level++;
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = msg.Author.Mention + ", you have leveled up to " + Code("Level " + usr.level.level) + ". You need " + Code(level.MaxXP + " XP") + " to get to the next level",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Leveled Up!",
|
||||
};
|
||||
string send = "";
|
||||
if (Data.misc.Data.levelMention) send = msg.Author.Mention;
|
||||
|
||||
await msg.Channel.SendFileAsync(Data.appPath + "/data/constant/level-imgs/" + Math.Clamp(level.level, -1, 101) + ".png", send, false, e.Build());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// end of methods
|
||||
|
||||
public enum ModifyType
|
||||
{
|
||||
Level,
|
||||
Levels,
|
||||
XP,
|
||||
}
|
||||
}
|
||||
}
|
||||
175
Nerd's Teaser Bot/Modules/Commands/LogModule.cs
Normal file
175
Nerd's Teaser Bot/Modules/Commands/LogModule.cs
Normal file
@ -0,0 +1,175 @@
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using NerdsTeaserBot.Misc;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using static Discord.Format;
|
||||
using static NerdsTeaserBot.Const;
|
||||
|
||||
namespace NerdsTeaserBot.Modules
|
||||
{
|
||||
[Group("log")]
|
||||
[Name("Logging")]
|
||||
[Summary("Commands for setting log channels and information")]
|
||||
public class LogModule : ModuleBase<SocketCommandContext>
|
||||
{
|
||||
[Command("channel get")]
|
||||
[Summary("The current logging channel of the bot")]
|
||||
public async Task ChannelGet()
|
||||
{
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "The current logging channel is: " + Italics("<#" + Data.misc.Data.logChannel + ">"),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Current Logging Channel",
|
||||
};
|
||||
|
||||
if (Data.misc.Data.logChannel == default) e.Description = "No current logging channel found. Use " + Code("n;log channel set") + " to set it!";
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("channel reset")]
|
||||
[RequireUserPermission(GuildPermission.ManageChannels)]
|
||||
[Summary("Resets the logging channel of the bot back to none")]
|
||||
public async Task ChannelReset()
|
||||
{
|
||||
Data.misc.Data.logChannel = default;
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "Successfully set the current logging channel to: " + Code("None"),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Reset Logging Channel",
|
||||
};
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("channel set")]
|
||||
[RequireUserPermission(GuildPermission.ManageChannels)]
|
||||
[Summary("Sets the given channel to the logging channel of the bot")]
|
||||
public async Task ChannelSet([Summary("The Text Channel to set the logging channel to")] ITextChannel channel)
|
||||
{
|
||||
if (channel.Guild.Id != Context.Guild.Id)
|
||||
{
|
||||
LogMessage(LogSeverity.Error, "Text channel is not in this server");
|
||||
return;
|
||||
}
|
||||
|
||||
ulong old = Data.misc.Data.logChannel;
|
||||
Data.misc.Data.logChannel = channel.Id;
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "Successfully set logging channel to: " + Italics(channel.Mention),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Set Logging Channel",
|
||||
};
|
||||
|
||||
if (old != default) e.Description += "\n(Previous: " + Italics("<#" + old + ">") + ")";
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
// end commands
|
||||
|
||||
public static void LogMessage(Exception exe) => LogMessage(LogSeverity.Error, exe.Message, exe.Source);
|
||||
public static void LogMessage(LogSeverity severity, Exception exe) => LogMessage(severity, exe.Message, exe.Source);
|
||||
public static void LogMessage(LogMessage arg) => LogMessage(arg.Severity, arg.Message, arg.Source);
|
||||
public static void LogMessage(LogSeverity severity, string message, string source = "", IUserMessage edit = null, IUserMessage reply = null)
|
||||
{
|
||||
if (Internals.context == null) return;
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.SeverityColors[(int)severity],
|
||||
Description = message,
|
||||
Footer = new() { Text = source },
|
||||
Timestamp = DateTime.Now,
|
||||
Title = severity.ToString() + " Message",
|
||||
};
|
||||
|
||||
if (edit == null)
|
||||
{
|
||||
if (reply != null) Internals.context.Channel.SendMessageAsync("", false, e.Build(), messageReference: new(reply.Id));
|
||||
else Internals.context.Channel.SendMessageAsync("", false, e.Build());
|
||||
}
|
||||
else edit.ModifyAsync(x =>
|
||||
{
|
||||
x.Content = "";
|
||||
x.Embed = e.Build();
|
||||
});
|
||||
|
||||
Log.Write("The bot has thrown a(n) " + severity.ToString() + " Message: '" + message + "' Source: '" + source + "'");
|
||||
}
|
||||
|
||||
// begin log handlers
|
||||
|
||||
/*public static async Task ChannelCreatedHandler(SocketChannel channel)
|
||||
{
|
||||
|
||||
}
|
||||
public static async Task ChannelDeletedHandler(SocketChannel channel)
|
||||
{
|
||||
|
||||
}
|
||||
public static async Task ChannelModifiedHandler(SocketChannel beforeC, SocketChannel afterC)
|
||||
{
|
||||
|
||||
}
|
||||
public static async Task RoleCreatedHandler(SocketRole role)
|
||||
{
|
||||
|
||||
}
|
||||
public static async Task RoleDeletedHandler(SocketRole role)
|
||||
{
|
||||
|
||||
}
|
||||
public static async Task RoleModifiedHandler(SocketRole beforeR, SocketRole afterR)
|
||||
{
|
||||
|
||||
}
|
||||
public static async Task MessageDeletedHandler(Cacheable<IMessage, ulong> message, ISocketMessageChannel channel)
|
||||
{
|
||||
|
||||
}
|
||||
public static async Task MessageEditedHandler(Cacheable<IMessage, ulong> beforeMsg, SocketMessage afterMsg, ISocketMessageChannel channel)
|
||||
{
|
||||
|
||||
}
|
||||
public static async Task MessagesPurgedHandler(IReadOnlyCollection<Cacheable<IMessage, ulong>> messages, ISocketMessageChannel channel)
|
||||
{
|
||||
|
||||
}
|
||||
public static async Task GuildModifiedHandler(SocketGuild beforeG, SocketGuild afterG)
|
||||
{
|
||||
|
||||
}
|
||||
public static async Task UserBannedHandler(SocketUser user, SocketGuild guild)
|
||||
{
|
||||
|
||||
}
|
||||
public static async Task UserJoinedHandler(SocketUser user)
|
||||
{
|
||||
|
||||
}
|
||||
public static async Task UserLeftHandler(SocketUser user)
|
||||
{
|
||||
|
||||
}
|
||||
public static async Task UserModifiedHandler(SocketUser beforeU, SocketUser afterU)
|
||||
{
|
||||
|
||||
}
|
||||
public static async Task UserUnbannedHandler(SocketUser user, SocketGuild guild)
|
||||
{
|
||||
|
||||
}*/
|
||||
}
|
||||
}
|
||||
111
Nerd's Teaser Bot/Modules/Commands/MessagingModule.cs
Normal file
111
Nerd's Teaser Bot/Modules/Commands/MessagingModule.cs
Normal file
@ -0,0 +1,111 @@
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.Rest;
|
||||
using Discord.WebSocket;
|
||||
using NerdsTeaserBot.Misc;
|
||||
using NerdsTeaserBot.Modules.Attributes;
|
||||
using NerdsTeaserBot.Modules.Models;
|
||||
using Nerd_STF.Extensions;
|
||||
using Nerd_STF.File.Saving;
|
||||
using Nerd_STF.Lists;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using static Discord.Format;
|
||||
using static NerdsTeaserBot.Const;
|
||||
|
||||
namespace NerdsTeaserBot.Modules.Commands
|
||||
{
|
||||
[Group("message")]
|
||||
[Name("Messaging")]
|
||||
[Summary("Commands about messaging services")]
|
||||
public class MessagingModule : ModuleBase<SocketCommandContext>
|
||||
{
|
||||
[Command("channel get")]
|
||||
[Summary("The current message channel of the bot")]
|
||||
public async Task ChannelGet()
|
||||
{
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "The current message channel is: " + Italics("<#" + Data.misc.Data.messagingC + ">"),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Current Message Channel",
|
||||
};
|
||||
|
||||
if (Data.misc.Data.messagingC == default) e.Description = "No current message channel found. Use " + Code("n;message channel set") + " to set it!";
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("channel reset")]
|
||||
[RequireUserPermission(GuildPermission.ManageChannels)]
|
||||
[Summary("Resets the message channel of the bot back to none")]
|
||||
public async Task ChannelReset()
|
||||
{
|
||||
Data.misc.Data.messagingC = default;
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "Successfully set the current message channel to: " + Code("None"),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Reset Message Channel",
|
||||
};
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("channel set")]
|
||||
[RequireUserPermission(GuildPermission.ManageChannels)]
|
||||
[Summary("Sets the given channel to the message channel of the bot")]
|
||||
public async Task ChannelSet([Summary("The Text Channel to set the message channel to")] ITextChannel channel)
|
||||
{
|
||||
if (channel.Guild.Id != Context.Guild.Id)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "Text channel is not in this server");
|
||||
return;
|
||||
}
|
||||
|
||||
ulong old = Data.misc.Data.messagingC;
|
||||
Data.misc.Data.messagingC = channel.Id;
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "Successfully set message channel to: " + Italics(channel.Mention),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Set Message Channel",
|
||||
};
|
||||
|
||||
if (old != default) e.Description += "\n(Previous: " + Italics("<#" + old + ">") + ")";
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
// end commands
|
||||
|
||||
public static async Task UserJoinedHandler(SocketGuildUser user)
|
||||
{
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "Welcome, " + user.Mention + ", to " + Bold(user.Guild.Name) + "!",
|
||||
Timestamp = DateTime.Now,
|
||||
};
|
||||
|
||||
await user.Guild.GetTextChannel(Data.misc.Data.messagingC).SendMessageAsync("", false, e.Build());
|
||||
}
|
||||
public static async Task UserLeftHandler(SocketGuildUser user)
|
||||
{
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "Goodbye, " + user.Mention + "! We hope you come back soon!",
|
||||
Timestamp = DateTime.Now,
|
||||
};
|
||||
|
||||
await user.Guild.GetTextChannel(Data.misc.Data.messagingC).SendMessageAsync("", false, e.Build());
|
||||
}
|
||||
}
|
||||
}
|
||||
833
Nerd's Teaser Bot/Modules/Commands/ModerationModule.cs
Normal file
833
Nerd's Teaser Bot/Modules/Commands/ModerationModule.cs
Normal file
@ -0,0 +1,833 @@
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using NerdsTeaserBot.Misc;
|
||||
using NerdsTeaserBot.Modules;
|
||||
using NerdsTeaserBot.Modules.Extensions;
|
||||
using NerdsTeaserBot.Modules.Models;
|
||||
using Nerd_STF;
|
||||
using Nerd_STF.Lists;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using static Discord.Format;
|
||||
using static NerdsTeaserBot.Const;
|
||||
|
||||
namespace NerdsTeaserBot.Modules.Commands
|
||||
{
|
||||
[Name("Moderation")]
|
||||
[Summary("Commands about moderating and watching over users")]
|
||||
public class ModerationModule : ModuleBase<SocketCommandContext>
|
||||
{
|
||||
[Command("kick")]
|
||||
[RequireUserPermission(GuildPermission.KickMembers)]
|
||||
[Summary("Kicks a user from the server. The user can always join back with an invite")]
|
||||
public async Task Kick([Summary("The user to kick")] SocketGuildUser user, [Remainder][Summary("The reason to kick the user for. The user will be DMed this reason")] string reason = "No Reason Specified")
|
||||
{
|
||||
bool dat = await MainKickSystem(user, reason);
|
||||
|
||||
if (dat) return;
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Color.Red,
|
||||
Description = "You have been kicked by " + Code(Context.User.Username + "#" + Context.User.Discriminator) + " for reason: " + Code(reason),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "You have been kicked from " + Context.Guild.Name,
|
||||
};
|
||||
|
||||
await user.DMUserAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("kick ghost")]
|
||||
[RequireUserPermission(GuildPermission.KickMembers)]
|
||||
[Summary("Kicks a user from the server (without DMing them). The user can always join back with an invite")]
|
||||
public async Task KickGhost([Summary("The user to kick")] SocketGuildUser user, [Remainder][Summary("The reason to kick the user for")] string reason = "No Reason Specified") => await MainKickSystem(user, reason);
|
||||
|
||||
[Command("message")]
|
||||
[RequireUserPermission(GuildPermission.ManageMessages)]
|
||||
[Summary("Send a message a user via a DM (This is not the way to respond to a ModMail message)")]
|
||||
public async Task Message([Summary("The user to DM")] IUser user, [Remainder][Summary("The message to DM to the user")] string message)
|
||||
{
|
||||
EmbedAuthorBuilder a = new()
|
||||
{
|
||||
IconUrl = Context.User.GetAvatarUrl(),
|
||||
Name = "Message from " + Context.User.Username + "#" + Context.User.Discriminator,
|
||||
};
|
||||
|
||||
await MainMessageSystem(user, a, message);
|
||||
}
|
||||
|
||||
[Command("message anon")]
|
||||
[RequireUserPermission(GuildPermission.ManageMessages)]
|
||||
[Summary("Send a message a user via a DM (This is not the way to respond to a ModMail message). Going anonymous hides your username from the recipient")]
|
||||
public async Task MessageAnon([Summary("The user to DM")] IUser user, [Remainder][Summary("The message to DM to the user")] string message)
|
||||
{
|
||||
EmbedAuthorBuilder a = new()
|
||||
{
|
||||
IconUrl = Context.Guild.IconUrl,
|
||||
Name = "Message from ",
|
||||
};
|
||||
|
||||
if (((SocketGuildUser)Context.User).Roles.Count == 1) a.Name += "a user";
|
||||
else
|
||||
{
|
||||
SocketRole highest = null;
|
||||
foreach (SocketRole r in ((SocketGuildUser)Context.User).Roles)
|
||||
{
|
||||
if (highest == null) highest = r;
|
||||
else if (highest.Position < r.Position) highest = r;
|
||||
}
|
||||
|
||||
int count = new List<SocketGuildUser>(Context.Guild.Users).FindAll(x => new List<SocketRole>(x.Roles).Contains(highest)).Length;
|
||||
|
||||
if (count == 1) a.Name += "a " + highest.Name;
|
||||
else
|
||||
{
|
||||
a.Name += "the " + highest.Name;
|
||||
if (!highest.Name.EndsWith("s")) a.Name += "s";
|
||||
}
|
||||
}
|
||||
|
||||
a.Name += " in " + Context.Guild.Name;
|
||||
|
||||
await MainMessageSystem(user, a, message);
|
||||
}
|
||||
|
||||
[Command("mute")]
|
||||
[RequireUserPermission(GuildPermission.ManageGuild & GuildPermission.ManageRoles)]
|
||||
[Summary("Mutes a user for a specified amount of time")]
|
||||
public async Task Mute([Summary("The user to mute")] IUser user, [Summary("The time to mute for. Use '---' for no limit")] string time, [Remainder][Summary("The reason to mute the user for")] string reason = "No Reason Specified")
|
||||
{
|
||||
DateTime release = DateTime.Now;
|
||||
|
||||
string timeS = "";
|
||||
if (time == "---")
|
||||
{
|
||||
release = DateTime.MaxValue;
|
||||
timeS = "indefinitely";
|
||||
}
|
||||
else if (!int.TryParse(time.Remove(time.Length - 1), out _))
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "Time was not in the correct format" +
|
||||
"\n(must include a unit of time at the end of the string)");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
(int, char) dat = new();
|
||||
dat.Item1 = int.Parse(time[0..(time.Length - 1)]);
|
||||
dat.Item2 = time[^1];
|
||||
|
||||
switch (dat.Item2)
|
||||
{
|
||||
case 's':
|
||||
release = release.AddSeconds(dat.Item1);
|
||||
timeS = dat.Item1 + " Seconds";
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
release = release.AddMinutes(dat.Item1);
|
||||
timeS = dat.Item1 + " Minutes";
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
release = release.AddHours(dat.Item1);
|
||||
timeS = dat.Item1 + " Hours";
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
release = release.AddDays(dat.Item1);
|
||||
timeS = dat.Item1 + " Days";
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
release = release.AddDays(dat.Item1 * 7);
|
||||
timeS = dat.Item1 + " Weeks";
|
||||
break;
|
||||
|
||||
case 'y':
|
||||
release = release.AddDays(dat.Item1 * 365.24238);
|
||||
timeS = dat.Item1 + " Years";
|
||||
break;
|
||||
|
||||
default:
|
||||
LogModule.LogMessage(LogSeverity.Error, "Time was not in the correct format" +
|
||||
"\n(unit of time was incorrect)");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Color.Red,
|
||||
Description = user.Mention + " has been muted ",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "User has been muted"
|
||||
};
|
||||
|
||||
if (timeS.ToLower().Trim() != "indefinitely") e.Description += "for ";
|
||||
e.Description += Code(timeS) + " for reason: " + Code(reason);
|
||||
|
||||
Mute m = new()
|
||||
{
|
||||
moderator = Context.User.Id,
|
||||
reason = reason,
|
||||
release = release,
|
||||
start = DateTime.Now,
|
||||
unmute = null,
|
||||
};
|
||||
User usr = Data.users.Data.FindOrDefault(x => x.userID == user.Id);
|
||||
if (usr == default)
|
||||
{
|
||||
Data.users.Data.Add(new User()
|
||||
{
|
||||
currentMute = m,
|
||||
userID = user.Id,
|
||||
warns = new(),
|
||||
});
|
||||
}
|
||||
else usr.currentMute = m;
|
||||
|
||||
Embed b1 = e.Build();
|
||||
|
||||
e.Description = "You have been muted for ";
|
||||
|
||||
if (timeS.ToLower().Trim() != "indefinitely") e.Description += "for ";
|
||||
e.Description += Code(timeS) + " by " + Context.User.Mention + " for reason: " + Code(reason);
|
||||
|
||||
e.Title = "You have been muted in " + Context.Guild.Name;
|
||||
|
||||
e.WithFooter("Your mute expires at: " + release.ToString());
|
||||
|
||||
Embed b2 = e.Build();
|
||||
|
||||
await user.DMUserAsync("", false, b2);
|
||||
|
||||
await ReplyAsync("", false, b1);
|
||||
}
|
||||
// these two commands have practically the same code. remember to change both when editing code
|
||||
[Command("mute ghost")]
|
||||
[RequireUserPermission(GuildPermission.ManageGuild & GuildPermission.ManageRoles)]
|
||||
[Summary("Mutes a user for a specified amount of time (without DMing them)")]
|
||||
public async Task MuteGhost([Summary("The user to mute")] IUser user, [Summary("The time to mute for. Use '---' for no limit")] string time, [Remainder][Summary("The reason to mute the user for")] string reason = "No Reason Specified")
|
||||
{
|
||||
DateTime release = DateTime.Now;
|
||||
|
||||
string timeS = "";
|
||||
if (time == "---")
|
||||
{
|
||||
release = DateTime.MaxValue;
|
||||
timeS = "indefinitely";
|
||||
}
|
||||
else if (!int.TryParse(time.Remove(time.Length - 1), out _))
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "Time was not in the correct format" +
|
||||
"\n(must include a unit of time at the end of the string)");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
(int, char) dat = new();
|
||||
dat.Item1 = int.Parse(time[0..(time.Length - 1)]);
|
||||
dat.Item2 = time[^1];
|
||||
|
||||
switch (dat.Item2)
|
||||
{
|
||||
case 's':
|
||||
release = release.AddSeconds(dat.Item1);
|
||||
timeS = dat.Item1 + " Seconds";
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
release = release.AddMinutes(dat.Item1);
|
||||
timeS = dat.Item1 + " Minutes";
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
release = release.AddHours(dat.Item1);
|
||||
timeS = dat.Item1 + " Hours";
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
release = release.AddDays(dat.Item1);
|
||||
timeS = dat.Item1 + " Days";
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
release = release.AddDays(dat.Item1 * 7);
|
||||
timeS = dat.Item1 + " Weeks";
|
||||
break;
|
||||
|
||||
case 'y':
|
||||
release = release.AddDays(dat.Item1 * 365.24238);
|
||||
timeS = dat.Item1 + " Years";
|
||||
break;
|
||||
|
||||
default:
|
||||
LogModule.LogMessage(LogSeverity.Error, "Time was not in the correct format" +
|
||||
"\n(unit of time was incorrect)");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Color.Red,
|
||||
Description = user.Mention + " has been muted ",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "User has been muted"
|
||||
};
|
||||
|
||||
if (timeS.ToLower().Trim() != "indefinitely") e.Description += "for ";
|
||||
e.Description += Code(timeS) + " for reason: " + Code(reason);
|
||||
|
||||
Mute m = new()
|
||||
{
|
||||
moderator = Context.User.Id,
|
||||
reason = reason,
|
||||
release = release,
|
||||
start = DateTime.Now,
|
||||
unmute = null,
|
||||
};
|
||||
User usr = Data.users.Data.FindOrDefault(x => x.userID == user.Id);
|
||||
if (usr == default)
|
||||
{
|
||||
Data.users.Data.Add(new User()
|
||||
{
|
||||
currentMute = m,
|
||||
userID = user.Id,
|
||||
warns = new(),
|
||||
});
|
||||
}
|
||||
else usr.currentMute = m;
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("mute info")]
|
||||
[Summary("Shows mute data on the user executing the command")]
|
||||
public async Task MuteInfo() => await MuteInfo(Context.User);
|
||||
|
||||
[Command("mute info")]
|
||||
[Summary("Shows mute data on a specific person")]
|
||||
public async Task MuteInfo([Summary("The user to show info on")] IUser user)
|
||||
{
|
||||
User usr = Data.users.Data.FindOrDefault(x => x.userID == user.Id);
|
||||
|
||||
if (usr == default)
|
||||
{
|
||||
usr = new() { userID = user.Id };
|
||||
Data.users.Data.Add(usr);
|
||||
}
|
||||
|
||||
Mute mute = usr.currentMute;
|
||||
|
||||
if (mute == null)
|
||||
{
|
||||
mute = new();
|
||||
usr.currentMute = mute;
|
||||
}
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "User is ",
|
||||
};
|
||||
|
||||
e.AddField("Mute Info", Italics("Muted At:") + " " + Code(mute.start.ToString()) +
|
||||
"\n" + Italics("Will Unmute At:") + " " + Code(mute.release.ToString()) +
|
||||
"\n" + Italics("Muted By:") + " <@" + mute.moderator + ">" +
|
||||
"\n" + Italics("Mute Reason:") + " " + Code(mute.reason));
|
||||
|
||||
if (mute.IsMuted)
|
||||
{
|
||||
e.Color = Color.Red;
|
||||
e.Description = "Mute info is below:";
|
||||
}
|
||||
else
|
||||
{
|
||||
Mute.Unmute unmute = mute.unmute;
|
||||
|
||||
e.Color = Color.Green;
|
||||
e.Description = "Mute and unmute info is below:";
|
||||
e.Title += "not ";
|
||||
|
||||
e.AddField("Unmute Info", Italics("Unmuted At:") + " " + Code(unmute.time.ToString()) +
|
||||
"\n" + Italics("Unmuted By:") + " <@" + unmute.moderator + ">" +
|
||||
"\n" + Italics("Unmute Reason:") + " " + Code(unmute.reason));
|
||||
}
|
||||
e.Title += "currently muted";
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("warn")]
|
||||
[RequireUserPermission(GuildPermission.ManageGuild)]
|
||||
[Summary("Warns a user")]
|
||||
public async Task Warn([Summary("The user to warn")] IUser user, [Remainder][Summary("The reason to warn the user with")] string reason = "No Reason Specified")
|
||||
{
|
||||
(EmbedBuilder, int, bool) dat = await MainWarnSystem(user, reason);
|
||||
|
||||
if (dat.Item3) return;
|
||||
|
||||
dat.Item1.Description = "You have been warned by " + Context.User.Mention + " for reason: " + Code(reason) +
|
||||
"\n" + Italics("This is your " + Code(Nerd_STF.Misc.PlaceMaker(dat.Item2)) + " warning.");
|
||||
dat.Item1.Title = "You have been warned in " + Context.Guild.Name + "!";
|
||||
|
||||
await user.DMUserAsync("", false, dat.Item1.Build());
|
||||
}
|
||||
|
||||
[Command("warn change")]
|
||||
[RequireUserPermission(GuildPermission.ManageGuild)]
|
||||
[Summary("Changes the warn reason of a specific warn")]
|
||||
public async Task WarnChange([Summary("The user to change the warn of")] IUser user, [Summary("The hash of the warn to change")] string hash, [Remainder] [Summary("The new reason to set the warn to")] string newReason)
|
||||
{
|
||||
if (Data.users.Data is null) Data.users.Data = new();
|
||||
|
||||
User usr = Data.users.Data.FindOrDefault(x => x.userID == user.Id);
|
||||
|
||||
if (usr == null)
|
||||
{
|
||||
usr = new() { userID = user.Id };
|
||||
Data.users.Data.Add(usr);
|
||||
}
|
||||
|
||||
if (usr.warns is null)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "User has no tracked warns, and as such cannot find a specific one");
|
||||
return;
|
||||
}
|
||||
|
||||
Warn warn = usr.warns.FindOrDefault(x => x.hash == hash);
|
||||
|
||||
if (warn == null)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "No warn exists on this user with the specified hash");
|
||||
return;
|
||||
}
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "Successfully changed " + user.Mention + "'s warn with reason " + Code(warn.reason) + " to have a new reason of " + Code(newReason),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Warn reason changed"
|
||||
};
|
||||
|
||||
warn.reason = newReason;
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("warn clear")]
|
||||
[RequireUserPermission(GuildPermission.ManageGuild)]
|
||||
[Summary("Clears a user of all warns currently tracked")]
|
||||
public async Task WarnClear([Summary("The user to clear the warns of")] IUser user)
|
||||
{
|
||||
(int, bool) dat = await MainWarnClearSystem(user);
|
||||
|
||||
if (dat.Item2) return;
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Color.Green,
|
||||
Description = "Your " + Code(dat.Item1.ToString()) + " warn",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "All warns cleared in " + Context.Guild.Name,
|
||||
};
|
||||
|
||||
if (dat.Item1 != 1) e.Description += "s";
|
||||
|
||||
e.Description += " have now been reset. Great job!";
|
||||
|
||||
await user.DMUserAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("warn clear ghost")]
|
||||
[RequireUserPermission(GuildPermission.ManageGuild)]
|
||||
[Summary("Clears a user of all warns currently tracked (without DMing them)")]
|
||||
public async Task WarnClearGhost([Summary("The user to clear the warns of")] IUser user) => await MainWarnClearSystem(user);
|
||||
|
||||
[Command("warn delete")]
|
||||
[RequireUserPermission(GuildPermission.ManageGuild)]
|
||||
[Summary("Deletes a warn with a given hash from a user's warn list")]
|
||||
public async Task WarnDelete([Summary("The user to delete the warn of")] IUser user, [Summary("The hash of the warn to delete")] string hash)
|
||||
{
|
||||
(User, Warn, bool) dat = await MainWarnDeleteSystem(user, hash);
|
||||
if (dat.Item3) return;
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Color.Green,
|
||||
Description = "One of your warnings has been deleted by " + Context.User.Mention +
|
||||
"\n" + Italics("More info about your deleted warning is below.") +
|
||||
"\n" +
|
||||
"\n" + Italics("Reason:") + " " + Code(dat.Item2.reason) +
|
||||
"\n" + Italics("Moderator:") + " <@" + dat.Item2.moderator + ">" +
|
||||
"\n" + Italics("Time:") + " " + Code(dat.Item2.time.ToString()) +
|
||||
"\n" + Italics("Hash:") + " " + Code(dat.Item2.hash),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Warn Deleted in " + Context.Guild.Name,
|
||||
};
|
||||
e.WithFooter("Use 'n;warn list' to see your total tracked warns!");
|
||||
|
||||
await user.DMUserAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("warn delete ghost")]
|
||||
[RequireUserPermission(GuildPermission.ManageGuild)]
|
||||
[Summary("Deletes a warn with a given hash from a user's warn list (without DMing them)")]
|
||||
public async Task WarnDeleteGhost([Summary("The user to delete the warn of")] IUser user, [Summary("The hash of the warn to delete")] string hash) => await MainWarnDeleteSystem(user, hash);
|
||||
|
||||
[Command("warn ghost")]
|
||||
[RequireUserPermission(GuildPermission.ManageGuild)]
|
||||
[Summary("Warns a user (without DMing them)")]
|
||||
public async Task WarnGhost([Summary("The user to warn")] IUser user, [Remainder][Summary("The reason to warn the user with")] string reason = "No Reason Specified") => await MainWarnSystem(user, reason + " [GHOST]");
|
||||
|
||||
[Command("warn info")]
|
||||
[Summary("Shows info about a user's warn")]
|
||||
public async Task WarnInfo([Summary("The user to find the warn of")] IUser user, [Summary("The hash of the warn to show")] string hash)
|
||||
{
|
||||
if (Data.users.Data is null) Data.users.Data = new();
|
||||
|
||||
User usr = Data.users.Data.FindOrDefault(x => x.userID == user.Id);
|
||||
|
||||
if (usr == null)
|
||||
{
|
||||
usr = new() { userID = user.Id };
|
||||
Data.users.Data.Add(usr);
|
||||
}
|
||||
|
||||
if (usr.warns is null) usr.warns = new();
|
||||
|
||||
Warn warn = usr.warns.FindOrDefault(x => x.hash == hash);
|
||||
|
||||
if (warn == null)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "No warn exists on this user with the specified hash");
|
||||
return;
|
||||
}
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = user.Mention + "'s warning info is below" +
|
||||
"\n" +
|
||||
"\n" + Italics("Reason:") + " " + Code(warn.reason) +
|
||||
"\n" + Italics("Moderator:") + " <@" + warn.moderator + ">" +
|
||||
"\n" + Italics("Time:") + " " + Code(warn.time.ToString()) +
|
||||
"\n" + Italics("Hash:") + " " + Code(warn.hash),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Warning Info",
|
||||
};
|
||||
e.WithFooter("Use 'n;warn list' to see the total tracked warns of this user!");
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("warn list")]
|
||||
[Summary("Lists all current warns of the user executing the command")]
|
||||
public async Task WarnList() => await WarnList(Context.User);
|
||||
[Command("warn list")]
|
||||
[Summary("Lists all current warns of a user")]
|
||||
public async Task WarnList([Summary("The warned user")] IUser user)
|
||||
{
|
||||
if (Data.users.Data is null) Data.users.Data = new();
|
||||
|
||||
User usr = Data.users.Data.FindOrDefault(x => x.userID == user.Id);
|
||||
|
||||
if (usr == null)
|
||||
{
|
||||
usr = new() { userID = user.Id };
|
||||
Data.users.Data.Add(usr);
|
||||
}
|
||||
|
||||
if (usr.warns is null) usr.warns = new();
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = user.Mention + " has been warned " + Code(usr.warns.Length.ToString()) + " time",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = user.Username + "#" + user.Discriminator + "'s warns",
|
||||
};
|
||||
|
||||
if (usr.warns.Length != 1) e.Description += "s";
|
||||
|
||||
foreach (Warn w in usr.warns) e.AddField(w.reason, Italics("Moderator:") + " " + "<@" + w.moderator + ">" +
|
||||
"\n" + Italics("Time:") + " " + Code(w.time.ToString()) +
|
||||
"\n" + Italics("Hash:") + " " + Code(w.hash));
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("unmute")]
|
||||
[RequireUserPermission(GuildPermission.ManageGuild & GuildPermission.ManageRoles)]
|
||||
[Summary("Unmutes a user")]
|
||||
public async Task Unmute([Summary("The user to unmute")] IUser user, [Remainder][Summary("The reason to unmute the user for")] string reason = "No Reason Specified")
|
||||
{
|
||||
User usr = Data.users.Data.FindOrDefault(x => x.userID == user.Id);
|
||||
if (usr == null)
|
||||
{
|
||||
usr = new() { userID = user.Id };
|
||||
Data.users.Data.Add(usr);
|
||||
}
|
||||
Mute m = usr.currentMute;
|
||||
if (m == null)
|
||||
{
|
||||
m = new();
|
||||
usr.currentMute = m;
|
||||
}
|
||||
if (!m.IsMuted)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "User is not currently muted. Use " + Code("n;mute") + " to mute them");
|
||||
return;
|
||||
}
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Color.Green,
|
||||
Description = user.Mention + " has been successfully unmuted for reason: " + Code(reason),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "User Unmuted",
|
||||
};
|
||||
e.WithFooter("Use 'n;mute info' for info on the user's current mute status");
|
||||
|
||||
Mute.Unmute unmute = new()
|
||||
{
|
||||
moderator = Context.User.Id,
|
||||
reason = reason,
|
||||
time = DateTime.Now,
|
||||
};
|
||||
|
||||
m.unmute = unmute;
|
||||
|
||||
await user.DMUserAsync("", false, UnmuteDMEmbed((IGuildUser)user, reason, Context.User).Build());
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
// these two commands have practically the same code. remember to change both when editing code
|
||||
[Command("unmute ghost")]
|
||||
[RequireUserPermission(GuildPermission.ManageGuild & GuildPermission.ManageRoles)]
|
||||
[Summary("Unmutes a user (without DMing them)")]
|
||||
public async Task UnmuteGhost([Summary("The user to unmute")] IUser user, [Remainder][Summary("The reason to unmute the user for")] string reason = "No Reason Specified")
|
||||
{
|
||||
User usr = Data.users.Data.FindOrDefault(x => x.userID == user.Id);
|
||||
if (usr == null)
|
||||
{
|
||||
usr = new()
|
||||
{
|
||||
currentMute = new(),
|
||||
userID = user.Id,
|
||||
};
|
||||
Data.users.Data.Add(usr);
|
||||
}
|
||||
Mute m = usr.currentMute;
|
||||
if (!m.IsMuted)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "User is not currently muted. Use " + Code("n;mute") + " to mute them");
|
||||
return;
|
||||
}
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Color.Green,
|
||||
Description = user.Mention + " has been successfully unmuted for reason: " + Code(reason),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "User Unmuted",
|
||||
};
|
||||
e.WithFooter("Use 'n;mute info' for info on the user's current mute status");
|
||||
|
||||
Mute.Unmute unmute = new()
|
||||
{
|
||||
moderator = Context.User.Id,
|
||||
reason = reason,
|
||||
time = DateTime.Now,
|
||||
};
|
||||
|
||||
m.unmute = unmute;
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
// end commands
|
||||
|
||||
public async Task<bool> MainKickSystem(SocketGuildUser user, string reason)
|
||||
{
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Color.Red,
|
||||
Description = user.Mention + " has been kicked from " + Code(Context.Guild.Name) + " for reason: " + Code(reason),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "User Kicked from Server",
|
||||
};
|
||||
|
||||
await user.KickAsync("Moderator: " + LogItem() + " | Reason: " + reason);
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
|
||||
return false;
|
||||
}
|
||||
public static async Task<bool> MainMessageSystem(IUser user, EmbedAuthorBuilder author, string message)
|
||||
{
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Author = author,
|
||||
Color = Colors.DefaultColor,
|
||||
Description = message,
|
||||
Timestamp = DateTime.Now,
|
||||
};
|
||||
|
||||
if((await user.DMUserAsync("", false, e.Build())).Item2)
|
||||
{
|
||||
e.Author = null;
|
||||
e.WithTitle("DM sent to " + user.Username + "#" + user.Discriminator);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
public async Task<(int, bool)> MainWarnClearSystem(IUser user)
|
||||
{
|
||||
if (Data.users.Data is null) Data.users.Data = new();
|
||||
|
||||
User usr = Data.users.Data.FindOrDefault(x => x.userID == user.Id);
|
||||
|
||||
if (usr == null)
|
||||
{
|
||||
usr = new() { userID = user.Id };
|
||||
Data.users.Data.Add();
|
||||
}
|
||||
|
||||
int originalAmount = 0;
|
||||
|
||||
if (usr.warns is not null) originalAmount = usr.warns.Length;
|
||||
|
||||
if (originalAmount == 0)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "User has no currently tracked warns, and as such cannot clear them");
|
||||
usr.warns = new();
|
||||
return (-1, true);
|
||||
}
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Color.Green,
|
||||
Description = user.Mention + "has gone from " + Code(originalAmount.ToString()) + " to " + Code("0") + " warns",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "User's warns have been cleared",
|
||||
};
|
||||
e.WithFooter("Use 'n;warn delete' to delete a specific warn by it's hash");
|
||||
|
||||
usr.warns = new();
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
|
||||
return (originalAmount, false);
|
||||
}
|
||||
public async Task<(User, Warn, bool)> MainWarnDeleteSystem(IUser user, string hash)
|
||||
{
|
||||
if (Data.users.Data is null)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "No user data is found");
|
||||
return (null, null, true);
|
||||
}
|
||||
|
||||
User usr = Data.users.Data.FindOrDefault(x => x.userID == user.Id);
|
||||
|
||||
if (usr == null)
|
||||
{
|
||||
usr = new() { userID = user.Id };
|
||||
Data.users.Data.Add(usr);
|
||||
}
|
||||
|
||||
if (usr.warns is null) usr.warns = new();
|
||||
|
||||
Warn warn = usr.warns.FindOrDefault(x => x.hash == hash);
|
||||
|
||||
if (warn == null)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "No warn exists on this user with the specified hash");
|
||||
return (null, null, true);
|
||||
}
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Color.Green,
|
||||
Description = "Deleted " + user.Mention + "'s warn." +
|
||||
"\n" + Italics("More info on that warn is below.") +
|
||||
"\n" +
|
||||
"\n" + Italics("Reason:") + " " + Code(warn.reason) +
|
||||
"\n" + Italics("Moderator:") + " <@" + warn.moderator + ">" +
|
||||
"\n" + Italics("Time:") + " " + Code(warn.time.ToString()) +
|
||||
"\n" + Italics("Hash:") + " " + Code(warn.hash),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Removed User Warn",
|
||||
};
|
||||
e.WithFooter("Use 'n;warn list' to see the total tracked warns of this user!");
|
||||
|
||||
usr.warns.Remove(warn);
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
|
||||
return (usr, warn, false);
|
||||
}
|
||||
public async Task<(EmbedBuilder, int, bool)> MainWarnSystem(IUser user, string reason)
|
||||
{
|
||||
Warn warn = new()
|
||||
{
|
||||
hash = Hashes.MD5(user.Mention + reason + DateTime.Now),
|
||||
moderator = Context.User.Id,
|
||||
reason = reason,
|
||||
time = DateTime.Now,
|
||||
};
|
||||
|
||||
int amount;
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Color.Red,
|
||||
Description = user.Mention + " has been warned for reason: " + Code(reason),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Warned User"
|
||||
};
|
||||
e.WithFooter("Warn Hash: " + warn.hash);
|
||||
if (reason.EndsWith(" [GHOST]")) e.Title = "Ghost " + e.Title;
|
||||
|
||||
int index = Data.users.Data.FindIndex(x => x.userID == user.Id);
|
||||
if (index == -1)
|
||||
{
|
||||
Data.users.Data.Add(new()
|
||||
{
|
||||
userID = user.Id,
|
||||
warns = new(warn),
|
||||
});
|
||||
amount = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Data.users.Data[index].warns.Add(warn);
|
||||
amount = Data.users.Data[index].warns.Length;
|
||||
}
|
||||
|
||||
e.Description += "\n" + Italics("This is their " + Code(Nerd_STF.Misc.PlaceMaker(amount)) + " warning");
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
|
||||
return (e, amount, false);
|
||||
}
|
||||
|
||||
public static EmbedBuilder UnmuteDMEmbed(IGuildUser user, string reason, IUser moderator)
|
||||
{
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Color.Green,
|
||||
Description = moderator + " has unmuted you for reason: " + Code(reason),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "You have been unmuted in " + user.Guild.Name,
|
||||
};
|
||||
e.WithFooter("Use 'n;mute info' for info on your current mute status");
|
||||
|
||||
return e;
|
||||
}
|
||||
}
|
||||
}
|
||||
562
Nerd's Teaser Bot/Modules/Commands/ModmailModule.cs
Normal file
562
Nerd's Teaser Bot/Modules/Commands/ModmailModule.cs
Normal file
@ -0,0 +1,562 @@
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using NerdsTeaserBot.Misc;
|
||||
using NerdsTeaserBot.Modules.Extensions;
|
||||
using NerdsTeaserBot.Modules.Models;
|
||||
using Nerd_STF.Extensions;
|
||||
using Nerd_STF.File.Saving;
|
||||
using Nerd_STF.Lists;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using static Discord.Format;
|
||||
using static NerdsTeaserBot.Const;
|
||||
|
||||
namespace NerdsTeaserBot.Modules.Commands
|
||||
{
|
||||
[Group("mm")]
|
||||
[Name("Modmail")]
|
||||
[Summary("Commands about Modmail and it's functions")]
|
||||
public class ModmailModule : ModuleBase<SocketCommandContext>
|
||||
{
|
||||
[Command("anon")]
|
||||
[RequireUserPermission(GuildPermission.ManageMessages)]
|
||||
[Summary("Sends an anonymous message to the recipient")]
|
||||
public async Task Anon()
|
||||
{
|
||||
SocketTextChannel ch = (SocketTextChannel)Context.Channel;
|
||||
|
||||
if (!ch.CategoryId.HasValue)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "Channel is not a ModMail ticket channel (Channel is not in any category)");
|
||||
return;
|
||||
}
|
||||
if (ch.CategoryId != Data.consts.Data.modmailCategory)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "Channel is not a ModMail ticket channel (Channel category is not the specified ModMail category. Use " + Code("n;mm category set") + " to set it!)");
|
||||
return;
|
||||
}
|
||||
if (ch.Topic.Trim().ToLower().Contains("archive"))
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "ModMail ticket has been archived");
|
||||
return;
|
||||
}
|
||||
|
||||
ulong userId = ulong.Parse(ch.Topic.Substring(9, 18));
|
||||
|
||||
EmbedAuthorBuilder a = new()
|
||||
{
|
||||
IconUrl = Context.Client.CurrentUser.GetAvatarUrl(),
|
||||
Name = "From ModMail Recipients",
|
||||
};
|
||||
|
||||
await SendModMailMessage(a, Context.Message, await Internals.client.GetUser(userId).GetOrCreateDMChannelAsync());
|
||||
if (new List<IMessage>(await ch.GetMessagesAsync().FlattenAsync()).FindAll(x => x != null).Length < 4) await SuccessModMailMessage(ch, true);
|
||||
}
|
||||
|
||||
[Command("archive")]
|
||||
[RequireUserPermission(GuildPermission.ManageMessages & GuildPermission.ManageChannels)]
|
||||
[Summary("Pauses communication in a ModMail thread and saves all communication in a text file (this does not delete the ticket)")]
|
||||
public async Task Archive([Remainder][Summary("The reason you have to archive the ticket")] string reason = "No Reason Specified")
|
||||
{
|
||||
if (Context.Channel is INestedChannel nest)
|
||||
{
|
||||
SocketTextChannel ch = (SocketTextChannel)Context.Channel;
|
||||
|
||||
if (nest.CategoryId != Data.consts.Data.modmailCategory)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "Channel is not a ModMail ticket channel (Channel category is not the specified ModMail category. Use " + Code("n;mm category set") + " to set it!)");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ch.Topic.Trim().ToLower().Contains("archive"))
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "ModMail ticket has already been archived");
|
||||
return;
|
||||
}
|
||||
|
||||
ulong userId = ulong.Parse(ch.Topic.Substring(9, 18));
|
||||
IUser user = Context.Client.GetUser(userId);
|
||||
User usr = Data.users.Data.FindOrDefault(x => x.userID == userId);
|
||||
|
||||
int num = 0;
|
||||
|
||||
if (usr != null) num = usr.tickets - 1;
|
||||
|
||||
string folder = Data.appPath + "/data/files-" + Context.Guild.Id + "/tickets/";
|
||||
|
||||
TextFile save = new(folder + userId + "-" + num + ".ticket");
|
||||
|
||||
string add = "Nerd's Teaser Bot - Ticket Transcript\n" +
|
||||
"=========================\n" +
|
||||
"Ticket Info is below:\n" +
|
||||
"\n" +
|
||||
"Archiving Reason: " + reason + "\n" +
|
||||
"=========================\n" +
|
||||
"User Info is below:\n" +
|
||||
"\n" +
|
||||
"Full Name: ";
|
||||
|
||||
if (user == null) add += "-- Unknown --";
|
||||
else add += user.Username + "#" + user.Discriminator;
|
||||
add += "\n";
|
||||
|
||||
add += "User ID: ";
|
||||
if (user == null) add += "-- Unknown --";
|
||||
else add += user.Id.ToString();
|
||||
add += "\n";
|
||||
|
||||
add += "User Is Muted: ";
|
||||
if (usr == null || usr.currentMute == null) add += "False";
|
||||
else add += usr.currentMute.IsMuted.ToString();
|
||||
add += "\n";
|
||||
|
||||
add += "Ticket Count: ";
|
||||
if (usr == null) add += "1 Ticket";
|
||||
else
|
||||
{
|
||||
add += usr.tickets + " Ticket";
|
||||
if (usr.tickets != 1) add += "s";
|
||||
}
|
||||
add += "\n";
|
||||
|
||||
add += "Warn Count: ";
|
||||
if (usr == null || usr.warns is null) add += "0 Warns";
|
||||
else
|
||||
{
|
||||
add += usr.warns.Length + " Warns";
|
||||
if (usr.warns.Length != 1) add += "s";
|
||||
}
|
||||
add += "\n";
|
||||
|
||||
add += "=========================\n" +
|
||||
"-- Begin Transcript --\n" +
|
||||
"\n";
|
||||
|
||||
List<IUserMessage> messages = new List<IUserMessage>(await ch.GetMessagesAsync(1000).FlattenAsync()).FindAll(x => x != null);
|
||||
messages.Reverse();
|
||||
|
||||
foreach (IUserMessage msg in messages)
|
||||
{
|
||||
add += msg.Author.Username + "#" + msg.Author.Discriminator;
|
||||
if (msg.Author.IsBot) add += " [BOT]";
|
||||
|
||||
add += " (" + msg.Timestamp.DateTime + "):\n";
|
||||
if (msg.Content != null && msg.Content != "") add += msg.Content.Replace("\n", "\n ") + "\n";
|
||||
|
||||
List<Embed> embeds = new List<Embed>(msg.Embeds).FindAll(x => x != null);
|
||||
for (int i = 0; i < embeds.Length; i++)
|
||||
{
|
||||
EmbedBuilder embed = embeds[i].ToEmbedBuilder();
|
||||
|
||||
add += "Embed " + (i + 1) + "/" + embeds.Length + ":\n";
|
||||
|
||||
if (embed.Author != null && embed.Author != new EmbedAuthorBuilder())
|
||||
{
|
||||
add += " Author:\n" +
|
||||
" Icon Url: " + (embed.Author.IconUrl ?? "-- None --") + "\n" +
|
||||
" Name: " + (embed.Author.Name ?? "-- None --").Replace("\n", "\n ") + "\n" +
|
||||
" Url: " + (embed.Author.Url ?? "-- None --") + "\n";
|
||||
}
|
||||
|
||||
if (embed.Description != null && embed.Description != "") add += " Description: " + embed.Description + "\n";
|
||||
|
||||
if (embed.Fields != null && embed.Fields != new System.Collections.Generic.List<EmbedFieldBuilder>())
|
||||
{
|
||||
for (int j = 0; j < embed.Fields.Count; j++)
|
||||
{
|
||||
add += " Field " + (j + 1) + "/" + embed.Fields.Count + ":\n" +
|
||||
" Name: " + (embed.Fields[j].Name ?? "-- None --").Replace("\n", "\n ") + "\n" +
|
||||
" Value: " + (embed.Fields[j].Value ?? "-- None --").ToString().Replace("\n", "\n ") + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (embed.Footer != null && embed.Footer != new EmbedFooterBuilder())
|
||||
{
|
||||
add += " Footer:\n" +
|
||||
" Icon Url: " + (embed.Footer.IconUrl ?? "-- None --") + "\n" +
|
||||
" Text: " + (embed.Footer.Text ?? "-- None --").Replace("\n", "\n ") + "\n";
|
||||
}
|
||||
|
||||
if (embed.ImageUrl != null && embed.ImageUrl != "") add += " Image Url: " + embed.ImageUrl + "\n";
|
||||
if (embed.ThumbnailUrl != null && embed.ThumbnailUrl != "") add += " Thumbnail Url: " + embed.ThumbnailUrl + "\n";
|
||||
if (embed.Timestamp.HasValue && embed.Timestamp.Value.DateTime != DateTime.MinValue) add += " Timestamp: " + embed.Timestamp.Value.DateTime + "\n";
|
||||
if (embed.Title != null && embed.Title != "") add += " Title: " + embed.Title.Replace("\n", "\n ") + "\n";
|
||||
if (embed.Url != null && embed.Url != "") add += " Url: " + embed.Url + "\n";
|
||||
}
|
||||
|
||||
List<Attachment> attachments = new List<Attachment>(msg.Attachments).FindAll(x => x != null);
|
||||
for (int i = 0; i < attachments.Length; i++)
|
||||
{
|
||||
Attachment att = attachments[i];
|
||||
|
||||
add += "Attachment " + (i + 1) + "/" + attachments.Length + ":\n" +
|
||||
" Filename: " + att.Filename + "\n" +
|
||||
" ID: " + att.Id + "\n" +
|
||||
" Size: " + att.Size + " Byte";
|
||||
if (att.Size != 1) add += "s";
|
||||
add += "\n" +
|
||||
" Url: " + att.Url;
|
||||
}
|
||||
|
||||
add += "\n\n";
|
||||
}
|
||||
|
||||
add += "-- End Transcript --\n" +
|
||||
"=========================\n";
|
||||
|
||||
save.Data = add;
|
||||
|
||||
Directory.CreateDirectory(folder);
|
||||
save.Save();
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Color.Red,
|
||||
Description = "This ticket has been archived and closed for reason: " + Code(reason),
|
||||
Footer = new() { Text = "Reply to create a new ticket" },
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Ticket Archived",
|
||||
};
|
||||
|
||||
Modify(x =>
|
||||
{
|
||||
x.Name = user.Username + user.Discriminator + "-archived";
|
||||
x.Topic = "User: " + user.Mention + " (ARCHIVED)";
|
||||
});
|
||||
|
||||
await user.DMUserAsync("", false, e.Build());
|
||||
|
||||
e.Description += ". The ticket transcript is attached above";
|
||||
e.Footer = null;
|
||||
|
||||
await Context.Channel.SendFileAsync(save.Path, "", false, e.Build());
|
||||
|
||||
void Modify(Action<TextChannelProperties> func) => ch.ModifyAsync(func);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "Channel is not a ModMail ticket channel (Channel is not in any category)");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
[Command("category get")]
|
||||
[Summary("The current modmail category for the bot")]
|
||||
public async Task CategoryGet()
|
||||
{
|
||||
SocketCategoryChannel c = null;
|
||||
if (Data.consts.Data.modmailCategory != default)
|
||||
{
|
||||
foreach (SocketGuild g in Context.Client.Guilds)
|
||||
{
|
||||
SocketCategoryChannel c2 = new List<SocketCategoryChannel>(g.CategoryChannels).FindOrDefault(x => x.Id == Data.consts.Data.modmailCategory);
|
||||
if (c2 != default)
|
||||
{
|
||||
c = c2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (c == null)
|
||||
{
|
||||
Data.consts.Data.modmailCategory = default;
|
||||
LogModule.LogMessage(LogSeverity.Error, "The Modmail category found was no longer accessible by the bot, so it was reset");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "No current modmail category found. Use " + Code("n;mm category set") + " to set it!",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Current Modmail Category",
|
||||
};
|
||||
|
||||
if (Data.consts.Data.modmailCategory != default && c != null) e.Description = "The current modmail category is " + Italics(c.Name) + " in the server " + Italics(c.Guild.Name + " (" + Code(c.Guild.Id.ToString()) + ")");
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("category reset")]
|
||||
[RequireUserPermission(GuildPermission.ManageChannels)]
|
||||
[Summary("Resets the changelog channel of the bot back to none")]
|
||||
public async Task CategoryReset()
|
||||
{
|
||||
Data.consts.Data.modmailCategory = default;
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Color.Red,
|
||||
Description = "Successfully set the current modmail category to: " + Code("None"),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Reset Modmail Category",
|
||||
};
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("category set")]
|
||||
[RequireUserPermission(GuildPermission.ManageChannels)]
|
||||
[Summary("Sets the given category to use for modmail tickets")]
|
||||
public async Task CategorySet([Summary("The category to use for modmail tickets")] SocketCategoryChannel cat)
|
||||
{
|
||||
if (!new List<SocketGuild>(Context.Client.Guilds).Any(x => new List<SocketCategoryChannel>(x.CategoryChannels).Contains(cat)))
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "Category is not found in any of the bot's known servers");
|
||||
return;
|
||||
}
|
||||
|
||||
ulong old = Data.consts.Data.modmailCategory;
|
||||
|
||||
Data.consts.Data.modmailCategory = cat.Id;
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "Successfully set modmail category to: " + Italics(cat.Name) + " in the server " + Italics(cat.Guild.Name + " (" + Code(cat.Guild.Id.ToString()) + ")"),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Set modmail category",
|
||||
};
|
||||
|
||||
SocketCategoryChannel oldC = null;
|
||||
foreach (SocketGuild g in Context.Client.Guilds)
|
||||
{
|
||||
SocketCategoryChannel tempO = new List<SocketCategoryChannel>(g.CategoryChannels).FindOrDefault(x => x.Id == old);
|
||||
if (tempO == default) continue;
|
||||
oldC = tempO;
|
||||
break;
|
||||
}
|
||||
|
||||
if (oldC != null) e.Description += "\n(Previous: " + Italics(oldC.Name) + " in the server " + Italics(oldC.Guild.Name + " (" + Code(oldC.Guild.Id.ToString()) + ")") + ")";
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("unarchive")]
|
||||
[RequireUserPermission(GuildPermission.ManageChannels & GuildPermission.ManageChannels)]
|
||||
[Summary("Resumes communication in an archived ModMail thread and saves all communication in a text file")]
|
||||
public async Task Unarchive([Remainder][Summary("The reason you have to unarchive the ticket")] string reason = "No Reason Specified")
|
||||
{
|
||||
if (Context.Channel is INestedChannel nest)
|
||||
{
|
||||
SocketTextChannel ch = (SocketTextChannel)Context.Channel;
|
||||
|
||||
if (nest.CategoryId != Data.consts.Data.modmailCategory)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "Channel is not a ModMail ticket channel (Channel category is not the specified ModMail category. Use " + Code("n;mm category set") + " to set it!)");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ch.Topic.Trim().ToLower().Contains("archive"))
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "ModMail ticket has not been archived");
|
||||
return;
|
||||
}
|
||||
|
||||
ulong userId = ulong.Parse(ch.Topic.Substring(9, 18));
|
||||
IUser user = Context.Client.GetUser(userId);
|
||||
|
||||
SocketTextChannel other = new List<SocketTextChannel>(Context.Guild.TextChannels).FindAll(x => x.Category == ch.Category).FindOrDefault(x => x.Topic.Trim().StartsWith("User: " + user.Mention) && !x.Topic.Trim().ToLower().Contains("archive"));
|
||||
if (other != default)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "There is already an open ticket for this user, " + other.Mention);
|
||||
return;
|
||||
}
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Color.Green,
|
||||
Description = "This ticket has been unarchived and reopened for reason: " + Code(reason),
|
||||
Footer = new() { Text = "Answering ModMail tickets will now go through this ticket" },
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Ticket Unarchived",
|
||||
};
|
||||
|
||||
Modify(x =>
|
||||
{
|
||||
x.Name = user.Username + user.Discriminator;
|
||||
x.Topic = "User: " + user.Mention;
|
||||
});
|
||||
|
||||
await user.DMUserAsync("", false, e.Build());
|
||||
|
||||
e.Footer = null;
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
|
||||
void Modify(Action<TextChannelProperties> func) => ch.ModifyAsync(func);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "Channel is not a ModMail ticket channel (Channel is not in any category)");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// end commands
|
||||
|
||||
public static async Task ModmailHandler(SocketMessage message)
|
||||
{
|
||||
if (message is SocketUserMessage msg)
|
||||
{
|
||||
if (msg.Author.Id == ID) return;
|
||||
if (msg.Content.Trim().StartsWith(";") || msg.Content.Trim().StartsWith("n;") || msg.Content.Trim().StartsWith("m;")) return;
|
||||
|
||||
EmbedBuilder e;
|
||||
|
||||
if (msg.Channel is SocketDMChannel)
|
||||
{
|
||||
SocketCategoryChannel cat = null;
|
||||
foreach (SocketGuild g in Internals.context.Client.Guilds)
|
||||
{
|
||||
SocketCategoryChannel tempCat = new List<SocketCategoryChannel>(g.CategoryChannels).FindOrDefault(x => x.Id == Data.consts.Data.modmailCategory);
|
||||
if (tempCat == default) continue;
|
||||
cat = tempCat;
|
||||
break;
|
||||
}
|
||||
|
||||
if (cat == null) return;
|
||||
|
||||
Data.TryLoadAll(cat.Guild.Id);
|
||||
|
||||
ITextChannel ch = null;
|
||||
foreach (SocketGuildChannel tCh in cat.Channels) if (tCh is SocketTextChannel textCh && textCh.Topic == "User: " + msg.Author.Mention) ch = textCh;
|
||||
|
||||
e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Timestamp = DateTime.Now,
|
||||
};
|
||||
|
||||
if (ch == null)
|
||||
{
|
||||
ch = await cat.Guild.CreateTextChannelAsync(msg.Author.Username + msg.Author.Discriminator, x =>
|
||||
{
|
||||
x.CategoryId = cat.Id;
|
||||
x.Topic = "User: " + msg.Author.Mention;
|
||||
});
|
||||
|
||||
e.Description = "Info on the thread creator is below";
|
||||
e.Title = "New ModMail Thread Created";
|
||||
|
||||
e.AddField("User Full Name", Code(msg.Author.Username + "#" + msg.Author.Discriminator), true);
|
||||
e.AddField("User Id", Code(msg.Author.Id.ToString()), true);
|
||||
e.AddField("User Mention", msg.Author.Mention, true);
|
||||
|
||||
int count = 0;
|
||||
User usr = Data.users.Data.FindOrDefault(x => x.userID == msg.Author.Id);
|
||||
if (usr == default)
|
||||
{
|
||||
usr = new()
|
||||
{
|
||||
currentMute = null,
|
||||
tickets = 1,
|
||||
userID = msg.Author.Id,
|
||||
};
|
||||
count = 1;
|
||||
Data.users.Data.Add(usr);
|
||||
}
|
||||
else
|
||||
{
|
||||
usr.tickets++;
|
||||
count = usr.tickets;
|
||||
}
|
||||
|
||||
bool muted;
|
||||
if (usr.currentMute == null) muted = false;
|
||||
else muted = usr.currentMute.IsMuted;
|
||||
|
||||
e.AddField("User is Muted", Code(muted.ToString()), true);
|
||||
|
||||
string s = "";
|
||||
if (count != 1) s += "s";
|
||||
e.AddField("Ticket Count", Code(count + " Ticket" + s), true);
|
||||
|
||||
if (usr.warns is null) count = 0;
|
||||
else count = usr.warns.Length;
|
||||
|
||||
s = "";
|
||||
if (count != 1) s += "s";
|
||||
e.AddField("Warn Count", Code(count + " Warn" + s), true);
|
||||
|
||||
await ch.SendMessageAsync("", false, e.Build());
|
||||
await ch.SyncPermissionsAsync();
|
||||
await SuccessModMailMessage(await msg.Author.GetOrCreateDMChannelAsync(), true);
|
||||
}
|
||||
|
||||
EmbedAuthorBuilder a = new()
|
||||
{
|
||||
IconUrl = msg.Author.GetAvatarUrl(),
|
||||
Name = "From " + msg.Author.Username + "#" + msg.Author.Discriminator,
|
||||
};
|
||||
|
||||
await SendModMailMessage(a, msg, ch);
|
||||
|
||||
Data.SaveAll(cat.Guild.Id);
|
||||
}
|
||||
else if (msg.Channel is SocketTextChannel ch)
|
||||
{
|
||||
if (!ch.CategoryId.HasValue) return;
|
||||
if (ch.CategoryId != Data.consts.Data.modmailCategory) return;
|
||||
if (ch.Topic.Trim().ToLower().Contains("archive")) return;
|
||||
|
||||
ulong userId = ulong.Parse(ch.Topic.Substring(9, 18));
|
||||
|
||||
EmbedAuthorBuilder a = new()
|
||||
{
|
||||
IconUrl = msg.Author.GetAvatarUrl(),
|
||||
Name = "From " + msg.Author.Username + msg.Author.Discriminator,
|
||||
};
|
||||
|
||||
await SendModMailMessage(a, msg, await Internals.client.GetUser(userId).GetOrCreateDMChannelAsync());
|
||||
if (new List<IMessage>(await ch.GetMessagesAsync().FlattenAsync()).FindAll(x => x != null).Length < 4) await SuccessModMailMessage(ch, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task SendModMailMessage(EmbedAuthorBuilder a, IMessage msg, IMessageChannel ch)
|
||||
{
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Author = a,
|
||||
Color = Colors.DefaultColor,
|
||||
Description = msg.Content,
|
||||
Title = "ModMail Message Recieved",
|
||||
};
|
||||
|
||||
List<Attachment> attachments = new(msg.Attachments);
|
||||
if (attachments.Length == 1) e.ImageUrl = attachments[0].Url;
|
||||
|
||||
IUserMessage sent = await ch.SendMessageAsync("", false, e.Build());
|
||||
|
||||
if (attachments.Length > 1)
|
||||
{
|
||||
for (int i = 0; i < attachments.Length; i++)
|
||||
{
|
||||
e.Author = null;
|
||||
e.Description = "This ModMail message has been send more than one attachment, and as such must be broken down into several embeds";
|
||||
e.ImageUrl = attachments[i].Url;
|
||||
e.Title = "ModMail Message Attachment " + (i + 1) + "/" + attachments.Length;
|
||||
|
||||
await sent.ReplyAsync("", false, e.Build());
|
||||
}
|
||||
}
|
||||
}
|
||||
public static async Task SuccessModMailMessage(IMessageChannel ch, bool appearsOnce = false)
|
||||
{
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "Your message has been sent to the ModMail recievers, and they will get back to you as soon as possible!",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "ModMail Message Sent",
|
||||
};
|
||||
if (appearsOnce) e.WithFooter("This message will appear only once per ticket");
|
||||
|
||||
await ch.SendMessageAsync("", false, e.Build());
|
||||
}
|
||||
}
|
||||
}
|
||||
211
Nerd's Teaser Bot/Modules/Commands/OnlineModule.cs
Normal file
211
Nerd's Teaser Bot/Modules/Commands/OnlineModule.cs
Normal file
@ -0,0 +1,211 @@
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using NerdsTeaserBot.Misc;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using static Discord.Format;
|
||||
|
||||
namespace NerdsTeaserBot.Modules.Commands
|
||||
{
|
||||
[Name("Online")]
|
||||
[Summary("Commands that involve the internet")]
|
||||
public class OnlineModule : ModuleBase<SocketCommandContext>
|
||||
{
|
||||
[Command("meme")]
|
||||
[Summary("Returns a meme from a random meme subreddit")]
|
||||
public async Task Meme([Name("minimum upvotes")] [Summary("The minimum amount of upvotes")] float minUps = 1500)
|
||||
{
|
||||
if (Data.misc.Data.memeSubs.Length == 0)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "No Meme Subreddits are given. Use " + Code("n;memesub add") + " to add a subreddit to the list");
|
||||
return;
|
||||
}
|
||||
|
||||
await Reddit(Data.misc.Data.memeSubs[new Random().Next(0, Data.misc.Data.memeSubs.Length)], minUps);
|
||||
}
|
||||
|
||||
[Command("memesub add")]
|
||||
[RequireUserPermission(GuildPermission.ManageGuild)]
|
||||
[Summary("Adds a new meme subreddit to the list, if it is avaliable")]
|
||||
public async Task MemesubAdd([Summary("The name of the subreddit")] string name)
|
||||
{
|
||||
if (name.StartsWith("r/")) name = name[2..];
|
||||
|
||||
if (Data.misc.Data.memeSubs.Contains(name))
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "Subreddit already exists in list");
|
||||
return;
|
||||
}
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Color.LightGrey,
|
||||
Description = "Checking if the subreddit r/" + name + "exists.\n" +
|
||||
Italics("The Reddit API is slow, and loading an object can take some time. Please be patient."),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Checking Subreddit Authenticity",
|
||||
};
|
||||
|
||||
IUserMessage msg = await ReplyAsync("", false, e.Build());
|
||||
|
||||
string str = await new HttpClient().GetStringAsync("https://reddit.com/r/" + name + "/random.json?limit=1");
|
||||
JObject obj = HalfParse(str);
|
||||
if ((int)obj["dist"] < 1)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "Subreddit does not exist, or is private", "", msg);
|
||||
return;
|
||||
}
|
||||
|
||||
Data.misc.Data.memeSubs.Add(name);
|
||||
|
||||
e = new()
|
||||
{
|
||||
Color = Color.Orange,
|
||||
Description = "The subreddit, " + Url("r/" + name, "https://reddit.com/r/" + name) + " has been added to the meme subreddit list.",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Subreddit Added",
|
||||
};
|
||||
e.WithFooter("Use 'n;memesub list' for a list of all considered meme subreddits");
|
||||
|
||||
await msg.ModifyAsync(x => x.Embed = e.Build());
|
||||
|
||||
static JObject HalfParse(string str)
|
||||
{
|
||||
if (str.StartsWith("[")) return (JObject)JArray.Parse(str)[0]["data"];
|
||||
else return (JObject)JObject.Parse(str)["data"];
|
||||
}
|
||||
}
|
||||
|
||||
[Command("memesub list")]
|
||||
[Summary("Lists all current meme subreddits")]
|
||||
public async Task MemesubList()
|
||||
{
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Color.Orange,
|
||||
Description = "",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Showing " + Data.misc.Data.memeSubs.Length + " Accepted Meme Subreddits",
|
||||
};
|
||||
|
||||
foreach (string s in Data.misc.Data.memeSubs) e.Description += Code("r/" + s) + "\n";
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("memesub remove")]
|
||||
[RequireUserPermission(GuildPermission.ManageGuild)]
|
||||
[Summary("Removed a meme subreddit from the subreddit list, if it exists in the list")]
|
||||
public async Task MemesubRemove([Summary("The name of the subreddit")] string name)
|
||||
{
|
||||
if (name.StartsWith("r/")) name = name[2..];
|
||||
|
||||
bool predicate(string x) => x.ToLower() == name.ToLower();
|
||||
if (!Data.misc.Data.memeSubs.Contains(predicate))
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "Subreddit doesn't exist in the list");
|
||||
return;
|
||||
}
|
||||
|
||||
Data.misc.Data.memeSubs.Remove(predicate);
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Color.Orange,
|
||||
Description = "Subreddit " + Code("r/" + name) + " has been removed from the meme subreddit list.",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Subreddit Removed"
|
||||
};
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("reddit")]
|
||||
[Summary("Returns a reddit post from a subreddit. Defaults to r/all")]
|
||||
public async Task Reddit([Summary("The subreddit to pull the post from")] string subreddit = "all", [Name("minimum upvotes")] [Summary("The minimum amount of upvotes")] float minUps = 1500)
|
||||
{
|
||||
if (subreddit.StartsWith("r/")) subreddit = subreddit[2..];
|
||||
|
||||
HttpClient client = new();
|
||||
JObject obj;
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Color.LightGrey,
|
||||
Description = "Searching r/" + subreddit + " for a post with at least " + minUps + " upvote",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Post Loading..."
|
||||
};
|
||||
if (minUps != 1) e.Description += "s";
|
||||
e.Description += "\n" + Italics("The Reddit API is slow, and loading an object can take some time. Please be patient.");
|
||||
|
||||
IUserMessage msg = await ReplyAsync("", false, e.Build());
|
||||
|
||||
bool selected = false;
|
||||
string str = await client.GetStringAsync("https://reddit.com/r/" + subreddit + "/top.json?t=all");
|
||||
obj = HalfParse(str);
|
||||
if ((int)obj["dist"] < 1)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "Subreddit does not exist, or is private", "", msg);
|
||||
return;
|
||||
}
|
||||
obj = (JObject)obj["children"][0]["data"];
|
||||
if ((int)obj["ups"] < minUps)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Warning, "Top post of all time has less upvotes than the minimum required. Defaulting to that post.");
|
||||
minUps = (int)obj["ups"];
|
||||
selected = true;
|
||||
}
|
||||
|
||||
static JObject HalfParse(string str)
|
||||
{
|
||||
if (str.StartsWith("[")) return (JObject)JArray.Parse(str)[0]["data"];
|
||||
else return (JObject)JObject.Parse(str)["data"];
|
||||
}
|
||||
|
||||
while (!selected)
|
||||
{
|
||||
str = await client.GetStringAsync("https://reddit.com/r/" + subreddit + "/random.json?limit=1");
|
||||
obj = (JObject)HalfParse(str)["children"][0]["data"];
|
||||
|
||||
if ((int)obj["ups"] >= minUps) selected = true;
|
||||
}
|
||||
|
||||
if (obj == null)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Critical, "An unknown internal error has occurred. This should never happen.", "", msg);
|
||||
return;
|
||||
}
|
||||
|
||||
EmbedAuthorBuilder a = new()
|
||||
{
|
||||
Name = obj["author"].ToString(),
|
||||
Url = "https://reddit.com/u/" + obj["author"],
|
||||
};
|
||||
e = new()
|
||||
{
|
||||
Author = a,
|
||||
Color = Color.Orange,
|
||||
Title = obj["title"].ToString(),
|
||||
Url = "https://reddit.com" + obj["permalink"],
|
||||
};
|
||||
|
||||
e.WithFooter(obj["ups"] + " Upvote");
|
||||
if ((int)obj["ups"] != 1) e.Footer.Text += "s";
|
||||
e.Footer.Text += " | " + obj["num_comments"] + " Comment";
|
||||
if ((int)obj["num_comments"] != 1) e.Footer.Text += "s";
|
||||
|
||||
if (obj["selftext"].ToString() != "") e.WithDescription(obj["selftext"].ToString());
|
||||
if (obj["url"].ToString() != obj["permalink"].ToString())
|
||||
{
|
||||
string url = obj["url"].ToString();
|
||||
if (url.EndsWith(".gifv")) url = url.Remove(url.Length - 1);
|
||||
e.WithImageUrl(url);
|
||||
}
|
||||
|
||||
await msg.ModifyAsync(x => x.Embed = e.Build());
|
||||
}
|
||||
}
|
||||
}
|
||||
192
Nerd's Teaser Bot/Modules/Commands/RoleModule.cs
Normal file
192
Nerd's Teaser Bot/Modules/Commands/RoleModule.cs
Normal file
@ -0,0 +1,192 @@
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using NerdsTeaserBot.Misc;
|
||||
using NerdsTeaserBot.Modules.Extensions;
|
||||
using Nerd_STF.Lists;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using static Discord.Format;
|
||||
using static NerdsTeaserBot.Const;
|
||||
|
||||
namespace NerdsTeaserBot.Modules.Commands
|
||||
{
|
||||
[Group("role")]
|
||||
[Name("Role")]
|
||||
[Summary("Commands about role registering, unregistering, and creating/listing/removing")]
|
||||
public class RoleModule : ModuleBase<SocketCommandContext>
|
||||
{
|
||||
[Command("add")]
|
||||
[RequireUserPermission(GuildPermission.ManageRoles)]
|
||||
[Summary("Adds a role to the role list")]
|
||||
public async Task RoleAdd([Summary("The role to add")] SocketRole role)
|
||||
{
|
||||
List<SocketRole> roles = new List<SocketRole>(Context.Guild.Roles).FindAll(x => Data.misc.Data.roles.Contains(x.Id));
|
||||
if (roles.Any(x => x.Name.Trim().ToLower() == role.Name.Trim().ToLower()))
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "A role already is added with that name. Please change the name slightly");
|
||||
return;
|
||||
}
|
||||
|
||||
/*if (Context.Guild.CurrentUser.Roles < role.Position)
|
||||
{
|
||||
|
||||
}*/
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "A user can now use " + Code("n;role register " + role.Name.ToLower()) + " to be given the role " + role.Mention,
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Role added to register roles",
|
||||
};
|
||||
|
||||
Data.misc.Data.roles.Add(role.Id);
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("list")]
|
||||
[Summary("Lists all roles in the role list")]
|
||||
public async Task RoleList()
|
||||
{
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = Data.misc.Data.roles.Length + " Roles in Role List",
|
||||
};
|
||||
|
||||
List<IRole> roles = new List<IRole>(Context.Guild.Roles).FindAll(x => Data.misc.Data.roles.Contains(x.Id));
|
||||
|
||||
foreach (IRole role in roles) e.Description += role.Mention + "\n";
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("register")]
|
||||
[Summary("Gives yourself a role with the given name (DO NOT MENTION A ROLE)")]
|
||||
public async Task RoleRegister([Remainder][Summary("The role to add. Use '--all roles--' to give all roles (DO NOT MENTION A ROLE)")] string roleName)
|
||||
{
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Timestamp = DateTime.Now,
|
||||
};
|
||||
List<SocketRole> registeredRoles = new List<SocketRole>(Context.Guild.Roles).FindAll(x => Data.misc.Data.roles.Contains(x.Id));
|
||||
string name = roleName.Trim().ToLower();
|
||||
|
||||
SocketGuildUser gUser = (SocketGuildUser)Context.User;
|
||||
|
||||
if (name == "--all roles--" || name == "-- all roles --")
|
||||
{
|
||||
e.Description = Context.User.Mention + " has been given the following roles:\n";
|
||||
foreach (SocketRole r in registeredRoles) e.Description += r.Mention + ", ";
|
||||
e.Description = e.Description.Remove(e.Description.Length - 2);
|
||||
|
||||
e.Title = registeredRoles.Length + " Roles given to " + Context.User.Username + "#" + Context.User.Discriminator;
|
||||
|
||||
await gUser.AddRolesAsync(registeredRoles);
|
||||
}
|
||||
else
|
||||
{
|
||||
SocketRole role = registeredRoles.FindOrDefault(x => x.Name.Trim().ToLower() == name);
|
||||
|
||||
if (role == default)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "No register role found with that name (" + Code(name) + ")");
|
||||
return;
|
||||
}
|
||||
|
||||
if (new List<SocketRole>(gUser.Roles).Contains(x => x.Id == role.Id))
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "User has already registered that role");
|
||||
return;
|
||||
}
|
||||
|
||||
e.Description = Context.User.Mention + " has been given the role " + role.Mention;
|
||||
e.Title = "Role registered to user";
|
||||
|
||||
await gUser.AddRoleAsync(role);
|
||||
}
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("remove")]
|
||||
[RequireUserPermission(GuildPermission.ManageRoles)]
|
||||
[Summary("Removes a role from the role list")]
|
||||
public async Task RoleRemove([Summary("The role to remove")] IRole role)
|
||||
{
|
||||
if (!Data.misc.Data.roles.Contains(role.Id))
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "That role is not found in the list of register roles");
|
||||
return;
|
||||
}
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "A user can no longer now use " + Code("n;role register " + role.Name.ToLower()) + " to be given the role " + role.Mention,
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Role removed from register roles",
|
||||
};
|
||||
|
||||
Data.misc.Data.roles.Remove(role.Id);
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("unregister")]
|
||||
[Summary("Removes a role with the given name (DO NOT MENTION A ROLE)")]
|
||||
public async Task RoleUnregister([Remainder][Summary("The role to remove. Use '--all roles--' to remove all roles (DO NOT MENTION A ROLE)")] string roleName)
|
||||
{
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Timestamp = DateTime.Now,
|
||||
};
|
||||
List<SocketRole> registeredRoles = new List<SocketRole>(Context.Guild.Roles).FindAll(x => Data.misc.Data.roles.Contains(x.Id));
|
||||
string name = roleName.Trim().ToLower();
|
||||
|
||||
SocketGuildUser gUser = (SocketGuildUser)Context.User;
|
||||
|
||||
if (name == "--all roles--" || name == "-- all roles --")
|
||||
{
|
||||
e.Description = Context.User.Mention + " has removed the following roles:\n";
|
||||
foreach (SocketRole r in registeredRoles) e.Description += r.Mention + ", ";
|
||||
e.Description = e.Description.Remove(e.Description.Length - 2);
|
||||
|
||||
e.Title = registeredRoles.Length + " Roles removed from " + Context.User.Username + "#" + Context.User.Discriminator;
|
||||
|
||||
await gUser.RemoveRolesAsync(registeredRoles);
|
||||
}
|
||||
else
|
||||
{
|
||||
SocketRole role = registeredRoles.FindOrDefault(x => x.Name.Trim().ToLower() == name);
|
||||
|
||||
if (role == default)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "No register role (to remove) found with that name " + Code("(" + name + ")"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!new List<SocketRole>(gUser.Roles).Contains(x => x.Id == role.Id))
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "User has not registered that role");
|
||||
return;
|
||||
}
|
||||
|
||||
e.Description = Context.User.Mention + " has lost the role " + role.Mention;
|
||||
e.Title = "Role unregistered to user";
|
||||
|
||||
await gUser.RemoveRoleAsync(role);
|
||||
}
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
}
|
||||
}
|
||||
311
Nerd's Teaser Bot/Modules/Commands/ServerModule.cs
Normal file
311
Nerd's Teaser Bot/Modules/Commands/ServerModule.cs
Normal file
@ -0,0 +1,311 @@
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using NerdsTeaserBot.Misc;
|
||||
using NerdsTeaserBot.Modules.Models;
|
||||
using Nerd_STF.Lists;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using static Discord.Format;
|
||||
using static NerdsTeaserBot.Const;
|
||||
|
||||
namespace NerdsTeaserBot.Modules.Commands
|
||||
{
|
||||
[Name("Server")]
|
||||
[Summary("Commands about the server and it's functions")]
|
||||
public class ServerModule : ModuleBase<SocketCommandContext>
|
||||
{
|
||||
[Command("announce")]
|
||||
[RequireUserPermission(GuildPermission.ManageChannels & GuildPermission.ManageMessages)]
|
||||
[Summary("Sends a message into all channels in the announcement channel list")]
|
||||
public async Task Announce([Remainder][Summary("The message to be announced")] string text)
|
||||
{
|
||||
bool ded = false;
|
||||
if (Data.misc.Data.announceChannels is null) ded = true;
|
||||
else if (Data.misc.Data.announceChannels.Length == 0) ded = true;
|
||||
|
||||
if (ded)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "No Channels are in the Announcement Channel List");
|
||||
return;
|
||||
}
|
||||
|
||||
int removedCount = 0;
|
||||
string[] txt = new[] { "", "has", "it" };
|
||||
|
||||
for (int i = 0; i < Data.misc.Data.announceChannels.Length; i++)
|
||||
{
|
||||
ulong u = Data.misc.Data.announceChannels[i];
|
||||
if (Context.Guild.GetTextChannel(u) == null)
|
||||
{
|
||||
Data.misc.Data.announceChannels.Remove(u);
|
||||
removedCount++;
|
||||
if (i >= 1) txt = new[] { "s", "have", "them" };
|
||||
}
|
||||
}
|
||||
|
||||
if (removedCount != 0) LogModule.LogMessage(LogSeverity.Warning, removedCount + " Announcement Channel" + txt[0] + " " + txt[1] + " been removed for no longer being found in the server. This is because the channel" + txt[0] + " may have been deleted, or the bot can no longer see " + txt[2]);
|
||||
|
||||
EmbedAuthorBuilder a = new()
|
||||
{
|
||||
IconUrl = Context.User.GetAvatarUrl(),
|
||||
Name = Context.User.Username + "#" + Context.User.Discriminator,
|
||||
};
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Author = a,
|
||||
Color = Colors.DefaultColor,
|
||||
Description = text,
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Annoucement for " + Context.Guild.Name,
|
||||
};
|
||||
|
||||
foreach (ulong u in Data.misc.Data.announceChannels)
|
||||
{
|
||||
ITextChannel c = Context.Guild.GetTextChannel(u);
|
||||
if (c == null) continue;
|
||||
|
||||
await c.SendMessageAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
e.Author.IconUrl = Context.Client.CurrentUser.GetAvatarUrl();
|
||||
e.Author.Name = "Message Sent. A preview is below";
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("announcements add")]
|
||||
[RequireUserPermission(GuildPermission.ManageChannels)]
|
||||
[Summary("Add a channel to the list of announcement channels")]
|
||||
public async Task AnnouncementsAdd([Summary("The text channel to add to the list")] ITextChannel channel)
|
||||
{
|
||||
if (channel.Guild.Id != Context.Guild.Id)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "Text channel is not in this server");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Data.misc.Data.announceChannels.Contains(channel.Id))
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "Text channel already exists in list");
|
||||
return;
|
||||
}
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "The bot will now send a message in " + channel.Mention + " when the command " + Code("n;announce") + " is triggered",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Added Channel to Announcement Channels",
|
||||
};
|
||||
|
||||
Data.misc.Data.announceChannels.Add(channel.Id);
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("announcements list")]
|
||||
[Summary("Shows the list of announcement channels")]
|
||||
public async Task AnnouncementsList()
|
||||
{
|
||||
int removedCount = 0;
|
||||
string[] text = new[] { "", "has", "it" };
|
||||
|
||||
for (int i = 0; i < Data.misc.Data.announceChannels.Length; i++)
|
||||
{
|
||||
ulong u = Data.misc.Data.announceChannels[i];
|
||||
if (Context.Guild.GetTextChannel(u) == null)
|
||||
{
|
||||
Data.misc.Data.announceChannels.Remove(u);
|
||||
removedCount++;
|
||||
if (i >= 1) text = new[] { "s", "have", "them" };
|
||||
}
|
||||
}
|
||||
|
||||
if (removedCount != 0) LogModule.LogMessage(LogSeverity.Warning, removedCount + " Announcement Channel" + text[0] + " " + text[1] + " been removed for no longer being found in the server. This is because the channel" + text[0] + " may have been deleted, or the bot can no longer see " + text[2]);
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = Data.misc.Data.announceChannels.Length + " Announcement Channel",
|
||||
};
|
||||
if (Data.misc.Data.announceChannels.Length != 1) e.Title += "s";
|
||||
|
||||
foreach (ulong u in Data.misc.Data.announceChannels) e.Description += "<#" + u + ">\n";
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("announcements remove")]
|
||||
[RequireUserPermission(GuildPermission.ManageChannels)]
|
||||
[Summary("Removes a channel from the list of announcement channels")]
|
||||
public async Task AnnouncementsRemove([Summary("The text channel to remove from the list")] ITextChannel channel)
|
||||
{
|
||||
if (!Data.misc.Data.announceChannels.Contains(channel.Id))
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "Channel not found in list");
|
||||
return;
|
||||
}
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Color.Red,
|
||||
Description = "The bot will no longer send a message in " + channel.Mention + " during an announcement",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Announcement Channel Removed"
|
||||
};
|
||||
|
||||
Data.misc.Data.announceChannels.Remove(channel.Id);
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("serverinfo")]
|
||||
[Summary("Show info about the server executed in")]
|
||||
public async Task Serverinfo()
|
||||
{
|
||||
SocketGuild server = Context.Guild;
|
||||
string add;
|
||||
Embed e1, e2;
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Server Info about " + server.Name + " (Page 1 of 2)",
|
||||
};
|
||||
|
||||
if (server.AFKChannel == null) add = "No AFK Voice Channel";
|
||||
else add = server.AFKChannel.Name;
|
||||
e.AddField("AFK Voice Channel", Code(add), true);
|
||||
|
||||
e.AddField("AFK Timeout", Code(server.AFKTimeout + " Seconds"), true);
|
||||
|
||||
if (server.BannerUrl == null || server.BannerUrl == "") add = Code("No Banner");
|
||||
else add = Url("Click Here", server.BannerUrl);
|
||||
e.AddField("Banner", add, true);
|
||||
|
||||
add = server.CategoryChannels.Count + " Categor";
|
||||
if (server.CategoryChannels.Count == 1) add += "y";
|
||||
else add += "ies";
|
||||
e.AddField("Category Count", Code(add), true);
|
||||
|
||||
add = server.Channels.Count + " Channel";
|
||||
if (server.Channels.Count != 1) add += "s";
|
||||
e.AddField("Total Channel Count", Code(add), true);
|
||||
|
||||
e.AddField("Created At", Code(server.CreatedAt.ToString()), true);
|
||||
|
||||
e.AddField("Default Text Channel", server.DefaultChannel.Mention, true);
|
||||
|
||||
e.AddField("Default Message Notifications", Code(server.DefaultMessageNotifications.ToString()), true);
|
||||
|
||||
if (server.Description == null || server.Description == "") add = "No Description";
|
||||
else add = server.Description;
|
||||
e.AddField("Server Description", Code(add), true);
|
||||
|
||||
if (server.DiscoverySplashUrl == null || server.DiscoverySplashUrl == "") add = Code("No Discovery Splash");
|
||||
else add = Url("Click Here", server.DiscoverySplashUrl);
|
||||
e.AddField("Discovery Splash", add, true);
|
||||
|
||||
add = server.Emotes.Count + " Emote";
|
||||
if (server.Emotes.Count != 1) add += "s";
|
||||
e.AddField("Emote Count", Code(add), true);
|
||||
|
||||
add = "";
|
||||
foreach (string s in server.Features) add += Code(s) + "\n";
|
||||
if (add == "") add = Code("No Server Features");
|
||||
e.AddField("Server Features", add);
|
||||
|
||||
e.ThumbnailUrl = server.IconUrl;
|
||||
|
||||
e.AddField("Server ID", Code(server.Id.ToString()), true);
|
||||
|
||||
e.AddField("Max Bitrate", Code((server.MaxBitrate / 1000) + "kbps"), true);
|
||||
|
||||
if (server.MaxMembers == null) add = "No Limit";
|
||||
else
|
||||
{
|
||||
add = server.MaxMembers + " User";
|
||||
if (server.MaxMembers != 1) add += "s";
|
||||
}
|
||||
e.AddField("Max Member Count", Code(add), true);
|
||||
|
||||
if (server.MaxPresences == null) add = "No Limit";
|
||||
else
|
||||
{
|
||||
add = server.MaxPresences + " Presence";
|
||||
if (server.MaxPresences != 1) add += "s";
|
||||
}
|
||||
e.AddField("Max Presence Count", Code(add), true);
|
||||
|
||||
add = server.MemberCount + " User";
|
||||
if (server.MemberCount != 1) add += "s";
|
||||
e.AddField("Current Member Count", Code(add), true);
|
||||
|
||||
e.AddField("2FA Required to Moderate", Code(Convert.ToBoolean((int)server.MfaLevel).ToString()), true);
|
||||
|
||||
e.AddField("Server Name", Code(server.Name), true);
|
||||
|
||||
e.AddField("Server Owner", server.Owner.Mention, true);
|
||||
|
||||
e.AddField("Preferred Culture", Code(server.PreferredCulture.Name), true);
|
||||
|
||||
add = server.PremiumSubscriptionCount + " User";
|
||||
if (server.PremiumSubscriptionCount != 1) add += "s";
|
||||
e.AddField("Server Booster Count", Code(add), true);
|
||||
|
||||
e.AddField("Boost Tier", Code(server.PremiumTier.ToString()), true);
|
||||
|
||||
if (server.PublicUpdatesChannel == null) add = Code("No Public Updates Channel");
|
||||
else add = server.PublicUpdatesChannel.Mention;
|
||||
e.AddField("Public Updates Channel", add, true);
|
||||
|
||||
add = server.Roles.Count + " Role";
|
||||
if (server.Roles.Count != 1) add += "s";
|
||||
e.AddField("Role Count", Code(add), true);
|
||||
|
||||
// embed 1 done
|
||||
|
||||
e1 = e.Build();
|
||||
|
||||
e.Fields = new();
|
||||
e.Title = "Server Info about " + server.Name + " (Page 2 of 2)";
|
||||
|
||||
// begin embed 2 fields
|
||||
|
||||
if (server.RulesChannel == null) add = Code("No Rule Channel");
|
||||
else add = server.RulesChannel.Mention;
|
||||
e.AddField("Rule Channel", add, true);
|
||||
|
||||
if (server.SplashUrl == null || server.SplashUrl == "") add = Code("No Splash");
|
||||
else add = Url("Click Here", server.SplashUrl);
|
||||
e.AddField("Splash", add, true);
|
||||
|
||||
if (server.SystemChannel == null) add = Code("No System Channel");
|
||||
else add = server.SystemChannel.Mention;
|
||||
e.AddField("System Channel", add, true);
|
||||
|
||||
add = server.TextChannels.Count + " Channel";
|
||||
if (server.TextChannels.Count != 1) add += "s";
|
||||
e.AddField("Text Channel Count", Code(add), true);
|
||||
|
||||
if (server.VanityURLCode == null) add = Code("No Vanity URL");
|
||||
else add = EscapeUrl("https://discord.gg/" + server.VanityURLCode);
|
||||
e.AddField("Vanity URL", add, true);
|
||||
|
||||
e.AddField("Verification Level", Code(server.VerificationLevel.ToString()), true);
|
||||
|
||||
add = server.VoiceChannels.Count + " Channel";
|
||||
if (server.VoiceChannels.Count != 1) add += "s";
|
||||
e.AddField("Voice Channel Count", Code(add), true);
|
||||
|
||||
e2 = e.Build();
|
||||
|
||||
await ReplyAsync("", false, e1);
|
||||
await ReplyAsync("", false, e2);
|
||||
}
|
||||
}
|
||||
}
|
||||
191
Nerd's Teaser Bot/Modules/Commands/TagModule.cs
Normal file
191
Nerd's Teaser Bot/Modules/Commands/TagModule.cs
Normal file
@ -0,0 +1,191 @@
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using NerdsTeaserBot.Misc;
|
||||
using NerdsTeaserBot.Modules.Models;
|
||||
using Nerd_STF.Lists;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using static Discord.Format;
|
||||
using static NerdsTeaserBot.Const;
|
||||
|
||||
namespace NerdsTeaserBot.Modules.Commands
|
||||
{
|
||||
[Group("tag")]
|
||||
[Name("Tag")]
|
||||
[Summary("Commands used to create, remove, and view all tags")]
|
||||
public class TagModule : ModuleBase<SocketCommandContext>
|
||||
{
|
||||
[Command("delete")]
|
||||
[RequireUserPermission(GuildPermission.ManageMessages)]
|
||||
[Summary("Deletes a tag with the specified name")]
|
||||
public async Task Delete([Summary("The name of the tag to delete")] string name)
|
||||
{
|
||||
Tag tag = Data.misc.Data.tags.FindOrDefault(x => x.name == name.Trim().ToLower() || "$" + x.name == name.Trim().ToLower());
|
||||
|
||||
if (tag == null)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "Tag does not exist in the database of created tags");
|
||||
return;
|
||||
}
|
||||
else if (tag.owner == Context.User.Id)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "You do not own this tag, and as such cannot delete it");
|
||||
return;
|
||||
}
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Color.Red,
|
||||
Description = "Using " + Code("$" + tag.name) + " will no longer trigger any sort of response from the bot",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Tag Deleted",
|
||||
};
|
||||
|
||||
Data.misc.Data.tags.Remove(tag);
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("info")]
|
||||
[Summary("Shows info on a given tag")]
|
||||
public async Task Info([Summary("The name of the tag to show info of")] string name)
|
||||
{
|
||||
Tag tag = Data.misc.Data.tags.FindOrDefault(x => x.name == name.Trim().ToLower() || "$" + x.name == name.Trim().ToLower());
|
||||
|
||||
if (tag == null)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "Tag does not exist in the database of created tags");
|
||||
return;
|
||||
}
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Info on $" + tag.name,
|
||||
};
|
||||
e.AddField("Tag Owner", "<@" + tag.owner + ">", true);
|
||||
e.AddField("Tag Name", "$" + tag.name, true);
|
||||
e.AddField("Response", tag.response);
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("list")]
|
||||
[Summary("Shows all currently existing tags and their owners")]
|
||||
public async Task List()
|
||||
{
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = Data.misc.Data.tags.Length + " Tags in List",
|
||||
};
|
||||
|
||||
foreach (Tag t in Data.misc.Data.tags)
|
||||
{
|
||||
string res = t.response.Replace("\n", " ");
|
||||
if (res.Length > 50) res = res.Remove(47) + "…";
|
||||
e.Description += "<@" + t.owner + "> - " + Code("$" + t.name) + ": " + res + "\n";
|
||||
}
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("set")]
|
||||
[RequireUserPermission(GuildPermission.ManageMessages)]
|
||||
[Summary("Edit a tag if it is found, otherwise creates one")]
|
||||
public async Task Set([Summary("The name of the tag to add/edit")] string name, [Remainder][Summary("The summary of the tag to make/change")] string response)
|
||||
{
|
||||
Tag tag = Data.misc.Data.tags.FindOrDefault(x => x.name.ToLower().Trim() == name.ToLower().Trim() || "$" + x.name == name.Trim().ToLower());
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = " will now trigger the bot to respond with: ",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Tag "
|
||||
};
|
||||
|
||||
if (tag == default)
|
||||
{
|
||||
tag = new()
|
||||
{
|
||||
name = name,
|
||||
owner = Context.User.Id,
|
||||
response = response.Trim(),
|
||||
};
|
||||
Data.misc.Data.tags.Add(tag);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tag.owner != Context.User.Id)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "You do not own this tag, and as such cannot edit it");
|
||||
return;
|
||||
}
|
||||
tag.response = response.Trim();
|
||||
}
|
||||
|
||||
if (tag.response.Contains("\n")) e.Description += "\n" + tag.response;
|
||||
else e.Description += tag.response;
|
||||
e.Title += "Edited";
|
||||
e.Description = Code("$" + tag.name) + e.Description;
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("transfer")]
|
||||
[RequireUserPermission(GuildPermission.ManageMessages)]
|
||||
[Summary("Transfers ownership of a tag from one user to another")]
|
||||
public async Task Transfer([Summary("The user to make the new owner")] IGuildUser user, [Summary("The name of the tag to transfer owners of")] string name)
|
||||
{
|
||||
Tag tag = Data.misc.Data.tags.FindOrDefault(x => x.name == name.Trim().ToLower() || x.name == "$" + name.Trim().ToLower());
|
||||
|
||||
if (tag == null)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "Tag does not exist in the database of created tags");
|
||||
return;
|
||||
}
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "<@" + tag.owner + "> has transfered the tag ownership of " + Code("$" + tag.name) + " now belongs to " + user.Mention,
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Tag Ownership Transferred",
|
||||
};
|
||||
|
||||
tag.owner = user.Id;
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
// end commands
|
||||
|
||||
public static async Task TagHandler(SocketUserMessage msg)
|
||||
{
|
||||
List<string> words = new(msg.Content.Split(" "));
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Timestamp = DateTime.Now,
|
||||
};
|
||||
|
||||
foreach (Tag t in Data.misc.Data.tags)
|
||||
{
|
||||
if (words.Contains(x => x.Trim().ToLower() == "$" + t.name))
|
||||
{
|
||||
e.Description = t.response;
|
||||
e.Title = "$" + t.name;
|
||||
|
||||
if (msg.ReferencedMessage == null) await msg.ReplyAsync("", false, e.Build());
|
||||
else await msg.ReferencedMessage.ReplyAsync("", false, e.Build());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
63
Nerd's Teaser Bot/Modules/Commands/TextModule.cs
Normal file
63
Nerd's Teaser Bot/Modules/Commands/TextModule.cs
Normal file
@ -0,0 +1,63 @@
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using NerdsTeaserBot.Misc;
|
||||
using NerdsTeaserBot.Modules.Models;
|
||||
using Nerd_STF.Lists;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using static Discord.Format;
|
||||
using static NerdsTeaserBot.Const;
|
||||
|
||||
namespace NerdsTeaserBot.Modules.Commands
|
||||
{
|
||||
[Name("Text")]
|
||||
[Summary("Commands related to messages sent")]
|
||||
public class TextModule : ModuleBase<SocketCommandContext>
|
||||
{
|
||||
[Command("purge")]
|
||||
[RequireUserPermission(GuildPermission.ManageMessages)]
|
||||
[Summary("Deletes a certain number of messages in the current channel")]
|
||||
public async Task Purge([Summary("The amount of messages to delete")] int amount) => await Purge((ITextChannel)Context.Channel, amount);
|
||||
|
||||
[Command("purge")]
|
||||
[RequireUserPermission(GuildPermission.ManageMessages)]
|
||||
[Summary("Deletes a certain number of messages in a given channel")]
|
||||
public async Task Purge([Summary("The text channel to delete the messages in")] ITextChannel channel, [Summary("The amount of messages to delete")] int amount)
|
||||
{
|
||||
List<IMessage> msgs = new(await channel.GetMessagesAsync(amount).FlattenAsync());
|
||||
|
||||
if (msgs.Length < amount)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Warning, "Amount is more than all messages in this channel. Defaulting to max");
|
||||
amount = msgs.Length;
|
||||
}
|
||||
|
||||
int failed = msgs.FindAll(x => x.CreatedAt < DateTime.Now - TimeSpan.FromDays(14)).Length, deleted = amount - failed;
|
||||
|
||||
await channel.DeleteMessagesAsync(msgs.FindAll(x => x.CreatedAt > DateTime.Now - TimeSpan.FromDays(14)).ToArray());
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "Statistics of the purge are below:",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = deleted + " Message",
|
||||
};
|
||||
if (deleted != 1) e.Title += "s";
|
||||
e.Title += " Deleted";
|
||||
|
||||
string add = amount + " Message";
|
||||
if (amount != 1) add += "s";
|
||||
|
||||
e.AddField("Attempted", Code(add), true);
|
||||
|
||||
add = failed + " Message";
|
||||
if (failed != 1) add += "s";
|
||||
|
||||
e.AddField("Failed", Code(add), true);
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
}
|
||||
}
|
||||
135
Nerd's Teaser Bot/Modules/Commands/UserModule.cs
Normal file
135
Nerd's Teaser Bot/Modules/Commands/UserModule.cs
Normal file
@ -0,0 +1,135 @@
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.Rest;
|
||||
using Discord.WebSocket;
|
||||
using NerdsTeaserBot.Misc;
|
||||
using NerdsTeaserBot.Modules.Models;
|
||||
using Nerd_STF.Lists;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using static Discord.Format;
|
||||
using static NerdsTeaserBot.Const;
|
||||
|
||||
namespace NerdsTeaserBot.Modules.Commands
|
||||
{
|
||||
[Name("User")]
|
||||
[Summary("Commands about a specific user")]
|
||||
public class UserModule : ModuleBase<SocketCommandContext>
|
||||
{
|
||||
[Command("avatar")]
|
||||
[Summary("The avatar of the user executing the command")]
|
||||
public async Task Avatar() => await Avatar(Context.User);
|
||||
[Command("avatar")]
|
||||
[Summary("The avatar of a user")]
|
||||
public async Task Avatar([Summary("The mention of the user")] SocketUser user)
|
||||
{
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Avatar for " + user.Username + "#" + user.Discriminator,
|
||||
ImageUrl = user.GetAvatarUrl(ImageFormat.Auto, 2048),
|
||||
};
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
[Command("avatar")]
|
||||
[Summary("The avatar of a user (found by their ID)")]
|
||||
public async Task Avatar([Summary("The user ID of the user")] ulong userID) => await Avatar(Context.Client.GetUser(userID));
|
||||
|
||||
[Command("userinfo")]
|
||||
[Summary("Info about the user executing the command")]
|
||||
public async Task Userinfo() => await Userinfo((RestUser)(IUser)Context.User);
|
||||
[Command("userinfo")]
|
||||
[Summary("Info about a user")]
|
||||
public async Task Userinfo([Summary("The mention of the user")] RestUser user)
|
||||
{
|
||||
string add = "";
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "*" + user.Mention + " ",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "User Info about " + user.Username + "#" + user.Discriminator,
|
||||
ThumbnailUrl = user.GetAvatarUrl(ImageFormat.Auto, 512),
|
||||
};
|
||||
|
||||
if (Context.Guild.GetUser(user.Id) != null) e.Description += Bold("IS");
|
||||
else e.Description += "is " + Bold("NOT");
|
||||
|
||||
e.Description += " in this server*";
|
||||
|
||||
e.AddField("Full Name:", Code(user.Username + "#" + user.Discriminator), true);
|
||||
e.AddField("User ID:", Code(user.Id.ToString()), true);
|
||||
e.AddField("Mention:", user.Mention, true);
|
||||
|
||||
add = "";
|
||||
if (user.ActiveClients.Count != 0) add = Code("None");
|
||||
foreach (ClientType c in user.ActiveClients) add += Code(c.ToString()) + "\n";
|
||||
e.AddField("Open Clients:", add, true);
|
||||
|
||||
add = Code("None");
|
||||
|
||||
if (user.Activity != null)
|
||||
{
|
||||
add = Italics("Activity:") + " " + Code(user.Activity.ToString()) + "\n";
|
||||
if (user.Activity.Name != null) add += Italics("Name:") + " " + Code(user.Activity.Name) + "\n";
|
||||
add += Italics("Type:") + " " + Code(user.Activity.Type.ToString()) + "\n";
|
||||
if (user.Activity.Details != null) add += Italics("Details:") + " " + Code(user.Activity.Details) + "\n";
|
||||
add += Italics("Flag:") + " " + Code(user.Activity.Flags.ToString());
|
||||
}
|
||||
|
||||
e.AddField("Activity:", add, true);
|
||||
|
||||
e.AddField("Account Created At:", Code(user.CreatedAt.DateTime.ToString()), true);
|
||||
e.AddField("Is Bot:", Code(user.IsBot.ToString()), true);
|
||||
e.AddField("Is Webhook:", Code(user.IsBot.ToString()), true);
|
||||
|
||||
e.AddField("Status:", Code(user.Status.ToString()), true);
|
||||
|
||||
SocketGuildUser usr = Context.Guild.GetUser(user.Id);
|
||||
if (usr != null)
|
||||
{
|
||||
add = "`" + Nerd_STF.Misc.PlaceMaker(usr.Hierarchy);
|
||||
if (usr.Hierarchy == int.MaxValue) add = "`Server Owner";
|
||||
add += "`";
|
||||
|
||||
e.AddField("Hierarchy:", add, true);
|
||||
|
||||
e.AddField("Deafened:", Code(usr.IsSelfDeafened.ToString()), true);
|
||||
e.AddField("Server Deafened:", Code(usr.IsDeafened.ToString()), true);
|
||||
e.AddField("Muted:", Code(usr.IsSelfDeafened.ToString()), true);
|
||||
e.AddField("Server Muted:", Code(usr.IsDeafened.ToString()), true);
|
||||
e.AddField("Streaming:", Code(usr.IsStreaming.ToString()), true);
|
||||
if (usr.JoinedAt.HasValue) e.AddField("Joined Server At:", Code(usr.JoinedAt.Value.DateTime.ToString()), true);
|
||||
|
||||
add = "None";
|
||||
if (usr.Nickname != null) add = usr.Nickname;
|
||||
|
||||
e.AddField("Nickname:", Code(add), true);
|
||||
|
||||
add = "Not Boosting";
|
||||
if (usr.PremiumSince.HasValue) add = usr.PremiumSince.Value.DateTime.ToString();
|
||||
|
||||
e.AddField("Server Boosting Since:", Code(add), true);
|
||||
|
||||
add = "Not in Voice Channel";
|
||||
if (usr.VoiceChannel != null) add = usr.VoiceChannel.Name;
|
||||
|
||||
e.AddField("Connected Voice Channel:", Code(add), true);
|
||||
|
||||
add = "";
|
||||
|
||||
foreach (SocketRole role in new List<SocketRole>(usr.Roles).FindAll(x => !x.IsEveryone && !x.IsManaged)) add += role.Mention + ", ";
|
||||
|
||||
e.AddField("Roles (Ignoring Mandatory Roles):", add.Remove(add.Length - 2));
|
||||
}
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
[Command("userinfo")]
|
||||
[Summary("Info about a user (found by their user ID)")]
|
||||
public async Task Userinfo([Summary("The user ID of the user")] ulong userID) => await Userinfo(await Context.Client.Rest.GetUserAsync(userID));
|
||||
}
|
||||
}
|
||||
304
Nerd's Teaser Bot/Modules/Commands/VariableModule.cs
Normal file
304
Nerd's Teaser Bot/Modules/Commands/VariableModule.cs
Normal file
@ -0,0 +1,304 @@
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.Net;
|
||||
using Discord.Rest;
|
||||
using Discord.WebSocket;
|
||||
using NerdsTeaserBot.Misc;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using static Discord.Format;
|
||||
using static NerdsTeaserBot.Const;
|
||||
|
||||
namespace NerdsTeaserBot.Modules.Commands
|
||||
{
|
||||
[Name("Variables")]
|
||||
[Summary("Includes commands for getting or setting variables in the bot that don't fit any other module")]
|
||||
public class VariableModule : ModuleBase<SocketCommandContext>
|
||||
{
|
||||
[Command("autopublish add")]
|
||||
[RequireUserPermission(GuildPermission.ManageChannels)]
|
||||
[Summary("Adds a text channel to the list of autopublishing channels")]
|
||||
public async Task AutopublishAdd([Summary("The text channel to add to the list")] ITextChannel channel)
|
||||
{
|
||||
if (channel.Guild.Id != Context.Guild.Id)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "Text channel is not in this server");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Data.misc.Data.publishChannels.Contains(channel.Id))
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "Text channel already exists in list");
|
||||
return;
|
||||
}
|
||||
|
||||
RestTextChannel c = await (await Context.Client.Rest.GetGuildAsync(Context.Guild.Id)).GetTextChannelAsync(channel.Id);
|
||||
if (c is not RestNewsChannel)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "Text channel is not a " + Url("Discord Announcement Channel", "https://support.discord.com/hc/en-us/articles/360032008192"));
|
||||
return;
|
||||
}
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "Any message sent in " + channel.Mention + " will now become automatically published to other servers",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Channel added to Autopublishing Channels",
|
||||
};
|
||||
|
||||
Data.misc.Data.publishChannels.Add(channel.Id);
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("autopublish list")]
|
||||
[Summary("Shows the current list of autopublishing channels")]
|
||||
public async Task AutopublishList()
|
||||
{
|
||||
int removedCount = 0;
|
||||
string[] text = new[] { "", "has", "it", "it is" };
|
||||
|
||||
for (int i = 0; i < Data.misc.Data.publishChannels.Length; i++)
|
||||
{
|
||||
ulong u = Data.misc.Data.publishChannels[i];
|
||||
RestTextChannel c = await (await Context.Client.Rest.GetGuildAsync(Context.Guild.Id)).GetTextChannelAsync(u);
|
||||
if (c == null || c is not RestNewsChannel)
|
||||
{
|
||||
Data.misc.Data.publishChannels.Remove(u);
|
||||
removedCount++;
|
||||
if (i >= 1) text = new[] { "s", "have", "them", "they are" };
|
||||
}
|
||||
}
|
||||
|
||||
if (removedCount != 0) LogModule.LogMessage(LogSeverity.Warning, removedCount + " Autopublishing Channel" + text[0] + " " + text[1] + " been removed for no longer being found in the server. This is because the channel" + text[0] + " may have been deleted, the bot can no longer see " + text[2] + ", or " + text[3] + " not a " + Url("Discord Announcement Channel", "https://support.discord.com/hc/en-us/articles/360032008192"));
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = Data.misc.Data.publishChannels.Length + " Autopublishing Channel",
|
||||
};
|
||||
|
||||
if (Data.misc.Data.publishChannels.Length != 1) e.Title += "s";
|
||||
|
||||
foreach (ulong u in Data.misc.Data.publishChannels) e.Description += "<#" + u + ">\n";
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("autopublish remove")]
|
||||
[RequireUserPermission(GuildPermission.ManageChannels)]
|
||||
[Summary("Removes a channel from the list of autopublish channels")]
|
||||
public async Task AutopublishRemove([Summary("The text channel to remove from the list")] ITextChannel channel)
|
||||
{
|
||||
if (!Data.misc.Data.announceChannels.Contains(channel.Id))
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "Channel not found in list");
|
||||
return;
|
||||
}
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Color.Red,
|
||||
Description = "The bot will no longer automatically publish any message in " + channel.Mention,
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Autopublish Channel Removed"
|
||||
};
|
||||
|
||||
Data.misc.Data.announceChannels.Remove(channel.Id);
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("changelog get")]
|
||||
[Summary("The current changelog channel of the bot")]
|
||||
public async Task ChangelogGet()
|
||||
{
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "The current changelog channel is: " + Italics("<#" + Data.misc.Data.changelogChannel + ">"),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Current changelog channel",
|
||||
};
|
||||
|
||||
if (Data.misc.Data.changelogChannel == default) e.Description = "No current changelog channel found. Use " + Code("n;changelog set") + " to set it!";
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("changelog reset")]
|
||||
[RequireUserPermission(GuildPermission.ManageChannels)]
|
||||
[Summary("Resets the changelog channel of the bot back to none")]
|
||||
public async Task ChangelogReset()
|
||||
{
|
||||
Data.misc.Data.changelogChannel = default;
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "Successfully set the current changelog channel to: " + Code("None"),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Reset changelog channel",
|
||||
};
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("changelog set")]
|
||||
[RequireUserPermission(GuildPermission.ManageChannels)]
|
||||
[Summary("Sets the given channel to the changelog channel of the bot")]
|
||||
public async Task ChangelogSet([Summary("The Text Channel to set the changelog to")] ITextChannel channel)
|
||||
{
|
||||
if (channel.Guild.Id != Context.Guild.Id)
|
||||
{
|
||||
LogModule.LogMessage(LogSeverity.Error, "Text channel is not in this server");
|
||||
return;
|
||||
}
|
||||
|
||||
ulong old = Data.misc.Data.changelogChannel;
|
||||
Data.misc.Data.changelogChannel = channel.Id;
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "Successfully set changelog channel to: " + Italics(channel.Mention),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Set changelog channel",
|
||||
};
|
||||
|
||||
if (old != default) e.Description += "\n(Previous: " + Italics("<#" + old + ">") + ")";
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("prefix get")]
|
||||
[Summary("The current prefix of the bot. Use it in commands")]
|
||||
public async Task PrefixGet()
|
||||
{
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "The current bot prefix is: " + Code(Data.misc.Data.prefix),
|
||||
Footer = new() { Text = "If all else fails, you can also mention me to execute a command" },
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Current Bot Prefix",
|
||||
};
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("prefix reset")]
|
||||
[RequireUserPermission(GuildPermission.ManageMessages)]
|
||||
[Summary("Resets the prefix of the bot back to the default, 'n;'")]
|
||||
public async Task PrefixReset()
|
||||
{
|
||||
Data.misc.Data.prefix = "n;";
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "Successfully set the current bot prefix to: " + Code("n;"),
|
||||
Footer = new() { Text = "If all else fails, you can also mention me to execute a command" },
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Reset Bot Prefix",
|
||||
};
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("prefix set")]
|
||||
[RequireUserPermission(GuildPermission.ManageMessages)]
|
||||
[Summary("Sets the given string to be the prefix of the bot")]
|
||||
public async Task PrefixSet([Summary("The new prefix to set the bot's prefix to")] string newPrefix)
|
||||
{
|
||||
string old = Data.misc.Data.prefix;
|
||||
Data.misc.Data.prefix = newPrefix;
|
||||
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "Successfully set the bot's prefix to: " + Code(newPrefix),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Set Bot Prefix",
|
||||
};
|
||||
|
||||
e.Description += "\n(Previous: " + Code(old) + ")";
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("serverlist add")]
|
||||
[RequireOwner]
|
||||
[Summary("Adds a server to the list of approved servers to join")]
|
||||
public async Task ServerlistAdd([Summary("The ID of the server you would like to add")] ulong id)
|
||||
{
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "The bot is now allowed to enter the server with the ID of " + Italics(Code(id.ToString())),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Approved Server",
|
||||
};
|
||||
|
||||
Data.misc.Data.allowedServers.Add(id);
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("serverlist list")]
|
||||
[Summary("Shows the list of approved servers to join")]
|
||||
public async Task ServerlistList()
|
||||
{
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Colors.DefaultColor,
|
||||
Description = "",
|
||||
Timestamp = DateTime.Now,
|
||||
Title = Data.misc.Data.allowedServers.Length + " Approved Server ID",
|
||||
};
|
||||
|
||||
if (Data.misc.Data.allowedServers.Length != 1) e.Title += "s";
|
||||
|
||||
foreach (ulong u in Data.misc.Data.allowedServers) e.Description += Italics(Code(u.ToString())) + "\n";
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
[Command("serverlist remove")]
|
||||
[RequireOwner]
|
||||
[Summary("Removes a server from the list of approved servers to join")]
|
||||
public async Task ServerlistRemove([Summary("The ID of the server you would like to remove")] ulong id)
|
||||
{
|
||||
EmbedBuilder e = new()
|
||||
{
|
||||
Color = Color.Red,
|
||||
Description = "The bot will no longer be permitted to enter a server with the ID of " + Italics(Code(id.ToString())),
|
||||
Timestamp = DateTime.Now,
|
||||
Title = "Server Prohibited",
|
||||
};
|
||||
|
||||
Data.misc.Data.allowedServers.Remove(id);
|
||||
|
||||
await ReplyAsync("", false, e.Build());
|
||||
}
|
||||
|
||||
// handles
|
||||
|
||||
public static async Task AutopublishHandler(SocketUserMessage msg)
|
||||
{
|
||||
if (!Data.misc.Data.publishChannels.Contains(msg.Channel.Id)) return;
|
||||
|
||||
RestTextChannel c = await (await Internals.context.Client.Rest.GetGuildAsync(Internals.context.Guild.Id)).GetTextChannelAsync(msg.Channel.Id);
|
||||
if (c is RestNewsChannel)
|
||||
{
|
||||
try { await msg.CrosspostAsync(); }
|
||||
catch(HttpException exe) when (exe.DiscordCode == 403) { LogModule.LogMessage(LogSeverity.Error, "Attempted to publish message, but failed. Error code 403"); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
18
Nerd's Teaser Bot/Modules/Extensions/IUserExtension.cs
Normal file
18
Nerd's Teaser Bot/Modules/Extensions/IUserExtension.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using Discord;
|
||||
using Discord.Net;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NerdsTeaserBot.Modules.Extensions
|
||||
{
|
||||
public static class IUserExtension
|
||||
{
|
||||
public static async Task<(IUserMessage, bool)> DMUserAsync(this IUser user, string msg = "", bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageComponent component = null)
|
||||
{
|
||||
(IUserMessage, bool) val = (null, false);
|
||||
try { val = (await user.SendMessageAsync(msg, isTTS, embed, options, allowedMentions, component), true); }
|
||||
catch (HttpException exe) when (exe.DiscordCode == 50007) { LogModule.LogMessage(LogSeverity.Warning, "Cannot DM this user. This is because the user most likely has the bot blocked"); }
|
||||
|
||||
return val;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
using Discord;
|
||||
using Discord.WebSocket;
|
||||
using Nerd_STF.Lists;
|
||||
|
||||
namespace NerdsTeaserBot.Modules.Extensions
|
||||
{
|
||||
public static class SocketGuildUserExtension
|
||||
{
|
||||
public static IRole GetHighestRole(this SocketGuildUser user)
|
||||
{
|
||||
List<IRole> roles = new(user.Roles);
|
||||
|
||||
IRole ret = roles[0];
|
||||
|
||||
foreach (IRole r in roles) if (r.Position > ret.Position) ret = r;
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
14
Nerd's Teaser Bot/Modules/HandlesModule.cs
Normal file
14
Nerd's Teaser Bot/Modules/HandlesModule.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NerdsTeaserBot.Modules
|
||||
{
|
||||
public static class HandlesModule
|
||||
{
|
||||
internal static Func<SocketUserMessage, Task> OnUserMessageRecieved;
|
||||
}
|
||||
}
|
||||
14
Nerd's Teaser Bot/Modules/Models/ConstData.cs
Normal file
14
Nerd's Teaser Bot/Modules/Models/ConstData.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NerdsTeaserBot.Modules.Models
|
||||
{
|
||||
[Serializable]
|
||||
public class ConstData
|
||||
{
|
||||
public ulong modmailCategory;
|
||||
public int statusNum;
|
||||
}
|
||||
}
|
||||
14
Nerd's Teaser Bot/Modules/Models/Credit.cs
Normal file
14
Nerd's Teaser Bot/Modules/Models/Credit.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NerdsTeaserBot.Modules.Models
|
||||
{
|
||||
[Serializable]
|
||||
public class Credit
|
||||
{
|
||||
public ulong id;
|
||||
public string reason = "Honerable mention.";
|
||||
}
|
||||
}
|
||||
29
Nerd's Teaser Bot/Modules/Models/Level.cs
Normal file
29
Nerd's Teaser Bot/Modules/Models/Level.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NerdsTeaserBot.Modules.Models
|
||||
{
|
||||
[Serializable]
|
||||
public class Level
|
||||
{
|
||||
public int MaxXP => level * 100 + 100;
|
||||
public int TotalXP
|
||||
{
|
||||
get
|
||||
{
|
||||
int ret = 0;
|
||||
for (int i = 0; i < level; i++) ret += 1 * 100 + 100;
|
||||
ret += xp;
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
public int countedMsgs;
|
||||
public DateTime lastCountedMsg;
|
||||
public int level;
|
||||
public int msgs;
|
||||
public int xp;
|
||||
}
|
||||
}
|
||||
23
Nerd's Teaser Bot/Modules/Models/MiscData.cs
Normal file
23
Nerd's Teaser Bot/Modules/Models/MiscData.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using Nerd_STF.Lists;
|
||||
using System;
|
||||
|
||||
namespace NerdsTeaserBot.Modules.Models
|
||||
{
|
||||
[Serializable]
|
||||
public class MiscData
|
||||
{
|
||||
public List<ulong> announceChannels = new();
|
||||
public List<ulong> allowedServers = new();
|
||||
public ulong changelogChannel;
|
||||
public int levelCooldown = 60;
|
||||
public bool levelMention;
|
||||
public ulong logChannel;
|
||||
public List<string> memeSubs = new();
|
||||
public ulong messagingC;
|
||||
public List<Poll> polls = new();
|
||||
public string prefix = "n;";
|
||||
public List<ulong> publishChannels = new();
|
||||
public List<ulong> roles = new();
|
||||
public List<Tag> tags = new();
|
||||
}
|
||||
}
|
||||
36
Nerd's Teaser Bot/Modules/Models/Mute.cs
Normal file
36
Nerd's Teaser Bot/Modules/Models/Mute.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NerdsTeaserBot.Modules.Models
|
||||
{
|
||||
[Serializable]
|
||||
public class Mute
|
||||
{
|
||||
public bool IsMuted
|
||||
{
|
||||
get
|
||||
{
|
||||
bool ret = release < DateTime.Now;
|
||||
if (unmute != null) if (unmute.moderator != default) ret |= unmute.time < DateTime.Now;
|
||||
|
||||
return !ret;
|
||||
}
|
||||
}
|
||||
|
||||
public ulong moderator;
|
||||
public string reason;
|
||||
public DateTime release;
|
||||
public DateTime start;
|
||||
public Unmute unmute;
|
||||
|
||||
[Serializable]
|
||||
public class Unmute
|
||||
{
|
||||
public ulong moderator;
|
||||
public string reason;
|
||||
public DateTime time;
|
||||
}
|
||||
}
|
||||
}
|
||||
46
Nerd's Teaser Bot/Modules/Models/Poll.cs
Normal file
46
Nerd's Teaser Bot/Modules/Models/Poll.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using Discord;
|
||||
using Discord.WebSocket;
|
||||
using Nerd_STF.Lists;
|
||||
using System;
|
||||
using static Discord.Format;
|
||||
|
||||
namespace NerdsTeaserBot.Modules.Models
|
||||
{
|
||||
[Serializable]
|
||||
public class Poll
|
||||
{
|
||||
public string hash;
|
||||
public List<User> voters = new();
|
||||
|
||||
public void Update(SocketUserMessage msg)
|
||||
{
|
||||
EmbedBuilder e = new List<Embed>(msg.Embeds)[0].ToEmbedBuilder();
|
||||
|
||||
string[] options = e.Description.Split("\n");
|
||||
|
||||
for (int i = 0; i < options.Length; i++)
|
||||
{
|
||||
int p = -1;
|
||||
for (int j = 0; j < options[i].Length; j++) if (options[i][j] == '`') p = j;
|
||||
|
||||
options[i] = options[i].Remove(p);
|
||||
|
||||
int num = voters.FindAll(x => x.option == i + 1).Length;
|
||||
|
||||
options[i] += "` - " + Bold(num + " Votes");
|
||||
}
|
||||
|
||||
e.Description = "";
|
||||
foreach (string s in options) e.Description += s + "\n";
|
||||
|
||||
msg.ModifyAsync(x => x.Embed = e.Build());
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class User
|
||||
{
|
||||
public ulong id;
|
||||
public byte option;
|
||||
}
|
||||
}
|
||||
}
|
||||
35
Nerd's Teaser Bot/Modules/Models/Static.cs
Normal file
35
Nerd's Teaser Bot/Modules/Models/Static.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NerdsTeaserBot.Modules.Models
|
||||
{
|
||||
public static class Static
|
||||
{
|
||||
public static Credit[] Credits
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Credit[]
|
||||
{
|
||||
new()
|
||||
{
|
||||
id = 478210457816006666,
|
||||
reason = "Main development of the bot.",
|
||||
},
|
||||
|
||||
new()
|
||||
{
|
||||
id = 533776358980059137,
|
||||
reason = "Gave suggestions.",
|
||||
},
|
||||
|
||||
new() { id = 750087661569703957 },
|
||||
|
||||
new() { id = 550845244137275453 },
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
15
Nerd's Teaser Bot/Modules/Models/Tag.cs
Normal file
15
Nerd's Teaser Bot/Modules/Models/Tag.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NerdsTeaserBot.Modules.Models
|
||||
{
|
||||
[Serializable]
|
||||
public class Tag
|
||||
{
|
||||
public string name;
|
||||
public ulong owner;
|
||||
public string response;
|
||||
}
|
||||
}
|
||||
15
Nerd's Teaser Bot/Modules/Models/User.cs
Normal file
15
Nerd's Teaser Bot/Modules/Models/User.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using Nerd_STF.Lists;
|
||||
using System;
|
||||
|
||||
namespace NerdsTeaserBot.Modules.Models
|
||||
{
|
||||
[Serializable]
|
||||
public class User
|
||||
{
|
||||
public Mute currentMute;
|
||||
public Level level;
|
||||
public int tickets;
|
||||
public ulong userID;
|
||||
public List<Warn> warns = new();
|
||||
}
|
||||
}
|
||||
16
Nerd's Teaser Bot/Modules/Models/Warn.cs
Normal file
16
Nerd's Teaser Bot/Modules/Models/Warn.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NerdsTeaserBot.Modules.Models
|
||||
{
|
||||
[Serializable]
|
||||
public class Warn
|
||||
{
|
||||
public string hash;
|
||||
public ulong moderator;
|
||||
public string reason;
|
||||
public DateTime time;
|
||||
}
|
||||
}
|
||||
12
Nerd's Teaser Bot/Modules/TypeReaders/PollTypeReader.cs
Normal file
12
Nerd's Teaser Bot/Modules/TypeReaders/PollTypeReader.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using Discord.Commands;
|
||||
using NerdsTeaserBot.Misc;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NerdsTeaserBot.Modules.TypeReaders
|
||||
{
|
||||
public class PollTypeReader : TypeReader
|
||||
{
|
||||
public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider services) => Task.FromResult(TypeReaderResult.FromSuccess(Data.misc.Data.polls.FindOrDefault(x => x.hash == input.Trim())));
|
||||
}
|
||||
}
|
||||
12
Nerd's Teaser Bot/Modules/TypeReaders/TagTypeReader.cs
Normal file
12
Nerd's Teaser Bot/Modules/TypeReaders/TagTypeReader.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using Discord.Commands;
|
||||
using NerdsTeaserBot.Misc;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NerdsTeaserBot.Modules.TypeReaders
|
||||
{
|
||||
public class TagTypeReader : TypeReader
|
||||
{
|
||||
public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider services) => Task.FromResult(TypeReaderResult.FromSuccess(Data.misc.Data.tags.FindOrDefault(x => x.name == input.Trim().ToLower())));
|
||||
}
|
||||
}
|
||||
12
Nerd's Teaser Bot/Modules/TypeReaders/UserTypeReader.cs
Normal file
12
Nerd's Teaser Bot/Modules/TypeReaders/UserTypeReader.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using Discord.Commands;
|
||||
using NerdsTeaserBot.Misc;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NerdsTeaserBot.Modules.TypeReaders
|
||||
{
|
||||
public class UserTypeReader : TypeReader
|
||||
{
|
||||
public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider services) => Task.FromResult(TypeReaderResult.FromSuccess(Data.users.Data.FindOrDefault(x => x.userID.ToString() == input || "<@" + x.userID + ">" == input || "<@!" + x.userID + ">" == input)));
|
||||
}
|
||||
}
|
||||
21
Nerd's Teaser Bot/Modules/TypeReaders/WarnTypeReader.cs
Normal file
21
Nerd's Teaser Bot/Modules/TypeReaders/WarnTypeReader.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using Discord.Commands;
|
||||
using NerdsTeaserBot.Misc;
|
||||
using NerdsTeaserBot.Modules.Models;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NerdsTeaserBot.Modules.TypeReaders
|
||||
{
|
||||
public class WarnTypeReader : TypeReader
|
||||
{
|
||||
public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider services)
|
||||
{
|
||||
foreach (User u in Data.users.Data)
|
||||
{
|
||||
Warn w = u.warns.FindOrDefault(x => x.hash == input);
|
||||
if (w is not null) return Task.FromResult(TypeReaderResult.FromSuccess(w));
|
||||
}
|
||||
return Task.FromResult(TypeReaderResult.FromSuccess(null));
|
||||
}
|
||||
}
|
||||
}
|
||||
8
README.md
Normal file
8
README.md
Normal file
@ -0,0 +1,8 @@
|
||||
# Nerd's Teaser Bot
|
||||
|
||||
Nerd's Teaser Bot is a bot I made to run my server mainly, but as I developed it more and more, I realized I could release it to the public just fine. So, here you go!
|
||||
This is being posted to the internet not so much to allow others to fork it, but more to look at the code. If you want the bot, you can invite it yourself.
|
||||
|
||||
Here are some links:
|
||||
+ <a href = "https://discord.gg/Ek7R3gx">Discord</a>
|
||||
+ <a href = "https://that-one-nerd.itch.io/">Itch</a>
|
||||
Loading…
x
Reference in New Issue
Block a user