diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..b3f8cdb --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,27 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "github-actions" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "weekly" + allow: + # Allow both direct and indirect updates for all packages + - dependency-type: "all" + assignees: + - "l1ttleO" + + - package-ecosystem: "nuget" # See documentation for possible values + directory: "/Boyfriend" # Location of package manifests + schedule: + interval: "weekly" + allow: + # Allow both direct and indirect updates for all packages + - dependency-type: "all" + # Add assignees + assignees: + - "l1ttleO" diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..4bd4390 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,44 @@ +name: "CodeQL" + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + schedule: + - cron: '45 7 * * 2' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'csharp' ] + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + queries: +security-extended,security-and-quality + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" diff --git a/Boyfriend/Boyfriend.cs b/Boyfriend/Boyfriend.cs index df38768..b0ec6ce 100644 --- a/Boyfriend/Boyfriend.cs +++ b/Boyfriend/Boyfriend.cs @@ -83,7 +83,7 @@ public static class Boyfriend { if (!RemovedRolesDictionary.ContainsKey(id)) RemovedRolesDictionary.Add(id, new Dictionary>()); - if (GuildConfigDictionary.ContainsKey(id)) return GuildConfigDictionary[id]; + if (GuildConfigDictionary.TryGetValue(id, out var cfg)) return cfg; var path = $"config_{id}.json"; @@ -110,7 +110,7 @@ public static class Boyfriend { } public static Dictionary> GetRemovedRoles(ulong id) { - if (RemovedRolesDictionary.ContainsKey(id)) return RemovedRolesDictionary[id]; + if (RemovedRolesDictionary.TryGetValue(id, out var dict)) return dict; var path = $"removedroles_{id}.json"; @@ -126,7 +126,7 @@ public static class Boyfriend { } public static SocketGuild FindGuild(ulong channel) { - if (GuildCache.ContainsKey(channel)) return GuildCache[channel]; + if (GuildCache.TryGetValue(channel, out var gld)) return gld; foreach (var guild in Client.Guilds) { // ReSharper disable once LoopCanBeConvertedToQuery foreach (var x in guild.Channels) diff --git a/Boyfriend/Boyfriend.csproj b/Boyfriend/Boyfriend.csproj index 4b1917d..e58826a 100644 --- a/Boyfriend/Boyfriend.csproj +++ b/Boyfriend/Boyfriend.csproj @@ -8,11 +8,11 @@ default Boyfriend l1ttle - https://git.cavej376.xyz/Octol1ttle/Boyfriend-CSharp - https://git.cavej376.xyz/Octol1ttle/Boyfriend-CSharp + https://github.com/l1ttleO/Boyfriend-CSharp + https://github.com/l1ttleO/Boyfriend-CSharp git - 1.0.1 - https://git.cavej376.xyz/Octol1ttle/Boyfriend-CSharp/src/branch/master/LICENSE + 1.0.0 + https://github.com/l1ttleO/Boyfriend-CSharp/blob/master/LICENSE en diff --git a/Boyfriend/CommandProcessor.cs b/Boyfriend/CommandProcessor.cs index c4cfbc1..06bbe2e 100644 --- a/Boyfriend/CommandProcessor.cs +++ b/Boyfriend/CommandProcessor.cs @@ -1,5 +1,4 @@ using System.Text; -using System.Text.RegularExpressions; using Boyfriend.Commands; using Discord; using Discord.Commands; @@ -14,14 +13,14 @@ public sealed class CommandProcessor { private const string NoAccess = ":no_entry_sign: "; private const string CantInteract = ":vertical_traffic_light: "; + private const string Mention = "<@855023234407333888>"; + public static readonly ICommand[] Commands = { new BanCommand(), new ClearCommand(), new HelpCommand(), new KickCommand(), new MuteCommand(), new PingCommand(), new SettingsCommand(), new UnbanCommand(), new UnmuteCommand() }; - private static readonly Dictionary RegexCache = new(); - private static readonly Regex MentionRegex = new(Regex.Escape("<@855023234407333888>"), RegexOptions.Compiled); private readonly StringBuilder _stackedPrivateFeedback = new(); private readonly StringBuilder _stackedPublicFeedback = new(); private readonly StringBuilder _stackedReplyMessage = new(); @@ -46,16 +45,10 @@ public sealed class CommandProcessor { return; } - Regex regex; - if (RegexCache.ContainsKey(config["Prefix"])) { regex = RegexCache[config["Prefix"]]; } else { - regex = new Regex(Regex.Escape(config["Prefix"]), RegexOptions.Compiled | RegexOptions.IgnoreCase); - RegexCache.Add(config["Prefix"], regex); - } - var list = Context.Message.Content.Split("\n"); var cleanList = Context.Message.CleanContent.Split("\n"); for (var i = 0; i < list.Length; i++) { - RunCommandOnLine(list[i], cleanList[i], regex); + RunCommandOnLine(list[i], cleanList[i], config["Prefix"]); if (_serverBlacklisted) { await Context.Message.ReplyAsync(Messages.ServerBlacklisted); return; @@ -78,20 +71,21 @@ public sealed class CommandProcessor { SendFeedbacks(); } - private void RunCommandOnLine(string line, string cleanLine, Regex regex) { + private void RunCommandOnLine(string line, string cleanLine, string prefix) { + var prefixed = line[..prefix.Length] == prefix; + if (!prefixed && line[..Mention.Length] is not Mention) return; foreach (var command in Commands) { - var lineNoMention = regex.Replace(MentionRegex.Replace(line, "", 1), "", 1); - if (lineNoMention == line - || !command.Aliases.Contains(lineNoMention.Trim().ToLower().Split()[0])) - continue; + var lineNoMention = line.Remove(0, prefixed ? prefix.Length : Mention.Length); + if (!command.Aliases.Contains(lineNoMention.Trim().Split()[0])) continue; if (Utils.IsServerBlacklisted(Context.Guild)) { _serverBlacklisted = true; return; } - var args = line.Split().Skip(lineNoMention.StartsWith(" ") ? 2 : 1).ToArray(); + var args = lineNoMention.Trim().Split().Skip(1).ToArray(); var cleanArgs = cleanLine.Split().Skip(lineNoMention.StartsWith(" ") ? 2 : 1).ToArray(); _tasks.Add(command.RunAsync(this, args, cleanArgs)); + return; } } diff --git a/Boyfriend/Commands/MuteCommand.cs b/Boyfriend/Commands/MuteCommand.cs index 998c65e..bc608f9 100644 --- a/Boyfriend/Commands/MuteCommand.cs +++ b/Boyfriend/Commands/MuteCommand.cs @@ -26,8 +26,8 @@ public sealed class MuteCommand : ICommand { var rolesRemoved = Boyfriend.GetRemovedRoles(cmd.Context.Guild.Id); - if (rolesRemoved.ContainsKey(toMute.Id)) { - foreach (var roleId in rolesRemoved[toMute.Id]) await toMute.AddRoleAsync(roleId); + if (rolesRemoved.TryGetValue(toMute.Id, out var mutedRemovedRoles)) { + foreach (var roleId in mutedRemovedRoles) await toMute.AddRoleAsync(roleId); rolesRemoved.Remove(toMute.Id); cmd.ConfigWriteScheduled = true; cmd.Reply(Messages.RolesReturned, ":warning: "); diff --git a/Boyfriend/Commands/SettingsCommand.cs b/Boyfriend/Commands/SettingsCommand.cs index f2ea68d..34d2bc5 100644 --- a/Boyfriend/Commands/SettingsCommand.cs +++ b/Boyfriend/Commands/SettingsCommand.cs @@ -110,10 +110,9 @@ public sealed class SettingsCommand : ICommand { }; if (value is "reset" or "default") { - if (selectedSetting is "WelcomeMessage") - config[selectedSetting] = Messages.DefaultWelcomeMessage; - else - config[selectedSetting] = Boyfriend.DefaultConfig[selectedSetting]; + config[selectedSetting] = selectedSetting is "WelcomeMessage" + ? Messages.DefaultWelcomeMessage + : Boyfriend.DefaultConfig[selectedSetting]; } else { if (value == config[selectedSetting]) { cmd.Reply(string.Format(Messages.SettingsNothingChanged, localizedSelectedSetting, formattedValue), diff --git a/Boyfriend/Commands/UnmuteCommand.cs b/Boyfriend/Commands/UnmuteCommand.cs index 8297830..b6a1aa9 100644 --- a/Boyfriend/Commands/UnmuteCommand.cs +++ b/Boyfriend/Commands/UnmuteCommand.cs @@ -23,8 +23,8 @@ public sealed class UnmuteCommand : ICommand { if (role != null && toUnmute.Roles.Contains(role)) { var rolesRemoved = Boyfriend.GetRemovedRoles(cmd.Context.Guild.Id); - if (rolesRemoved.ContainsKey(toUnmute.Id)) { - await toUnmute.AddRolesAsync(rolesRemoved[toUnmute.Id]); + if (rolesRemoved.TryGetValue(toUnmute.Id, out var unmutedRemovedRoles)) { + await toUnmute.AddRolesAsync(unmutedRemovedRoles); rolesRemoved.Remove(toUnmute.Id); cmd.ConfigWriteScheduled = true; } diff --git a/Boyfriend/Messages.mc.resx b/Boyfriend/Messages.mc.resx new file mode 100644 index 0000000..19db310 --- /dev/null +++ b/Boyfriend/Messages.mc.resx @@ -0,0 +1,378 @@ + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, + PublicKeyToken=b77a5c561934e089 + + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, + PublicKeyToken=b77a5c561934e089 + + + + {0}я родился! (C#) + + + вырезано {0} в канале {1}: {2} + + + ты тут распинался сильно, иди отдохни. + + + переделано {0}: {1} -> {2} + + + {0}, добро пожаловать на сервер {1} + + + брах! + + + брох! + + + брух! + + + у меня прав нету, сделай что нибудь. + + + у тебя прав нету, твои проблемы. + + + здарова, тебя крч забанил {0} на сервере {1} за {2} + + + время бана закончиловсь + + + ты выбрал менее {0} сообщений + + + ты выбрал более {0} сообщений + + + туториал по приколам: + + + здарова, тебя крч кикнул {0} на сервере {1} за {2} + + + мс + + + шизоид уже замучен! + + + *тут ничего нет* + + + *тут ничего нет* + + + настройки: + + + язык + + + префикс + + + удалять звание при муте + + + разглашать о том что пришел новый шизоид + + + роль замученного + + + канал админ-уведомлений + + + канал бот-уведомлений + + + такого языка нету, ты шо + + + да + + + нъет + + + шизик не забанен + + + шизоид не замучен! + + + кто-то решил поумничать и обошел роль мута. я ее вернул. + + + приветствие + + + выбери число от {0} до {1} вместо {2}! + + + забанен {0} на{1}: {2} + + + шизик не на этом сервере + + + такой прикол не существует + + + получать инфу о рождении бота + + + криво настроил прикол, давай по новой + + + этого звания нету, ты шо + + + этого канала нету, ты шо + + + я не украл звание {0} в связи с ошибкой! {1} + + + ты шо, мутить больше чем на 28 дней таймаут не разрешает, вот настроишь роль мута, тогда поговорим + + + я не могу замутить ботов, сделай что нибудь + + + базовое звание + + + {1}{2} приготовил новый квест {3}! он пройдёт в {4} и начнётся <t:{5}:R>!{0}{6} + + + роль для уведомлений о создании квеста + + + канал для уведомлений о создании квеста + + + канал для уведомлений о начале квеста + + + получатели уведомлений о начале квеста + + + {0}квест {1} начинается в {2}! + + + оъмъомоъемъъео(((( + + + квест {0} отменен!{1} + + + канал для уведомлений о отмене событий + + + канал для уведомлений о завершении квеста + + + квест {0} завершен! все это длилось {1} + + + *[{0}: {1}]* + + + всегда + + + удалено {0} сообщений в {1} + + + выгнан {0}: {1} + + + замучен {0} на{1}: {2} + + + раззабанен {0}: {1} + + + раззамучен {0}: {1} + + + ты все сломал! значение прикола `{0}` и так {1} + + + *тут ничего нет* + + + прикол для `{0}` теперь установлен на {1} + + + возводит великий банхаммер над шизоидом + + + удаляет сообщения. сколько хош, столько и удалит + + + показывает то, что ты сейчас видишь прямо сейчас + + + выпинывает шизоида + + + мутит шизоида + + + показывает пинг (сверхмегаточный (нет)) + + + настройки бота под этот сервер + + + отводит великий банхаммер от шизоида + + + раззамучивает шизоида + + + укажи целое число от {0} до {1} + + + укажи самого шизика + + + надо указать юзверя вместо {0}! + + + укажи самого шизика + + + укажи шизоида сервера вместо {0}! + + + бан + + + Ты не можешь управлять сообщениями этого сервера! + + + кик шизиков нельзя + + + тебе нельзя управлять шизоидами + + + тебе нельзя редактировать дурку + + + я не могу ваще никого банить чел. + + + я не могу исправлять орфографический кринж участников, сделай что нибудь. + + + я не могу ваще никого кикать чел. + + + я не могу контроллировать за всеми ними, сделай что нибудь. + + + я не могу этому серверу хоть че либо нибудь изменить, сделай что нибудь. + + + укажи зачем банить шизика + + + укажи зачем кикать шизика + + + укажи зачем мутить шизика + + + укажи настройку которую менять нужно + + + укажи зачем раззабанивать шизика + + + укажи зачам размучивать шизика + + + че ты там вякнул? + + + бан админу нельзя + + + бан этому шизику нельзя + + + самобан нельзя + + + я не могу его забанить... + + + кик админу нельзя + + + самокик нельзя + + + че ты там вякнул? + + + я не могу его кикнуть... + + + кик этому шизику нельзя + + + мут админу нельзя + + + самомут нельзя + + + че ты там вякнул? + + + я не могу его замутить... + + + мут этому шизику нельзя + + + ты шо далбайоп шоле, админ замозамучался, не трожь + + + ты замучен. + + + ... + + + тебе нельзя раззамучивать + + + я не могу его раззамутить... + + + каве пропал. + + + упс, кажется ваш сервер в черном списке, и я вам ничем помочь не смогу) + + diff --git a/Boyfriend/Utils.cs b/Boyfriend/Utils.cs index 4ec2865..f089435 100644 --- a/Boyfriend/Utils.cs +++ b/Boyfriend/Utils.cs @@ -66,7 +66,7 @@ public static class Utils { public static SocketRole? GetMuteRole(SocketGuild guild) { var id = ulong.Parse(Boyfriend.GetGuildConfig(guild.Id)["MuteRole"]); - if (MuteRoleCache.ContainsKey(id)) return MuteRoleCache[id]; + if (MuteRoleCache.TryGetValue(id, out var cachedMuteRole)) return cachedMuteRole; SocketRole? role = null; foreach (var x in guild.Roles) { if (x.Id != id) continue; @@ -89,7 +89,6 @@ public static class Utils { await channel.SendMessageAsync(text, false, null, null, allowRoles ? AllowRoles : AllowedMentions.None); } - public static RequestOptions GetRequestOptions(string reason) { var options = RequestOptions.Default; options.AuditLogReason = reason; @@ -99,7 +98,7 @@ public static class Utils { public static string GetMessage(string name) { var propertyName = name; name = $"{Messages.Culture}/{name}"; - if (ReflectionMessageCache.ContainsKey(name)) return ReflectionMessageCache[name]; + if (ReflectionMessageCache.TryGetValue(name, out var cachedMessage)) return cachedMessage; var toReturn = typeof(Messages).GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Static)?.GetValue(null)