2018-07-19 12:42:48 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Threading.Tasks;
|
2019-08-22 14:47:28 +00:00
|
|
|
|
using CompatBot.Commands;
|
2018-07-19 12:42:48 +00:00
|
|
|
|
using CompatBot.Utils;
|
2019-03-20 12:08:47 +00:00
|
|
|
|
using CompatBot.Utils.Extensions;
|
2018-07-19 12:42:48 +00:00
|
|
|
|
using DSharpPlus;
|
|
|
|
|
using DSharpPlus.Entities;
|
|
|
|
|
using DSharpPlus.EventArgs;
|
|
|
|
|
|
|
|
|
|
namespace CompatBot.EventHandlers
|
|
|
|
|
{
|
|
|
|
|
internal static class Starbucks
|
|
|
|
|
{
|
2019-03-20 13:10:13 +00:00
|
|
|
|
private static readonly Dictionary<DiscordEmoji, string> TextMap = new Dictionary<DiscordEmoji, string>
|
|
|
|
|
{
|
|
|
|
|
[DiscordEmoji.FromUnicode("Ⓜ")] = "M",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🅰")] = "A",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🅱")] = "B",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🆎")] = "AB",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🅾")] = "O",
|
|
|
|
|
|
|
|
|
|
[DiscordEmoji.FromUnicode("🇦")] = "A",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🇧")] = "B",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🇨")] = "C",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🇩")] = "D",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🇪")] = "E",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🇫")] = "F",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🇬")] = "G",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🇭")] = "H",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🇮")] = "I",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🇯")] = "G",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🇰")] = "K",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🇱")] = "L",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🇲")] = "M",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🇳")] = "N",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🇴")] = "O",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🇵")] = "P",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🇶")] = "Q",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🇷")] = "R",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🇸")] = "S",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🇹")] = "T",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🇺")] = "U",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🇻")] = "V",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🇼")] = "W",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🇽")] = "X",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🇾")] = "Y",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🇿")] = "Z",
|
|
|
|
|
|
2019-05-10 18:09:46 +00:00
|
|
|
|
[DiscordEmoji.FromUnicode("0\u20E3")] = "0",
|
|
|
|
|
[DiscordEmoji.FromUnicode("1\u20E3")] = "1",
|
|
|
|
|
[DiscordEmoji.FromUnicode("2\u20E3")] = "2",
|
|
|
|
|
[DiscordEmoji.FromUnicode("3\u20E3")] = "3",
|
|
|
|
|
[DiscordEmoji.FromUnicode("4\u20E3")] = "4",
|
|
|
|
|
[DiscordEmoji.FromUnicode("5\u20E3")] = "5",
|
|
|
|
|
[DiscordEmoji.FromUnicode("6\u20E3")] = "6",
|
|
|
|
|
[DiscordEmoji.FromUnicode("7\u20E3")] = "7",
|
|
|
|
|
[DiscordEmoji.FromUnicode("8\u20E3")] = "8",
|
|
|
|
|
[DiscordEmoji.FromUnicode("9\u20E3")] = "9",
|
2019-03-20 13:10:13 +00:00
|
|
|
|
[DiscordEmoji.FromUnicode("🔟")] = "10",
|
2019-05-10 18:09:46 +00:00
|
|
|
|
[DiscordEmoji.FromUnicode("💯")] = "100",
|
2019-03-20 13:10:13 +00:00
|
|
|
|
|
|
|
|
|
[DiscordEmoji.FromUnicode("🆑")] = "CL",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🆐")] = "DJ",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🆒")] = "COOL",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🆓")] = "FREE",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🆔")] = "ID",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🆕")] = "NEW",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🆖")] = "NG",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🆗")] = "OK",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🆘")] = "SOS",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🆙")] = "UP",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🆚")] = "VS",
|
|
|
|
|
[DiscordEmoji.FromUnicode("⭕")] = "O",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🔄")] = "O",
|
|
|
|
|
[DiscordEmoji.FromUnicode("✝")] = "T",
|
|
|
|
|
[DiscordEmoji.FromUnicode("❌")] = "X",
|
|
|
|
|
[DiscordEmoji.FromUnicode("✖")] = "X",
|
|
|
|
|
[DiscordEmoji.FromUnicode("❎")] = "X",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🅿")] = "P",
|
|
|
|
|
[DiscordEmoji.FromUnicode("🚾")] = "WC",
|
|
|
|
|
[DiscordEmoji.FromUnicode("ℹ")] = "i",
|
|
|
|
|
[DiscordEmoji.FromUnicode("〰")] = "W",
|
|
|
|
|
};
|
2019-03-20 09:05:37 +00:00
|
|
|
|
|
2018-07-19 12:42:48 +00:00
|
|
|
|
public static Task Handler(MessageReactionAddEventArgs args)
|
|
|
|
|
{
|
2019-08-22 14:47:28 +00:00
|
|
|
|
return CheckMessageAsync(args.Client, args.Channel, args.User, args.Message, args.Emoji, false);
|
2018-07-19 12:42:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-08-18 15:37:58 +00:00
|
|
|
|
public static async Task CheckBacklogAsync(DiscordClient client, DiscordGuild guild)
|
2018-07-19 12:42:48 +00:00
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2018-08-18 15:37:58 +00:00
|
|
|
|
var after = DateTime.UtcNow - Config.ModerationTimeThreshold;
|
2018-07-19 12:42:48 +00:00
|
|
|
|
var checkTasks = new List<Task>();
|
2019-04-20 12:56:16 +00:00
|
|
|
|
foreach (var channel in guild.Channels.Values.Where(ch => Config.Moderation.Channels.Contains(ch.Id)))
|
2018-07-19 12:42:48 +00:00
|
|
|
|
{
|
|
|
|
|
var messages = await channel.GetMessagesAsync().ConfigureAwait(false);
|
|
|
|
|
var messagesToCheck = from msg in messages
|
|
|
|
|
where msg.CreationTimestamp > after && msg.Reactions.Any(r => r.Emoji == Config.Reactions.Starbucks && r.Count >= Config.Moderation.StarbucksThreshold)
|
|
|
|
|
select msg;
|
|
|
|
|
foreach (var message in messagesToCheck)
|
|
|
|
|
{
|
|
|
|
|
var reactionUsers = await message.GetReactionsAsync(Config.Reactions.Starbucks).ConfigureAwait(false);
|
|
|
|
|
if (reactionUsers.Count > 0)
|
2019-08-22 14:47:28 +00:00
|
|
|
|
checkTasks.Add(CheckMessageAsync(client, channel, reactionUsers[0], message, Config.Reactions.Starbucks, true));
|
2018-07-19 12:42:48 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
await Task.WhenAll(checkTasks).ConfigureAwait(false);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
2018-10-05 17:56:44 +00:00
|
|
|
|
Config.Log.Error(e);
|
2018-07-19 12:42:48 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-22 14:47:28 +00:00
|
|
|
|
private static async Task CheckMessageAsync(DiscordClient client, DiscordChannel channel, DiscordUser user, DiscordMessage message, DiscordEmoji emoji, bool isBacklog)
|
2018-07-19 12:42:48 +00:00
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2019-03-20 12:08:47 +00:00
|
|
|
|
if (user.IsBotSafeCheck() || channel.IsPrivate)
|
2018-07-19 12:42:48 +00:00
|
|
|
|
return;
|
|
|
|
|
|
2019-03-20 09:05:37 +00:00
|
|
|
|
// in case it's not in cache and doesn't contain any info, including Author
|
|
|
|
|
message = await channel.GetMessageAsync(message.Id).ConfigureAwait(false);
|
|
|
|
|
if (emoji == Config.Reactions.Starbucks)
|
|
|
|
|
await CheckMediaTalkAsync(client, channel, message, emoji).ConfigureAwait(false);
|
2019-08-22 14:47:28 +00:00
|
|
|
|
if (emoji == Config.Reactions.Shutup && !isBacklog)
|
2019-05-10 18:31:56 +00:00
|
|
|
|
await ShutupAsync(client, user, message).ConfigureAwait(false);
|
2019-08-22 14:47:28 +00:00
|
|
|
|
if (emoji == Config.Reactions.BadUpdate && !isBacklog)
|
|
|
|
|
await BadUpdateAsync(client, user, message, emoji).ConfigureAwait(false);
|
2018-07-19 12:42:48 +00:00
|
|
|
|
|
2019-03-20 13:10:13 +00:00
|
|
|
|
await CheckGameFansAsync(client, channel, message).ConfigureAwait(false);
|
2019-03-20 09:05:37 +00:00
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
Config.Log.Error(e);
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-07-19 12:42:48 +00:00
|
|
|
|
|
2019-03-20 09:05:37 +00:00
|
|
|
|
private static async Task CheckMediaTalkAsync(DiscordClient client, DiscordChannel channel, DiscordMessage message, DiscordEmoji emoji)
|
|
|
|
|
{
|
|
|
|
|
if (!Config.Moderation.Channels.Contains(channel.Id))
|
|
|
|
|
return;
|
2018-07-19 12:42:48 +00:00
|
|
|
|
|
2019-03-20 09:05:37 +00:00
|
|
|
|
// message.Timestamp throws if it's not in the cache AND is in local time zone
|
|
|
|
|
if (DateTime.UtcNow - message.CreationTimestamp > Config.ModerationTimeThreshold)
|
|
|
|
|
return;
|
2018-07-19 12:42:48 +00:00
|
|
|
|
|
2019-03-20 09:05:37 +00:00
|
|
|
|
if (message.Reactions.Any(r => r.Emoji == emoji && (r.IsMe || r.Count < Config.Moderation.StarbucksThreshold)))
|
|
|
|
|
return;
|
2018-07-19 12:42:48 +00:00
|
|
|
|
|
2019-03-20 09:05:37 +00:00
|
|
|
|
if (message.Author.IsWhitelisted(client, channel.Guild))
|
|
|
|
|
return;
|
2018-07-19 12:42:48 +00:00
|
|
|
|
|
2019-03-20 09:05:37 +00:00
|
|
|
|
var users = await message.GetReactionsAsync(emoji).ConfigureAwait(false);
|
2020-01-26 20:14:33 +00:00
|
|
|
|
if (users.Any(u => u.IsCurrent))
|
|
|
|
|
return;
|
|
|
|
|
|
2019-03-20 09:05:37 +00:00
|
|
|
|
var members = users
|
2020-01-26 20:27:37 +00:00
|
|
|
|
.Distinct()
|
2019-03-20 09:05:37 +00:00
|
|
|
|
.Select(u => channel.Guild
|
|
|
|
|
.GetMemberAsync(u.Id)
|
|
|
|
|
.ContinueWith(ct => ct.IsCompletedSuccessfully ? ct : Task.FromResult((DiscordMember)null), TaskScheduler.Default))
|
|
|
|
|
.ToList() //force eager task creation
|
|
|
|
|
.Select(t => t.Unwrap().ConfigureAwait(false).GetAwaiter().GetResult())
|
|
|
|
|
.Where(m => m != null)
|
|
|
|
|
.ToList();
|
2020-01-26 20:14:33 +00:00
|
|
|
|
var reporters = members.Where(m => m.Roles.Any()).ToList();
|
2019-03-20 09:05:37 +00:00
|
|
|
|
if (reporters.Count < Config.Moderation.StarbucksThreshold)
|
|
|
|
|
return;
|
|
|
|
|
|
2019-08-19 11:53:30 +00:00
|
|
|
|
await message.ReactWithAsync(emoji).ConfigureAwait(false);
|
2019-03-20 09:05:37 +00:00
|
|
|
|
await client.ReportAsync(Config.Reactions.Starbucks + " Media talk report", message, reporters, null, ReportSeverity.Medium).ConfigureAwait(false);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-10 18:31:56 +00:00
|
|
|
|
|
|
|
|
|
private static Task ShutupAsync(DiscordClient client, DiscordUser user, DiscordMessage message)
|
|
|
|
|
{
|
|
|
|
|
if (!message.Author.IsCurrent)
|
|
|
|
|
return Task.CompletedTask;
|
|
|
|
|
|
|
|
|
|
if (message.CreationTimestamp.Add(Config.ShutupTimeLimit) < DateTime.UtcNow)
|
|
|
|
|
return Task.CompletedTask;
|
|
|
|
|
|
|
|
|
|
if (!user.IsWhitelisted(client, message.Channel.Guild))
|
|
|
|
|
return Task.CompletedTask;
|
|
|
|
|
|
|
|
|
|
return message.DeleteAsync();
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-22 14:47:28 +00:00
|
|
|
|
private static async Task BadUpdateAsync(DiscordClient client, DiscordUser user, DiscordMessage message, DiscordEmoji emoji)
|
|
|
|
|
{
|
|
|
|
|
if (message?.Channel.Id != Config.BotChannelId)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (!user.IsSmartlisted(client, message.Channel.Guild))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
await Moderation.ToggleBadUpdateAnnouncementAsync(message).ConfigureAwait(false);
|
2019-08-22 14:55:58 +00:00
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
await message.DeleteReactionAsync(emoji, user).ConfigureAwait(false);
|
|
|
|
|
}
|
|
|
|
|
catch { }
|
2019-08-22 14:47:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-05-10 18:31:56 +00:00
|
|
|
|
|
2019-08-16 15:32:16 +00:00
|
|
|
|
private static Task CheckGameFansAsync(DiscordClient client, DiscordChannel channel, DiscordMessage message)
|
2019-03-20 09:05:37 +00:00
|
|
|
|
{
|
2019-03-20 13:10:13 +00:00
|
|
|
|
var bot = client.GetMember(channel.Guild, client.CurrentUser);
|
2019-08-19 11:45:34 +00:00
|
|
|
|
var ch = channel.IsPrivate ? channel.Users.FirstOrDefault(u => u.Id != client.CurrentUser.Id)?.Username + "'s DM" : "#" + channel.Name;
|
2019-03-20 13:10:13 +00:00
|
|
|
|
if (!channel.PermissionsFor(bot).HasPermission(Permissions.AddReactions))
|
|
|
|
|
{
|
2019-08-19 11:45:34 +00:00
|
|
|
|
Config.Log.Debug($"No permissions to react in {ch}");
|
2019-08-16 15:32:16 +00:00
|
|
|
|
return Task.CompletedTask;
|
2019-03-20 13:10:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-03-20 09:05:37 +00:00
|
|
|
|
var mood = client.GetEmoji(":sqvat:", "😒");
|
2019-03-20 13:10:13 +00:00
|
|
|
|
if (message.Reactions.Any(r => r.Emoji == mood && r.IsMe))
|
2019-08-16 15:32:16 +00:00
|
|
|
|
return Task.CompletedTask;
|
2019-03-20 09:05:37 +00:00
|
|
|
|
|
2019-03-20 13:10:13 +00:00
|
|
|
|
var reactionMsg = string.Concat(message.Reactions.Select(r => TextMap.TryGetValue(r.Emoji, out var txt) ? txt : " ")).Trim();
|
|
|
|
|
if (string.IsNullOrEmpty(reactionMsg))
|
2019-08-16 15:32:16 +00:00
|
|
|
|
return Task.CompletedTask;
|
2019-03-20 13:10:13 +00:00
|
|
|
|
|
2019-08-19 11:45:34 +00:00
|
|
|
|
Config.Log.Debug($"Emoji text: {reactionMsg} (in {ch})");
|
2019-08-16 15:32:16 +00:00
|
|
|
|
return Task.CompletedTask;
|
2018-07-19 12:42:48 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|