commit
9cd81f4e39
@ -59,8 +59,8 @@ Command and aliases | Description | Usage
|
||||
`.fwtoall` | Toggles whether messages will be forwarded to all bot owners or only to the first one specified in the credentials.json **Bot Owner only.** | `.fwtoall`
|
||||
`.logserver` | Enables or Disables ALL log events. If enabled, all log events will log to this channel. **Requires Administrator server permission.** **Bot Owner only.** | `.logserver enable` or `.logserver disable`
|
||||
`.logignore` | Toggles whether the .logserver command ignores this channel. Useful if you have hidden admin channel and public log channel. **Requires Administrator server permission.** **Bot Owner only.** | `.logignore`
|
||||
`.logevents` | Shows a list of all events you can subscribe to with `.log` **Requires Administrator server permission.** | `.logevents`
|
||||
`.log` | Toggles logging event. Disables it if it's active anywhere on the server. Enables if it's not active. Use `.logevents` to see a lit of all events you can subscribe to. **Requires Administrator server permission.** | `.log userpresence` or `.log userbanned`
|
||||
`.logevents` | Shows a list of all events you can subscribe to with `.log` **Requires Administrator server permission.** **Bot Owner only.** | `.logevents`
|
||||
`.log` | Toggles logging event. Disables it if it's active anywhere on the server. Enables if it's not active. Use `.logevents` to see a lit of all events you can subscribe to. **Requires Administrator server permission.** **Bot Owner only.** | `.log userpresence` or `.log userbanned`
|
||||
`.repeatinvoke` `.repinv` | Immediately shows the repeat message and restarts the timer. **Requires ManageMessages server permission.** | `.repinv`
|
||||
`.repeat` | Repeat a message every X minutes. If no parameters are specified, repeat is disabled. **Requires ManageMessages server permission.** | `.repeat 5 Hello there`
|
||||
`.migratedata` | Migrate data from old bot configuration **Bot Owner only.** | `.migratedata`
|
||||
@ -137,7 +137,7 @@ Command and aliases | Description | Usage
|
||||
`$leaderboard` `$lb` | Displays bot currency leaderboard. | `$lb`
|
||||
`$race` | Starts a new animal race. | `$race`
|
||||
`$joinrace` `$jr` | Joins a new race. You can specify an amount of currency for betting (optional). You will get YourBet*(participants-1) back if you win. | `$jr` or `$jr 5`
|
||||
`$roll` | Rolls 0-100. If you supply a number [x] it rolls up to 30 normal dice. If you split 2 numbers with letter d (xdy) it will roll x dice from 1 to y. | `$roll` or `$roll 7` or `$roll 3d5`
|
||||
`$roll` | Rolls 0-100. If you supply a number [x] it rolls up to 30 normal dice. If you split 2 numbers with letter d (xdy) it will roll x dice from 1 to y. Y can be a letter 'F' if you want to roll fate dice instead of dnd. | `$roll` or `$roll 7` or `$roll 3d5` or `$roll 5dF`
|
||||
`$rolluo` | Rolls X normal dice (up to 30) unordered. If you split 2 numbers with letter d (xdy) it will roll x dice from 1 to y. | `$rolluo` or `$rolluo 7` or `$rolluo 3d5`
|
||||
`$nroll` | Rolls in a given range. | `$nroll 5` (rolls 0-5) or `$nroll 5-15`
|
||||
`$draw` | Draws a card from the deck.If you supply number X, she draws up to 5 cards from the deck. | `$draw` or `$draw 5`
|
||||
@ -195,6 +195,7 @@ Command and aliases | Description | Usage
|
||||
`!!stop` `!!s` | Stops the music and clears the playlist. Stays in the channel. | `!!s`
|
||||
`!!destroy` `!!d` | Completely stops the music and unbinds the bot from the channel. (may cause weird behaviour) | `!!d`
|
||||
`!!pause` `!!p` | Pauses or Unpauses the song. | `!!p`
|
||||
`!!fairplay` `!!fp` | Toggles fairplay. While enabled, music player will prioritize songs from users who didn't have their song recently played instead of the song's position in the queue. | `!!fp`
|
||||
`!!queue` `!!q` `!!yq` | Queue a song using keywords or a link. Bot will join your voice channel.**You must be in a voice channel**. | `!!q Dream Of Venice`
|
||||
`!!soundcloudqueue` `!!sq` | Queue a soundcloud song using keywords. Bot will join your voice channel.**You must be in a voice channel**. | `!!sq Dream Of Venice`
|
||||
`!!listqueue` `!!lq` | Lists 15 currently queued songs per page. Default page is 1. | `!!lq` or `!!lq 2`
|
||||
@ -211,6 +212,7 @@ Command and aliases | Description | Usage
|
||||
`!!remove` `!!rm` | Remove a song by its # in the queue, or 'all' to remove whole queue. | `!!rm 5`
|
||||
`!!movesong` `!!ms` | Moves a song from one position to another. | `!!ms 5>3`
|
||||
`!!setmaxqueue` `!!smq` | Sets a maximum queue size. Supply 0 or no argument to have no limit. | `!!smq 50` or `!!smq`
|
||||
`!!setmaxplaytime` `!!smp` | Sets a maximum number of seconds (>14) a song can run before being skipped automatically. Set 0 to have no limit. | `!!smp 0` or `!!smp 270`
|
||||
`!!reptcursong` `!!rcs` | Toggles repeat of current song. | `!!rcs`
|
||||
`!!rpeatplaylst` `!!rpl` | Toggles repeat of all songs in the queue (every song that finishes is added to the end of the queue). | `!!rpl`
|
||||
`!!save` | Saves a playlist under a certain name. Name must be no longer than 20 characters and mustn't contain dashes. | `!!save classical1`
|
||||
@ -218,7 +220,6 @@ Command and aliases | Description | Usage
|
||||
`!!playlists` `!!pls` | Lists all playlists. Paginated. 20 per page. Default page is 0. | `!!pls 1`
|
||||
`!!deleteplaylist` `!!delpls` | Deletes a saved playlist. Only if you made it or if you are the bot owner. | `!!delpls animu-5`
|
||||
`!!goto` | Goes to a specific time in seconds in a song. | `!!goto 30`
|
||||
`!!getlink` `!!gl` | Shows a link to the song in the queue by index, or the currently playing song by default. | `!!gl`
|
||||
`!!autoplay` `!!ap` | Toggles autoplay - When the song is finished, automatically queue a related youtube song. (Works only for youtube songs and when queue is empty) | `!!ap`
|
||||
|
||||
###### [Back to TOC](#table-of-contents)
|
||||
@ -228,8 +229,8 @@ Command and aliases | Description | Usage
|
||||
----------------|--------------|-------
|
||||
`~hentai` | Shows a hentai image from a random website (gelbooru or danbooru or konachan or atfbooru or yandere) with a given tag. Tag is optional but preferred. Only 1 tag allowed. | `~hentai yuri`
|
||||
`~hentaibomb` | Shows a total 5 images (from gelbooru, danbooru, konachan, yandere and atfbooru). Tag is optional but preferred. | `~hentaibomb yuri`
|
||||
`~yandere` | Shows a random image from yandere with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `~yandere tag1+tag2`
|
||||
`~danbooru` | Shows a random hentai image from danbooru with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `~danbooru yuri+kissing`
|
||||
`~yandere` | Shows a random image from yandere with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `~yandere tag1+tag2`
|
||||
`~konachan` | Shows a random hentai image from konachan with a given tag. Tag is optional but preferred. | `~konachan yuri`
|
||||
`~gelbooru` | Shows a random hentai image from gelbooru with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `~gelbooru yuri+kissing`
|
||||
`~rule34` | Shows a random image from rule34.xx with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `~rule34 yuri+kissing`
|
||||
@ -302,6 +303,7 @@ Command and aliases | Description | Usage
|
||||
`~hearthstone` `~hs` | Searches for a Hearthstone card and shows its image. Takes a while to complete. | `~hs Ysera`
|
||||
`~yodify` `~yoda` | Translates your normal sentences into Yoda styled sentences! | ~yodify I was once an adventurer like you` or `~yoda my feelings hurt`
|
||||
`~urbandict` `~ud` | Searches Urban Dictionary for a word. | `~ud Pineapple`
|
||||
`~define` `~def` | Finds a definition of a word. | `~def heresy`
|
||||
`~#` | Searches Tagdef.com for a hashtag. | `~# ff`
|
||||
`~catfact` | Shows a random catfact from <http://catfacts-api.appspot.com/api/facts> | `~catfact`
|
||||
`~revav` | Returns a google reverse image search for someone's avatar. | `~revav "@SomeGuy"`
|
||||
@ -349,6 +351,7 @@ Command and aliases | Description | Usage
|
||||
### Utility
|
||||
Command and aliases | Description | Usage
|
||||
----------------|--------------|-------
|
||||
`.togethertube` `.totube` | Creates a new room on <https://togethertube.com> and shows the link in the chat. | `.totube`
|
||||
`.whosplaying` `.whpl` | Shows a list of users who are playing the specified game. | `.whpl Overwatch`
|
||||
`.inrole` | Lists every person from the provided role or roles (separated by a ',') on this server. If the list is too long for 1 message, you must have Manage Messages permission. | `.inrole Role`
|
||||
`.checkmyperms` | Checks your user-specific permissions on this channel. | `.checkmyperms`
|
||||
|
@ -38,7 +38,7 @@ namespace NadekoBot.Modules.Administration
|
||||
_log = LogManager.GetCurrentClassLogger();
|
||||
NadekoBot.CommandHandler.CommandExecuted += DelMsgOnCmd_Handler;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
private static async Task DelMsgOnCmd_Handler(IUserMessage msg, Command cmd)
|
||||
@ -82,7 +82,7 @@ namespace NadekoBot.Modules.Administration
|
||||
PermRole = config.PermissionRole,
|
||||
Verbose = config.VerbosePermissions,
|
||||
};
|
||||
Permissions.Permissions.Cache.AddOrUpdate(channel.Guild.Id,
|
||||
Permissions.Permissions.Cache.AddOrUpdate(channel.Guild.Id,
|
||||
toAdd, (id, old) => toAdd);
|
||||
await uow.CompleteAsync();
|
||||
}
|
||||
@ -219,7 +219,7 @@ namespace NadekoBot.Modules.Administration
|
||||
return;
|
||||
}
|
||||
var roleName = args[0].ToUpperInvariant();
|
||||
var role = channel.Guild.Roles.Where(r=>r.Name.ToUpperInvariant() == roleName).FirstOrDefault();
|
||||
var role = channel.Guild.Roles.Where(r => r.Name.ToUpperInvariant() == roleName).FirstOrDefault();
|
||||
|
||||
if (role == null)
|
||||
{
|
||||
@ -234,7 +234,7 @@ namespace NadekoBot.Modules.Administration
|
||||
var red = Convert.ToByte(rgb ? int.Parse(arg1) : Convert.ToInt32(arg1.Substring(0, 2), 16));
|
||||
var green = Convert.ToByte(rgb ? int.Parse(args[2]) : Convert.ToInt32(arg1.Substring(2, 2), 16));
|
||||
var blue = Convert.ToByte(rgb ? int.Parse(args[3]) : Convert.ToInt32(arg1.Substring(4, 2), 16));
|
||||
|
||||
|
||||
await role.ModifyAsync(r => r.Color = new Discord.Color(red, green, blue).RawValue).ConfigureAwait(false);
|
||||
await channel.SendConfirmAsync($"☑️ Role **{role.Name}'s** color has been changed.").ConfigureAwait(false);
|
||||
}
|
||||
@ -254,7 +254,7 @@ namespace NadekoBot.Modules.Administration
|
||||
{
|
||||
msg = "❗️No reason provided.";
|
||||
}
|
||||
if (umsg.Author.Id != user.Guild.OwnerId && user.Roles.Select(r=>r.Position).Max() >= ((IGuildUser)umsg.Author).Roles.Select(r => r.Position).Max())
|
||||
if (umsg.Author.Id != user.Guild.OwnerId && user.Roles.Select(r => r.Position).Max() >= ((IGuildUser)umsg.Author).Roles.Select(r => r.Position).Max())
|
||||
{
|
||||
await channel.SendErrorAsync("⚠️ You can't use this command on users with a role higher or equal to yours in the role hierarchy.");
|
||||
return;
|
||||
@ -367,7 +367,7 @@ namespace NadekoBot.Modules.Administration
|
||||
{
|
||||
foreach (var u in users)
|
||||
{
|
||||
await u.ModifyAsync(usr=>usr.Deaf = true).ConfigureAwait(false);
|
||||
await u.ModifyAsync(usr => usr.Deaf = true).ConfigureAwait(false);
|
||||
}
|
||||
await channel.SendConfirmAsync("🔇 **Deafen** successful.").ConfigureAwait(false);
|
||||
}
|
||||
@ -390,7 +390,7 @@ namespace NadekoBot.Modules.Administration
|
||||
{
|
||||
foreach (var u in users)
|
||||
{
|
||||
await u.ModifyAsync(usr=> usr.Deaf = false).ConfigureAwait(false);
|
||||
await u.ModifyAsync(usr => usr.Deaf = false).ConfigureAwait(false);
|
||||
}
|
||||
await channel.SendConfirmAsync("🔊 **Undeafen** successful.").ConfigureAwait(false);
|
||||
}
|
||||
@ -467,9 +467,9 @@ namespace NadekoBot.Modules.Administration
|
||||
public async Task Prune(IUserMessage umsg)
|
||||
{
|
||||
var channel = (ITextChannel)umsg.Channel;
|
||||
|
||||
|
||||
var user = channel.Guild.GetCurrentUser();
|
||||
|
||||
|
||||
var enumerable = (await umsg.Channel.GetMessagesAsync()).AsEnumerable();
|
||||
enumerable = enumerable.Where(x => x.Author.Id == user.Id);
|
||||
await umsg.Channel.DeleteMessagesAsync(enumerable).ConfigureAwait(false);
|
||||
@ -650,8 +650,10 @@ namespace NadekoBot.Modules.Administration
|
||||
cnt -= 100;
|
||||
}
|
||||
var title = $"Chatlog-{channel.Guild.Name}/#{channel.Name}-{DateTime.Now}.txt";
|
||||
var grouping = msgs.GroupBy(x => $"{x.CreatedAt.Date:dd.MM.yyyy}")
|
||||
.Select(g => new { date = g.Key, messages = g.OrderBy(x=>x.CreatedAt).Select(s => $"【{s.Timestamp:HH:mm:ss}】{s.Author}:" + s.ToString()) });
|
||||
await (umsg.Author as IGuildUser).SendFileAsync(
|
||||
await JsonConvert.SerializeObject(new { Messages = msgs.Select(s => $"【{s.Timestamp:HH:mm:ss}】{s.Author}:" + s.ToString()) }, Formatting.Indented).ToStream().ConfigureAwait(false),
|
||||
await JsonConvert.SerializeObject(grouping, Formatting.Indented).ToStream().ConfigureAwait(false),
|
||||
title, title).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@ -665,9 +667,9 @@ namespace NadekoBot.Modules.Administration
|
||||
|
||||
string send = $"❕{umsg.Author.Mention} has invoked a mention on the following roles ❕";
|
||||
foreach (var role in roles)
|
||||
{
|
||||
{
|
||||
send += $"\n**{role.Name}**\n";
|
||||
send += string.Join(", ", (await channel.Guild.GetUsersAsync()).Where(u => u.Roles.Contains(role)).Distinct().Select(u=>u.Mention));
|
||||
send += string.Join(", ", (await channel.Guild.GetUsersAsync()).Where(u => u.Roles.Contains(role)).Distinct().Select(u => u.Mention));
|
||||
}
|
||||
|
||||
while (send.Length > 2000)
|
||||
@ -692,7 +694,7 @@ namespace NadekoBot.Modules.Administration
|
||||
donatorsOrdered = uow.Donators.GetDonatorsOrdered();
|
||||
}
|
||||
await umsg.Channel.SendConfirmAsync("Thanks to the people listed below for making this project happen!", string.Join("⭐", donatorsOrdered.Select(d => d.Name))).ConfigureAwait(false);
|
||||
|
||||
|
||||
nadekoSupportServer = nadekoSupportServer ?? NadekoBot.Client.GetGuild(117523346618318850);
|
||||
|
||||
if (nadekoSupportServer == null)
|
||||
@ -721,4 +723,4 @@ namespace NadekoBot.Modules.Administration
|
||||
await umsg.Channel.SendConfirmAsync($"Successfuly added a new donator. Total donated amount from this user: {don.Amount} 👑").ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -81,52 +81,46 @@ namespace NadekoBot.Modules.Administration
|
||||
{
|
||||
_log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
NadekoBot.Client.MessageReceived += (imsg) =>
|
||||
NadekoBot.Client.MessageReceived += async (imsg) =>
|
||||
{
|
||||
var msg = imsg as IUserMessage;
|
||||
if (msg == null || msg.Author.IsBot)
|
||||
return Task.CompletedTask;
|
||||
|
||||
var channel = msg.Channel as ITextChannel;
|
||||
if (channel == null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
var t = Task.Run(async () =>
|
||||
try
|
||||
{
|
||||
try
|
||||
var msg = imsg as IUserMessage;
|
||||
if (msg == null || msg.Author.IsBot)
|
||||
return;
|
||||
|
||||
var channel = msg.Channel as ITextChannel;
|
||||
if (channel == null)
|
||||
return;
|
||||
AntiSpamSetting spamSettings;
|
||||
if (!antiSpamGuilds.TryGetValue(channel.Guild.Id, out spamSettings))
|
||||
return;
|
||||
|
||||
var stats = spamSettings.UserStats.AddOrUpdate(msg.Author.Id, new UserSpamStats(msg.Content),
|
||||
(id, old) => { old.ApplyNextMessage(msg.Content); return old; });
|
||||
|
||||
if (stats.Count >= spamSettings.MessageThreshold)
|
||||
{
|
||||
AntiSpamSetting spamSettings;
|
||||
if (!antiSpamGuilds.TryGetValue(channel.Guild.Id, out spamSettings))
|
||||
return;
|
||||
|
||||
var stats = spamSettings.UserStats.AddOrUpdate(msg.Author.Id, new UserSpamStats(msg.Content),
|
||||
(id, old) => { old.ApplyNextMessage(msg.Content); return old; });
|
||||
|
||||
if (stats.Count >= spamSettings.MessageThreshold)
|
||||
if (spamSettings.UserStats.TryRemove(msg.Author.Id, out stats))
|
||||
{
|
||||
if (spamSettings.UserStats.TryRemove(msg.Author.Id, out stats))
|
||||
{
|
||||
await PunishUsers(spamSettings.Action, ProtectionType.Spamming, (IGuildUser)msg.Author)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
await PunishUsers(spamSettings.Action, ProtectionType.Spamming, (IGuildUser)msg.Author)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
catch { }
|
||||
};
|
||||
|
||||
NadekoBot.Client.UserJoined += (usr) =>
|
||||
NadekoBot.Client.UserJoined += async (usr) =>
|
||||
{
|
||||
if (usr.IsBot)
|
||||
return Task.CompletedTask;
|
||||
|
||||
AntiRaidSetting settings;
|
||||
if (!antiRaidGuilds.TryGetValue(usr.Guild.Id, out settings))
|
||||
return Task.CompletedTask;
|
||||
|
||||
var t = Task.Run(async () =>
|
||||
try
|
||||
{
|
||||
if (usr.IsBot)
|
||||
return;
|
||||
AntiRaidSetting settings;
|
||||
if (!antiRaidGuilds.TryGetValue(usr.Guild.Id, out settings))
|
||||
return;
|
||||
if (!settings.RaidUsers.Add(usr))
|
||||
return;
|
||||
|
||||
@ -143,9 +137,9 @@ namespace NadekoBot.Modules.Administration
|
||||
|
||||
settings.RaidUsers.TryRemove(usr);
|
||||
--settings.UsersCount;
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
catch { }
|
||||
};
|
||||
}
|
||||
|
||||
@ -241,7 +235,7 @@ namespace NadekoBot.Modules.Administration
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[RequirePermission(GuildPermission.Administrator)]
|
||||
public async Task AntiSpam(IUserMessage imsg, int messageCount=3, PunishmentAction action = PunishmentAction.Mute)
|
||||
public async Task AntiSpam(IUserMessage imsg, int messageCount = 3, PunishmentAction action = PunishmentAction.Mute)
|
||||
{
|
||||
var channel = (ITextChannel)imsg.Channel;
|
||||
|
||||
@ -273,10 +267,10 @@ namespace NadekoBot.Modules.Administration
|
||||
Action = action,
|
||||
MessageThreshold = messageCount,
|
||||
}))
|
||||
await channel.SendConfirmAsync("✅ **Anti-Spam feature** has been **enabled** on this server.").ConfigureAwait(false);
|
||||
await channel.SendConfirmAsync("✅ **Anti-Spam feature** has been **enabled** on this server.").ConfigureAwait(false);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -26,26 +26,22 @@ namespace NadekoBot.Modules.Administration
|
||||
AutoAssignedRoles = new ConcurrentDictionary<ulong, ulong>(NadekoBot.AllGuildConfigs.Where(x => x.AutoAssignRoleId != 0)
|
||||
.ToDictionary(k => k.GuildId, v => v.AutoAssignRoleId));
|
||||
_log = LogManager.GetCurrentClassLogger();
|
||||
NadekoBot.Client.UserJoined += (user) =>
|
||||
NadekoBot.Client.UserJoined += async (user) =>
|
||||
{
|
||||
var t = Task.Run(async () =>
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
ulong roleId = 0;
|
||||
AutoAssignedRoles.TryGetValue(user.Guild.Id, out roleId);
|
||||
ulong roleId = 0;
|
||||
AutoAssignedRoles.TryGetValue(user.Guild.Id, out roleId);
|
||||
|
||||
if (roleId == 0)
|
||||
return;
|
||||
if (roleId == 0)
|
||||
return;
|
||||
|
||||
var role = user.Guild.Roles.FirstOrDefault(r => r.Id == roleId);
|
||||
var role = user.Guild.Roles.FirstOrDefault(r => r.Id == roleId);
|
||||
|
||||
if (role != null)
|
||||
await user.AddRolesAsync(role).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex) { _log.Warn(ex); }
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
if (role != null)
|
||||
await user.AddRolesAsync(role).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex) { _log.Warn(ex); }
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -19,21 +19,18 @@ namespace NadekoBot.Modules.Administration
|
||||
static CrossServerTextChannel()
|
||||
{
|
||||
_log = LogManager.GetCurrentClassLogger();
|
||||
NadekoBot.Client.MessageReceived += (imsg) =>
|
||||
NadekoBot.Client.MessageReceived += async (imsg) =>
|
||||
{
|
||||
if (imsg.Author.IsBot)
|
||||
return Task.CompletedTask;
|
||||
|
||||
var msg = imsg as IUserMessage;
|
||||
if (msg == null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
var channel = imsg.Channel as ITextChannel;
|
||||
if (channel == null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
Task.Run(async () =>
|
||||
try
|
||||
{
|
||||
if (imsg.Author.IsBot)
|
||||
return;
|
||||
var msg = imsg as IUserMessage;
|
||||
if (msg == null)
|
||||
return;
|
||||
var channel = imsg.Channel as ITextChannel;
|
||||
if (channel == null)
|
||||
return;
|
||||
if (msg.Author.Id == NadekoBot.Client.GetCurrentUser().Id) return;
|
||||
foreach (var subscriber in Subscribers)
|
||||
{
|
||||
@ -45,8 +42,10 @@ namespace NadekoBot.Modules.Administration
|
||||
try { await chan.SendMessageAsync(GetText(channel.Guild, channel, (IGuildUser)msg.Author, msg)).ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
||||
}
|
||||
}
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
_log.Warn(ex);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -75,6 +75,7 @@ namespace NadekoBot.Modules.Administration
|
||||
_client.UserLeft += _client_UserLeft;
|
||||
_client.UserPresenceUpdated += _client_UserPresenceUpdated;
|
||||
_client.UserVoiceStateUpdated += _client_UserVoiceStateUpdated;
|
||||
_client.UserVoiceStateUpdated += _client_UserVoiceStateUpdated_TTS;
|
||||
_client.UserUpdated += _client_UserUpdated;
|
||||
|
||||
_client.ChannelCreated += _client_ChannelCreated;
|
||||
@ -85,51 +86,60 @@ namespace NadekoBot.Modules.Administration
|
||||
MuteCommands.UserUnmuted += MuteCommands_UserUnmuted;
|
||||
}
|
||||
|
||||
private Task MuteCommands_UserMuted(IGuildUser usr, MuteCommands.MuteType muteType)
|
||||
private async void _client_UserVoiceStateUpdated_TTS(IUser iusr, IVoiceState before, IVoiceState after)
|
||||
{
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out logSetting)
|
||||
|| (logSetting.UserMutedId == null))
|
||||
return Task.CompletedTask;
|
||||
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(usr.Guild, logSetting, LogType.UserMuted)) == null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
var task = Task.Run(async () =>
|
||||
try
|
||||
{
|
||||
string mutes = "";
|
||||
switch (muteType)
|
||||
{
|
||||
case MuteCommands.MuteType.Voice:
|
||||
mutes = "voice chat";
|
||||
break;
|
||||
case MuteCommands.MuteType.Chat:
|
||||
mutes = "text chat";
|
||||
break;
|
||||
case MuteCommands.MuteType.All:
|
||||
mutes = "text and voice chat";
|
||||
break;
|
||||
}
|
||||
try { await logChannel.SendMessageAsync($"‼️🕕`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__🔇 **| User muted from the {mutes}. |** 🆔 `{usr.Id}`").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
||||
});
|
||||
var usr = iusr as IGuildUser;
|
||||
if (usr == null)
|
||||
return;
|
||||
|
||||
return Task.CompletedTask;
|
||||
var beforeVch = before.VoiceChannel;
|
||||
var afterVch = after.VoiceChannel;
|
||||
|
||||
if (beforeVch == afterVch)
|
||||
return;
|
||||
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out logSetting)
|
||||
|| (logSetting.LogVoicePresenceTTSId == null))
|
||||
return;
|
||||
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(usr.Guild, logSetting, LogType.VoicePresenceTTS)) == null)
|
||||
return;
|
||||
|
||||
string str = null;
|
||||
if (beforeVch?.Guild == afterVch?.Guild)
|
||||
{
|
||||
str = $"{usr.Username} moved from {beforeVch.Name} to {afterVch.Name}";
|
||||
}
|
||||
else if (beforeVch == null)
|
||||
{
|
||||
str = $"{usr.Username} has joined {afterVch.Name}";
|
||||
}
|
||||
else if (afterVch == null)
|
||||
{
|
||||
str = $"{usr.Username} has left {beforeVch.Name}";
|
||||
}
|
||||
var toDelete = await logChannel.SendMessageAsync(str, true).ConfigureAwait(false);
|
||||
toDelete.DeleteAfter(5);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private Task MuteCommands_UserUnmuted(IGuildUser usr, MuteCommands.MuteType muteType)
|
||||
private async void MuteCommands_UserMuted(IGuildUser usr, MuteCommands.MuteType muteType)
|
||||
{
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out logSetting)
|
||||
|| (logSetting.UserMutedId == null))
|
||||
return Task.CompletedTask;
|
||||
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(usr.Guild, logSetting, LogType.UserMuted)) == null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
var task = Task.Run(async () =>
|
||||
try
|
||||
{
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out logSetting)
|
||||
|| (logSetting.UserMutedId == null))
|
||||
return;
|
||||
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(usr.Guild, logSetting, LogType.UserMuted)) == null)
|
||||
return;
|
||||
string mutes = "";
|
||||
switch (muteType)
|
||||
{
|
||||
@ -143,392 +153,404 @@ namespace NadekoBot.Modules.Administration
|
||||
mutes = "text and voice chat";
|
||||
break;
|
||||
}
|
||||
try { await logChannel.SendMessageAsync($"‼️🕕`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__🔊 **| User unmuted from the {mutes}. |** 🆔 `{usr.Id}`").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
||||
});
|
||||
await logChannel.SendMessageAsync($"‼️🕕`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__🔇 **| User muted from the {mutes}. |** 🆔 `{usr.Id}`").ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex) { _log.Warn(ex); }
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
private async void MuteCommands_UserUnmuted(IGuildUser usr, MuteCommands.MuteType muteType)
|
||||
{
|
||||
try
|
||||
{
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out logSetting)
|
||||
|| (logSetting.UserMutedId == null))
|
||||
return;
|
||||
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(usr.Guild, logSetting, LogType.UserMuted)) == null)
|
||||
return;
|
||||
|
||||
string mutes = "";
|
||||
switch (muteType)
|
||||
{
|
||||
case MuteCommands.MuteType.Voice:
|
||||
mutes = "voice chat";
|
||||
break;
|
||||
case MuteCommands.MuteType.Chat:
|
||||
mutes = "text chat";
|
||||
break;
|
||||
case MuteCommands.MuteType.All:
|
||||
mutes = "text and voice chat";
|
||||
break;
|
||||
}
|
||||
await logChannel.SendMessageAsync($"‼️🕕`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__🔊 **| User unmuted from the {mutes}. |** 🆔 `{usr.Id}`").ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex) { _log.Warn(ex); }
|
||||
}
|
||||
|
||||
public static async Task TriggeredAntiProtection(IGuildUser[] users, PunishmentAction action, ProtectionType protection)
|
||||
{
|
||||
if (users.Length == 0)
|
||||
return;
|
||||
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(users.First().Guild.Id, out logSetting)
|
||||
|| (logSetting.LogOtherId == null))
|
||||
return;
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(users.First().Guild, logSetting, LogType.Other)) == null)
|
||||
return;
|
||||
|
||||
var punishment = "";
|
||||
if (action == PunishmentAction.Mute)
|
||||
try
|
||||
{
|
||||
punishment = "🔇 MUTED";
|
||||
//punishment = "MUTED";
|
||||
}
|
||||
else if (action == PunishmentAction.Kick)
|
||||
{
|
||||
punishment = "☣ SOFT-BANNED (KICKED)";
|
||||
//punishment = "KICKED";
|
||||
}
|
||||
else if (action == PunishmentAction.Ban)
|
||||
{
|
||||
punishment = "⛔️ BANNED";
|
||||
//punishment = "BANNED";
|
||||
}
|
||||
await logChannel.SendMessageAsync(String.Join("\n", users.Select(user => $"‼️ {Format.Bold(user.ToString())} got **{punishment}** due to __**{protection}**__ protection on **{user.Guild.Name}** server.")))
|
||||
//await logChannel.SendMessageAsync(String.Join("\n",users.Select(user=>$"{Format.Bold(user.ToString())} was **{punishment}** due to `{protection}` protection on **{user.Guild.Name}** server.")))
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
if (users.Length == 0)
|
||||
return;
|
||||
|
||||
private Task _client_UserUpdated(IGuildUser before, IGuildUser after)
|
||||
{
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(before.Guild.Id, out logSetting)
|
||||
|| (logSetting.UserUpdatedId == null))
|
||||
return Task.CompletedTask;
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(users.First().Guild.Id, out logSetting)
|
||||
|| (logSetting.LogOtherId == null))
|
||||
return;
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(users.First().Guild, logSetting, LogType.Other)) == null)
|
||||
return;
|
||||
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(before.Guild, logSetting, LogType.UserUpdated)) == null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
var task = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
var punishment = "";
|
||||
if (action == PunishmentAction.Mute)
|
||||
{
|
||||
string str = $"🕔`{prettyCurrentTime}`";
|
||||
if (before.Username != after.Username)
|
||||
//str += $"**Name Changed**`{before.Username}#{before.Discriminator}`\n\t\t`New:`{after.ToString()}`";
|
||||
str += $"👤__**{before.Username}#{before.Discriminator}**__ **| Name Changed |** 🆔 `{before.Id}`\n\t\t`New:` **{after.ToString()}**";
|
||||
else if (before.Nickname != after.Nickname)
|
||||
str += $"👤__**{before.Username}#{before.Discriminator}**__ **| Nickname Changed |** 🆔 `{before.Id}`\n\t\t`Old:` **{before.Nickname}#{before.Discriminator}**\n\t\t`New:` **{after.Nickname}#{after.Discriminator}**";
|
||||
//str += $"**Nickname Changed**`{before.Username}#{before.Discriminator}`\n\t\t`Old:` {before.Nickname}#{before.Discriminator}\n\t\t`New:` {after.Nickname}#{after.Discriminator}";
|
||||
else if (before.AvatarUrl != after.AvatarUrl)
|
||||
//str += $"**Avatar Changed**👤`{before.Username}#{before.Discriminator}`\n\t {await _google.ShortenUrl(before.AvatarUrl)} `=>` {await _google.ShortenUrl(after.AvatarUrl)}";
|
||||
str += $"👤__**{before.Username}#{before.Discriminator}**__ **| Avatar Changed |** 🆔 `{before.Id}`\n\t🖼 {await _google.ShortenUrl(before.AvatarUrl)} `=>` {await _google.ShortenUrl(after.AvatarUrl)}";
|
||||
else if (!before.Roles.SequenceEqual(after.Roles))
|
||||
{
|
||||
if (before.Roles.Count() < after.Roles.Count())
|
||||
{
|
||||
var diffRoles = after.Roles.Where(r => !before.Roles.Contains(r)).Select(r => "**" + r.Name + "**");
|
||||
//str += $"**User's Roles changed ⚔➕**👤`{before.ToString()}`\n\tNow has {string.Join(", ", diffRoles)} role.";
|
||||
str += $"👤__**{before.ToString()}**__ **| User's Role Added |** 🆔 `{before.Id}`\n\t✅ {string.Join(", ", diffRoles).SanitizeMentions()}\n\t\t⚔ **`{string.Join(", ", after.Roles.Select(r => r.Name)).SanitizeMentions()}`** ⚔";
|
||||
}
|
||||
else if (before.Roles.Count() > after.Roles.Count())
|
||||
{
|
||||
var diffRoles = before.Roles.Where(r => !after.Roles.Contains(r)).Select(r => "**" + r.Name + "**");
|
||||
//str += $"**User's Roles changed **`{before.ToString()}`\n\tNo longer has {string.Join(", ", diffRoles)} role.";
|
||||
str += $"👤__**{before.ToString()}**__ **| User's Role Removed |** 🆔 `{before.Id}`\n\t🚮 {string.Join(", ", diffRoles).SanitizeMentions()}\n\t\t⚔ **`{string.Join(", ", after.Roles.Select(r => r.Name)).SanitizeMentions()}`** ⚔";
|
||||
}
|
||||
}
|
||||
else
|
||||
return;
|
||||
try { await logChannel.SendMessageAsync(str).ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
||||
punishment = "🔇 MUTED";
|
||||
//punishment = "MUTED";
|
||||
}
|
||||
catch { }
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
else if (action == PunishmentAction.Kick)
|
||||
{
|
||||
punishment = "☣ SOFT-BANNED (KICKED)";
|
||||
//punishment = "KICKED";
|
||||
}
|
||||
else if (action == PunishmentAction.Ban)
|
||||
{
|
||||
punishment = "⛔️ BANNED";
|
||||
//punishment = "BANNED";
|
||||
}
|
||||
await logChannel.SendMessageAsync(String.Join("\n", users.Select(user => $"‼️ {Format.Bold(user.ToString())} got **{punishment}** due to __**{protection}**__ protection on **{user.Guild.Name}** server.")))
|
||||
//await logChannel.SendMessageAsync(String.Join("\n",users.Select(user=>$"{Format.Bold(user.ToString())} was **{punishment}** due to `{protection}` protection on **{user.Guild.Name}** server.")))
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex) { _log.Warn(ex); }
|
||||
}
|
||||
|
||||
private Task _client_ChannelUpdated(IChannel cbefore, IChannel cafter)
|
||||
private async void _client_UserUpdated(IGuildUser before, IGuildUser after)
|
||||
{
|
||||
var before = cbefore as IGuildChannel;
|
||||
if (before == null)
|
||||
return Task.CompletedTask;
|
||||
var after = (IGuildChannel)cafter;
|
||||
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(before.Guild.Id, out logSetting)
|
||||
|| (logSetting.ChannelUpdatedId == null)
|
||||
|| logSetting.IgnoredChannels.Any(ilc => ilc.ChannelId == after.Id))
|
||||
return Task.CompletedTask;
|
||||
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(before.Guild, logSetting, LogType.ChannelUpdated)) == null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
var task = Task.Run(async () =>
|
||||
try
|
||||
{
|
||||
try
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(before.Guild.Id, out logSetting)
|
||||
|| (logSetting.UserUpdatedId == null))
|
||||
return;
|
||||
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(before.Guild, logSetting, LogType.UserUpdated)) == null)
|
||||
return;
|
||||
string str = $"🕔`{prettyCurrentTime}`";
|
||||
if (before.Username != after.Username)
|
||||
//str += $"**Name Changed**`{before.Username}#{before.Discriminator}`\n\t\t`New:`{after.ToString()}`";
|
||||
str += $"👤__**{before.Username}#{before.Discriminator}**__ **| Name Changed |** 🆔 `{before.Id}`\n\t\t`New:` **{after.ToString()}**";
|
||||
else if (before.Nickname != after.Nickname)
|
||||
str += $"👤__**{before.Username}#{before.Discriminator}**__ **| Nickname Changed |** 🆔 `{before.Id}`\n\t\t`Old:` **{before.Nickname}#{before.Discriminator}**\n\t\t`New:` **{after.Nickname}#{after.Discriminator}**";
|
||||
//str += $"**Nickname Changed**`{before.Username}#{before.Discriminator}`\n\t\t`Old:` {before.Nickname}#{before.Discriminator}\n\t\t`New:` {after.Nickname}#{after.Discriminator}";
|
||||
else if (before.AvatarUrl != after.AvatarUrl)
|
||||
//str += $"**Avatar Changed**👤`{before.Username}#{before.Discriminator}`\n\t {await _google.ShortenUrl(before.AvatarUrl)} `=>` {await _google.ShortenUrl(after.AvatarUrl)}";
|
||||
str += $"👤__**{before.Username}#{before.Discriminator}**__ **| Avatar Changed |** 🆔 `{before.Id}`\n\t🖼 {await _google.ShortenUrl(before.AvatarUrl)} `=>` {await _google.ShortenUrl(after.AvatarUrl)}";
|
||||
else if (!before.Roles.SequenceEqual(after.Roles))
|
||||
{
|
||||
if (before.Name != after.Name)
|
||||
//await logChannel.SendMessageAsync($@"`{prettyCurrentTime}` **Channel Name Changed** `#{after.Name}` ({after.Id})
|
||||
await logChannel.SendMessageAsync($@"🕓`{prettyCurrentTime}`ℹ️ **| Channel Name Changed |** #⃣ `{after.Name} ({after.Id})`
|
||||
if (before.Roles.Count() < after.Roles.Count())
|
||||
{
|
||||
var diffRoles = after.Roles.Where(r => !before.Roles.Contains(r)).Select(r => "**" + r.Name + "**");
|
||||
//str += $"**User's Roles changed ⚔➕**👤`{before.ToString()}`\n\tNow has {string.Join(", ", diffRoles)} role.";
|
||||
str += $"👤__**{before.ToString()}**__ **| User's Role Added |** 🆔 `{before.Id}`\n\t✅ {string.Join(", ", diffRoles).SanitizeMentions()}\n\t\t⚔ **`{string.Join(", ", after.Roles.Select(r => r.Name)).SanitizeMentions()}`** ⚔";
|
||||
}
|
||||
else if (before.Roles.Count() > after.Roles.Count())
|
||||
{
|
||||
var diffRoles = before.Roles.Where(r => !after.Roles.Contains(r)).Select(r => "**" + r.Name + "**");
|
||||
//str += $"**User's Roles changed **`{before.ToString()}`\n\tNo longer has {string.Join(", ", diffRoles)} role.";
|
||||
str += $"👤__**{before.ToString()}**__ **| User's Role Removed |** 🆔 `{before.Id}`\n\t🚮 {string.Join(", ", diffRoles).SanitizeMentions()}\n\t\t⚔ **`{string.Join(", ", after.Roles.Select(r => r.Name)).SanitizeMentions()}`** ⚔";
|
||||
}
|
||||
}
|
||||
else
|
||||
return;
|
||||
try { await logChannel.SendMessageAsync(str).ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
||||
}
|
||||
catch (Exception ex) { _log.Warn(ex); }
|
||||
}
|
||||
|
||||
private async void _client_ChannelUpdated(IChannel cbefore, IChannel cafter)
|
||||
{
|
||||
try
|
||||
{
|
||||
var before = cbefore as IGuildChannel;
|
||||
if (before == null)
|
||||
return;
|
||||
var after = (IGuildChannel)cafter;
|
||||
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(before.Guild.Id, out logSetting)
|
||||
|| (logSetting.ChannelUpdatedId == null)
|
||||
|| logSetting.IgnoredChannels.Any(ilc => ilc.ChannelId == after.Id))
|
||||
return;
|
||||
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(before.Guild, logSetting, LogType.ChannelUpdated)) == null)
|
||||
return;
|
||||
if (before.Name != after.Name)
|
||||
//await logChannel.SendMessageAsync($@"`{prettyCurrentTime}` **Channel Name Changed** `#{after.Name}` ({after.Id})
|
||||
await logChannel.SendMessageAsync($@"🕓`{prettyCurrentTime}`ℹ️ **| Channel Name Changed |** #⃣ `{after.Name} ({after.Id})`
|
||||
`Old:` {before.Name}
|
||||
**`New:`** {after.Name}").ConfigureAwait(false);
|
||||
else if ((before as ITextChannel).Topic != (after as ITextChannel).Topic)
|
||||
//await logChannel.SendMessageAsync($@"`{prettyCurrentTime}` **Channel Topic Changed** `#{after.Name}` ({after.Id})
|
||||
await logChannel.SendMessageAsync($@"🕘`{prettyCurrentTime}`ℹ️ **| Channel Topic Changed |** #⃣ `{after.Name} ({after.Id})`
|
||||
else if ((before as ITextChannel).Topic != (after as ITextChannel).Topic)
|
||||
//await logChannel.SendMessageAsync($@"`{prettyCurrentTime}` **Channel Topic Changed** `#{after.Name}` ({after.Id})
|
||||
await logChannel.SendMessageAsync($@"🕘`{prettyCurrentTime}`ℹ️ **| Channel Topic Changed |** #⃣ `{after.Name} ({after.Id})`
|
||||
`Old:` {((ITextChannel)before).Topic}
|
||||
**`New:`** {((ITextChannel)after).Topic}").ConfigureAwait(false);
|
||||
}
|
||||
catch { }
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Task _client_ChannelDestroyed(IChannel ich)
|
||||
{
|
||||
var ch = ich as IGuildChannel;
|
||||
if (ch == null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(ch.Guild.Id, out logSetting)
|
||||
|| (logSetting.ChannelDestroyedId == null)
|
||||
|| logSetting.IgnoredChannels.Any(ilc => ilc.ChannelId == ch.Id))
|
||||
return Task.CompletedTask;
|
||||
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(ch.Guild, logSetting, LogType.ChannelDestroyed)) == null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
var task = Task.Run(async () =>
|
||||
{
|
||||
try { await logChannel.SendMessageAsync($"🕕`{prettyCurrentTime}`🗑 **| {(ch is IVoiceChannel ? "Voice" : "Text")} Channel Deleted #⃣ {ch.Name}** `({ch.Id})`").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Task _client_ChannelCreated(IChannel ich)
|
||||
{
|
||||
var ch = ich as IGuildChannel;
|
||||
if (ch == null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(ch.Guild.Id, out logSetting)
|
||||
|| (logSetting.ChannelCreatedId == null))
|
||||
return Task.CompletedTask;
|
||||
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(ch.Guild, logSetting, LogType.ChannelCreated)) == null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
var task = Task.Run(async () =>
|
||||
{
|
||||
try { await logChannel.SendMessageAsync($"🕓`{prettyCurrentTime}`🆕 **| {(ch is IVoiceChannel ? "Voice" : "Text")} Channel Created: #⃣ {ch.Name}** `({ch.Id})`").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Task _client_UserVoiceStateUpdated(IUser iusr, IVoiceState before, IVoiceState after)
|
||||
{
|
||||
var usr = iusr as IGuildUser;
|
||||
if (usr == null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
var beforeVch = before.VoiceChannel;
|
||||
var afterVch = after.VoiceChannel;
|
||||
|
||||
if (beforeVch == afterVch)
|
||||
return Task.CompletedTask;
|
||||
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out logSetting)
|
||||
|| (logSetting.LogVoicePresenceId == null))
|
||||
return Task.CompletedTask;
|
||||
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(usr.Guild, logSetting, LogType.VoicePresence)) == null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
string str = null;
|
||||
if (beforeVch?.Guild == afterVch?.Guild)
|
||||
{
|
||||
str = $"🎙`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__ moved from **{beforeVch.Name}** to **{afterVch.Name}** voice channel.";
|
||||
}
|
||||
else if (beforeVch == null)
|
||||
catch (Exception ex) { _log.Warn(ex); }
|
||||
}
|
||||
|
||||
private async void _client_ChannelDestroyed(IChannel ich)
|
||||
{
|
||||
try
|
||||
{
|
||||
str = $"🎙`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__ has joined **{afterVch.Name}** voice channel.";
|
||||
var ch = ich as IGuildChannel;
|
||||
if (ch == null)
|
||||
return;
|
||||
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(ch.Guild.Id, out logSetting)
|
||||
|| (logSetting.ChannelDestroyedId == null)
|
||||
|| logSetting.IgnoredChannels.Any(ilc => ilc.ChannelId == ch.Id))
|
||||
return;
|
||||
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(ch.Guild, logSetting, LogType.ChannelDestroyed)) == null)
|
||||
return;
|
||||
|
||||
await logChannel.SendMessageAsync($"🕕`{prettyCurrentTime}`🗑 **| {(ch is IVoiceChannel ? "Voice" : "Text")} Channel Deleted #⃣ {ch.Name}** `({ch.Id})`").ConfigureAwait(false);
|
||||
}
|
||||
else if (afterVch == null)
|
||||
catch (Exception ex) { _log.Warn(ex); }
|
||||
}
|
||||
|
||||
private async void _client_ChannelCreated(IChannel ich)
|
||||
{
|
||||
try
|
||||
{
|
||||
str = $"🎙`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__ has left **{beforeVch.Name}** voice channel.";
|
||||
var ch = ich as IGuildChannel;
|
||||
if (ch == null)
|
||||
return;
|
||||
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(ch.Guild.Id, out logSetting)
|
||||
|| (logSetting.ChannelCreatedId == null))
|
||||
return;
|
||||
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(ch.Guild, logSetting, LogType.ChannelCreated)) == null)
|
||||
return;
|
||||
|
||||
await logChannel.SendMessageAsync($"🕓`{prettyCurrentTime}`🆕 **| {(ch is IVoiceChannel ? "Voice" : "Text")} Channel Created: #⃣ {ch.Name}** `({ch.Id})`").ConfigureAwait(false);
|
||||
}
|
||||
if (str != null)
|
||||
UserPresenceUpdates.AddOrUpdate(logChannel, new List<string>() { str }, (id, list) => { list.Add(str); return list; });
|
||||
|
||||
return Task.CompletedTask;
|
||||
catch (Exception ex) { _log.Warn(ex); }
|
||||
}
|
||||
|
||||
private Task _client_UserPresenceUpdated(IGuildUser usr, IPresence before, IPresence after)
|
||||
private async void _client_UserVoiceStateUpdated(IUser iusr, IVoiceState before, IVoiceState after) => await Task.Run(() =>
|
||||
{
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out logSetting)
|
||||
|| (logSetting.LogUserPresenceId == null)
|
||||
|| before.Status == after.Status)
|
||||
return Task.CompletedTask;
|
||||
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(usr.Guild, logSetting, LogType.UserPresence)) == null)
|
||||
return Task.CompletedTask;
|
||||
string str;
|
||||
if (before.Status != after.Status)
|
||||
str = $"🔵`{prettyCurrentTime}`👤__**{usr.Username}**__ is now **{after.Status}**.";
|
||||
else
|
||||
str = $"👾`{prettyCurrentTime}`👤__**{usr.Username}**__ is now playing **{after.Game}**.";
|
||||
|
||||
UserPresenceUpdates.AddOrUpdate(logChannel, new List<string>() { str }, (id, list) => { list.Add(str); return list; });
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Task _client_UserLeft(IGuildUser usr)
|
||||
{
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out logSetting)
|
||||
|| (logSetting.UserLeftId == null))
|
||||
return Task.CompletedTask;
|
||||
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(usr.Guild, logSetting, LogType.UserLeft)) == null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
var task = Task.Run(async () =>
|
||||
try
|
||||
{
|
||||
try { await logChannel.SendMessageAsync($"❗️🕛`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__❌ **| USER LEFT |** 🆔 `{usr.Id}`").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
||||
});
|
||||
var usr = iusr as IGuildUser;
|
||||
if (usr == null)
|
||||
return;
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
var beforeVch = before.VoiceChannel;
|
||||
var afterVch = after.VoiceChannel;
|
||||
|
||||
private Task _client_UserJoined(IGuildUser usr)
|
||||
{
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out logSetting)
|
||||
|| (logSetting.UserJoinedId == null))
|
||||
return Task.CompletedTask;
|
||||
if (beforeVch == afterVch)
|
||||
return;
|
||||
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(usr.Guild, logSetting, LogType.UserJoined)) == null)
|
||||
return Task.CompletedTask;
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out logSetting)
|
||||
|| (logSetting.LogVoicePresenceId == null))
|
||||
return;
|
||||
|
||||
var task = Task.Run(async () =>
|
||||
{
|
||||
try { await logChannel.SendMessageAsync($"❕🕓`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__✅ **| USER JOINED |** 🆔 `{usr.Id}`").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
||||
});
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(usr.Guild, logSetting, LogType.VoicePresence)) == null)
|
||||
return;
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Task _client_UserUnbanned(IUser usr, IGuild guild)
|
||||
{
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(guild.Id, out logSetting)
|
||||
|| (logSetting.UserUnbannedId == null))
|
||||
return Task.CompletedTask;
|
||||
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(guild, logSetting, LogType.UserUnbanned)) == null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
var task = Task.Run(async () =>
|
||||
{
|
||||
try { await logChannel.SendMessageAsync($"❕🕘`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__♻️ **| USER UN-BANNED |** 🆔 `{usr.Id}`").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Task _client_UserBanned(IUser usr, IGuild guild)
|
||||
{
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(guild.Id, out logSetting)
|
||||
|| (logSetting.UserBannedId == null))
|
||||
return Task.CompletedTask;
|
||||
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(guild, logSetting, LogType.UserBanned)) == null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
var task = Task.Run(async () =>
|
||||
{
|
||||
try { await logChannel.SendMessageAsync($"‼️🕕`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__🚫 **| USER BANNED |** 🆔 `{usr.Id}`").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Task _client_MessageDeleted(ulong arg1, Optional<IMessage> imsg)
|
||||
{
|
||||
var msg = (imsg.IsSpecified ? imsg.Value : null) as IUserMessage;
|
||||
if (msg == null || msg.IsAuthor())
|
||||
return Task.CompletedTask;
|
||||
|
||||
var channel = msg.Channel as ITextChannel;
|
||||
if (channel == null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(channel.Guild.Id, out logSetting)
|
||||
|| (logSetting.MessageDeletedId == null)
|
||||
|| logSetting.IgnoredChannels.Any(ilc => ilc.ChannelId == channel.Id))
|
||||
return Task.CompletedTask;
|
||||
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(channel.Guild, logSetting, LogType.MessageDeleted)) == null || logChannel.Id == msg.Id)
|
||||
return Task.CompletedTask;
|
||||
|
||||
var task = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
string str = null;
|
||||
if (beforeVch?.Guild == afterVch?.Guild)
|
||||
{
|
||||
var str = $@"🕔`{prettyCurrentTime}`👤__**{msg.Author.Username}#{msg.Author.Discriminator}**__ **| Deleted Message |** 🆔 `{msg.Author.Id}` #⃣ `{channel.Name}`
|
||||
🗑 {msg.Resolve(userHandling: UserMentionHandling.NameAndDiscriminator)}";
|
||||
if (msg.Attachments.Any())
|
||||
str += $"{Environment.NewLine}📎 {string.Join(", ", msg.Attachments.Select(a => a.ProxyUrl))}";
|
||||
await logChannel.SendMessageAsync(str.SanitizeMentions()).ConfigureAwait(false);
|
||||
str = $"🎙`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__ moved from **{beforeVch.Name}** to **{afterVch.Name}** voice channel.";
|
||||
}
|
||||
catch (Exception ex) { _log.Warn(ex); }
|
||||
});
|
||||
else if (beforeVch == null)
|
||||
{
|
||||
str = $"🎙`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__ has joined **{afterVch.Name}** voice channel.";
|
||||
}
|
||||
else if (afterVch == null)
|
||||
{
|
||||
str = $"🎙`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__ has left **{beforeVch.Name}** voice channel.";
|
||||
}
|
||||
if (str != null)
|
||||
UserPresenceUpdates.AddOrUpdate(logChannel, new List<string>() { str }, (id, list) => { list.Add(str); return list; });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.Warn(ex);
|
||||
}
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
private async void _client_UserPresenceUpdated(IGuildUser usr, IPresence before, IPresence after) => await Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out logSetting)
|
||||
|| (logSetting.LogUserPresenceId == null)
|
||||
|| before.Status == after.Status)
|
||||
return;
|
||||
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(usr.Guild, logSetting, LogType.UserPresence)) == null)
|
||||
return;
|
||||
string str;
|
||||
if (before.Status != after.Status)
|
||||
str = $"🔵`{prettyCurrentTime}`👤__**{usr.Username}**__ is now **{after.Status}**.";
|
||||
else
|
||||
str = $"👾`{prettyCurrentTime}`👤__**{usr.Username}**__ is now playing **{after.Game}**.";
|
||||
|
||||
UserPresenceUpdates.AddOrUpdate(logChannel, new List<string>() { str }, (id, list) => { list.Add(str); return list; });
|
||||
}
|
||||
catch { }
|
||||
});
|
||||
|
||||
private async void _client_UserLeft(IGuildUser usr)
|
||||
{
|
||||
try
|
||||
{
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out logSetting)
|
||||
|| (logSetting.UserLeftId == null))
|
||||
return;
|
||||
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(usr.Guild, logSetting, LogType.UserLeft)) == null)
|
||||
return;
|
||||
await logChannel.SendMessageAsync($"❗️🕛`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__❌ **| USER LEFT |** 🆔 `{usr.Id}`").ConfigureAwait(false);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private Task _client_MessageUpdated(Optional<IMessage> optmsg, IMessage imsg2)
|
||||
private async void _client_UserJoined(IGuildUser usr)
|
||||
{
|
||||
var after = imsg2 as IUserMessage;
|
||||
if (after == null || after.IsAuthor())
|
||||
return Task.CompletedTask;
|
||||
|
||||
var before = (optmsg.IsSpecified ? optmsg.Value : null) as IUserMessage;
|
||||
if (before == null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
var channel = after.Channel as ITextChannel;
|
||||
if (channel == null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
if (before.Content == after.Content)
|
||||
return Task.CompletedTask;
|
||||
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(channel.Guild.Id, out logSetting)
|
||||
|| (logSetting.MessageUpdatedId == null)
|
||||
|| logSetting.IgnoredChannels.Any(ilc => ilc.ChannelId == channel.Id))
|
||||
return Task.CompletedTask;
|
||||
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(channel.Guild, logSetting, LogType.MessageUpdated)) == null || logChannel.Id == after.Channel.Id)
|
||||
return Task.CompletedTask;
|
||||
|
||||
var task = Task.Run(async () =>
|
||||
try
|
||||
{
|
||||
//try { await logChannel.SendMessageAsync($@"🕔`{prettyCurrentTime}` **Message** 📝 `#{channel.Name}`
|
||||
//👤`{before.Author.Username}`
|
||||
try { await logChannel.SendMessageAsync($@"🕔`{prettyCurrentTime}`👤__**{before.Author.Username}#{before.Author.Discriminator}**__ **| 📝 Edited Message |** 🆔 `{before.Author.Id}` #⃣ `{channel.Name}`
|
||||
`Old:` {before.Resolve(userHandling: UserMentionHandling.NameAndDiscriminator).SanitizeMentions()}
|
||||
**`New:`** {after.Resolve(userHandling: UserMentionHandling.NameAndDiscriminator).SanitizeMentions()}").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
||||
});
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out logSetting)
|
||||
|| (logSetting.UserJoinedId == null))
|
||||
return;
|
||||
|
||||
return Task.CompletedTask;
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(usr.Guild, logSetting, LogType.UserJoined)) == null)
|
||||
return;
|
||||
|
||||
await logChannel.SendMessageAsync($"❕🕓`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__✅ **| USER JOINED |** 🆔 `{usr.Id}`").ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex) { _log.Warn(ex); }
|
||||
}
|
||||
|
||||
private async void _client_UserUnbanned(IUser usr, IGuild guild)
|
||||
{
|
||||
try
|
||||
{
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(guild.Id, out logSetting)
|
||||
|| (logSetting.UserUnbannedId == null))
|
||||
return;
|
||||
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(guild, logSetting, LogType.UserUnbanned)) == null)
|
||||
return;
|
||||
|
||||
await logChannel.SendMessageAsync($"❕🕘`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__♻️ **| USER UN-BANNED |** 🆔 `{usr.Id}`").ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex) { _log.Warn(ex); }
|
||||
}
|
||||
|
||||
private async void _client_UserBanned(IUser usr, IGuild guild)
|
||||
{
|
||||
try
|
||||
{
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(guild.Id, out logSetting)
|
||||
|| (logSetting.UserBannedId == null))
|
||||
return;
|
||||
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(guild, logSetting, LogType.UserBanned)) == null)
|
||||
return;
|
||||
await logChannel.SendMessageAsync($"‼️🕕`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__🚫 **| USER BANNED |** 🆔 `{usr.Id}`").ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex) { _log.Warn(ex); }
|
||||
}
|
||||
|
||||
private async void _client_MessageDeleted(ulong arg1, Optional<IMessage> imsg)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
var msg = (imsg.IsSpecified ? imsg.Value : null) as IUserMessage;
|
||||
if (msg == null || msg.IsAuthor())
|
||||
return;
|
||||
|
||||
var channel = msg.Channel as ITextChannel;
|
||||
if (channel == null)
|
||||
return;
|
||||
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(channel.Guild.Id, out logSetting)
|
||||
|| (logSetting.MessageDeletedId == null)
|
||||
|| logSetting.IgnoredChannels.Any(ilc => ilc.ChannelId == channel.Id))
|
||||
return;
|
||||
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(channel.Guild, logSetting, LogType.MessageDeleted)) == null || logChannel.Id == msg.Id)
|
||||
return;
|
||||
var str = $@"🕔`{prettyCurrentTime}`👤__**{msg.Author.Username}#{msg.Author.Discriminator}**__ **| Deleted Message |** 🆔 `{msg.Author.Id}` #⃣ `{channel.Name}`
|
||||
🗑 {msg.Resolve(userHandling: UserMentionHandling.NameAndDiscriminator)}";
|
||||
if (msg.Attachments.Any())
|
||||
str += $"{Environment.NewLine}📎 {string.Join(", ", msg.Attachments.Select(a => a.ProxyUrl))}";
|
||||
await logChannel.SendMessageAsync(str.SanitizeMentions()).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex) { _log.Warn(ex); }
|
||||
}
|
||||
|
||||
private async void _client_MessageUpdated(Optional<IMessage> optmsg, IMessage imsg2)
|
||||
{
|
||||
try
|
||||
{
|
||||
var after = imsg2 as IUserMessage;
|
||||
if (after == null || after.IsAuthor())
|
||||
return;
|
||||
|
||||
var before = (optmsg.IsSpecified ? optmsg.Value : null) as IUserMessage;
|
||||
if (before == null)
|
||||
return;
|
||||
|
||||
var channel = after.Channel as ITextChannel;
|
||||
if (channel == null)
|
||||
return;
|
||||
|
||||
if (before.Content == after.Content)
|
||||
return;
|
||||
|
||||
LogSetting logSetting;
|
||||
if (!GuildLogSettings.TryGetValue(channel.Guild.Id, out logSetting)
|
||||
|| (logSetting.MessageUpdatedId == null)
|
||||
|| logSetting.IgnoredChannels.Any(ilc => ilc.ChannelId == channel.Id))
|
||||
return;
|
||||
|
||||
ITextChannel logChannel;
|
||||
if ((logChannel = TryGetLogChannel(channel.Guild, logSetting, LogType.MessageUpdated)) == null || logChannel.Id == after.Channel.Id)
|
||||
return;
|
||||
await logChannel.SendMessageAsync($@"🕔`{prettyCurrentTime}`👤__**{before.Author.Username}#{before.Author.Discriminator}**__ **| 📝 Edited Message |** 🆔 `{before.Author.Id}` #⃣ `{channel.Name}`
|
||||
`Old:` {before.Resolve(userHandling: UserMentionHandling.NameAndDiscriminator).SanitizeMentions()}
|
||||
**`New:`** {after.Resolve(userHandling: UserMentionHandling.NameAndDiscriminator).SanitizeMentions()}").ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex) { _log.Warn(ex); }
|
||||
}
|
||||
|
||||
public enum LogType
|
||||
|
@ -53,13 +53,13 @@ namespace NadekoBot.Modules.Administration
|
||||
var toSend = "🔄 " + Repeater.Message;
|
||||
await Task.Delay(Repeater.Interval, token).ConfigureAwait(false);
|
||||
|
||||
var lastMsgInChannel = (await Channel.GetMessagesAsync(1)).FirstOrDefault();
|
||||
if (lastMsgInChannel.Id == oldMsg.Id) //don't send if it's the same message in the channel
|
||||
continue;
|
||||
//var lastMsgInChannel = (await Channel.GetMessagesAsync(2)).FirstOrDefault();
|
||||
// if (lastMsgInChannel.Id == oldMsg?.Id) //don't send if it's the same message in the channel
|
||||
// continue;
|
||||
|
||||
if (oldMsg != null)
|
||||
try { await oldMsg.DeleteAsync(); } catch { }
|
||||
try { oldMsg = await Channel.SendMessageAsync(toSend).ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); try { source.Cancel(); } catch { } }
|
||||
try { oldMsg = await Channel.SendMessageAsync(toSend).ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException) { }
|
||||
|
@ -24,8 +24,8 @@ namespace NadekoBot.Modules.Administration
|
||||
|
||||
private static ConcurrentDictionary<ulong, ConcurrentHashSet<ulong>> MutedUsers { get; } = new ConcurrentDictionary<ulong, ConcurrentHashSet<ulong>>();
|
||||
|
||||
public static event Func<IGuildUser, MuteType, Task> UserMuted = delegate { return Task.CompletedTask; };
|
||||
public static event Func<IGuildUser, MuteType, Task> UserUnmuted = delegate { return Task.CompletedTask; };
|
||||
public static event Action<IGuildUser, MuteType> UserMuted = delegate { };
|
||||
public static event Action<IGuildUser, MuteType> UserUnmuted = delegate { };
|
||||
|
||||
|
||||
public enum MuteType {
|
||||
@ -51,15 +51,22 @@ namespace NadekoBot.Modules.Administration
|
||||
NadekoBot.Client.UserJoined += Client_UserJoined;
|
||||
}
|
||||
|
||||
private static async Task Client_UserJoined(IGuildUser usr)
|
||||
private static async void Client_UserJoined(IGuildUser usr)
|
||||
{
|
||||
ConcurrentHashSet<ulong> muted;
|
||||
MutedUsers.TryGetValue(usr.Guild.Id, out muted);
|
||||
try
|
||||
{
|
||||
ConcurrentHashSet<ulong> muted;
|
||||
MutedUsers.TryGetValue(usr.Guild.Id, out muted);
|
||||
|
||||
if (muted == null || !muted.Contains(usr.Id))
|
||||
return;
|
||||
else
|
||||
await Mute(usr).ConfigureAwait(false);
|
||||
if (muted == null || !muted.Contains(usr.Id))
|
||||
return;
|
||||
else
|
||||
await Mute(usr).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.Warn(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -80,7 +87,7 @@ namespace NadekoBot.Modules.Administration
|
||||
|
||||
await uow.CompleteAsync().ConfigureAwait(false);
|
||||
}
|
||||
await UserMuted(usr, MuteType.All).ConfigureAwait(false);
|
||||
UserMuted(usr, MuteType.All);
|
||||
}
|
||||
|
||||
public static async Task Unmute(IGuildUser usr)
|
||||
@ -99,7 +106,7 @@ namespace NadekoBot.Modules.Administration
|
||||
muted.TryRemove(usr.Id);
|
||||
await uow.CompleteAsync().ConfigureAwait(false);
|
||||
}
|
||||
await UserUnmuted(usr, MuteType.All).ConfigureAwait(false);
|
||||
UserUnmuted(usr, MuteType.All);
|
||||
}
|
||||
|
||||
public static async Task<IRole> GetMuteRole(IGuild guild)
|
||||
@ -211,7 +218,7 @@ namespace NadekoBot.Modules.Administration
|
||||
try
|
||||
{
|
||||
await user.AddRolesAsync(await GetMuteRole(channel.Guild).ConfigureAwait(false)).ConfigureAwait(false);
|
||||
await UserMuted(user, MuteType.Chat).ConfigureAwait(false);
|
||||
UserMuted(user, MuteType.Chat);
|
||||
await channel.SendConfirmAsync($"✏️🚫 **{user}** has been **muted** from chatting.").ConfigureAwait(false);
|
||||
}
|
||||
catch
|
||||
@ -230,7 +237,7 @@ namespace NadekoBot.Modules.Administration
|
||||
try
|
||||
{
|
||||
await user.RemoveRolesAsync(await GetMuteRole(channel.Guild).ConfigureAwait(false)).ConfigureAwait(false);
|
||||
await UserUnmuted(user, MuteType.Chat).ConfigureAwait(false);
|
||||
UserUnmuted(user, MuteType.Chat);
|
||||
await channel.SendConfirmAsync($"✏️✅ **{user}** has been **unmuted** from chatting.").ConfigureAwait(false);
|
||||
}
|
||||
catch
|
||||
@ -249,7 +256,7 @@ namespace NadekoBot.Modules.Administration
|
||||
try
|
||||
{
|
||||
await user.ModifyAsync(usr => usr.Mute = true).ConfigureAwait(false);
|
||||
await UserMuted(user, MuteType.Voice).ConfigureAwait(false);
|
||||
UserMuted(user, MuteType.Voice);
|
||||
await channel.SendConfirmAsync($"🎙🚫 **{user}** has been **voice muted**.").ConfigureAwait(false);
|
||||
}
|
||||
catch
|
||||
@ -267,7 +274,7 @@ namespace NadekoBot.Modules.Administration
|
||||
try
|
||||
{
|
||||
await user.ModifyAsync(usr => usr.Mute = false).ConfigureAwait(false);
|
||||
await UserUnmuted(user, MuteType.Voice).ConfigureAwait(false);
|
||||
UserUnmuted(user, MuteType.Voice);
|
||||
await channel.SendConfirmAsync($"🎙✅ **{user}** has been **voice unmuted**.").ConfigureAwait(false);
|
||||
}
|
||||
catch
|
||||
|
@ -45,7 +45,8 @@ namespace NadekoBot.Modules.Administration
|
||||
else
|
||||
{
|
||||
usr.MessageCount++;
|
||||
var t = Task.Run(async () => {
|
||||
var t = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await Task.Delay(PerSeconds * 1000, cancelSource.Token);
|
||||
@ -61,26 +62,26 @@ namespace NadekoBot.Modules.Administration
|
||||
|
||||
static RatelimitCommand()
|
||||
{
|
||||
_log = LogManager.GetCurrentClassLogger();
|
||||
_log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
NadekoBot.Client.MessageReceived += (umsg) =>
|
||||
{
|
||||
var t = Task.Run(async () =>
|
||||
{
|
||||
var usrMsg = umsg as IUserMessage;
|
||||
var channel = usrMsg.Channel as ITextChannel;
|
||||
NadekoBot.Client.MessageReceived += async (umsg) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var usrMsg = umsg as IUserMessage;
|
||||
var channel = usrMsg.Channel as ITextChannel;
|
||||
|
||||
if (channel == null || usrMsg.IsAuthor())
|
||||
return;
|
||||
Ratelimiter limiter;
|
||||
if (!RatelimitingChannels.TryGetValue(channel.Id, out limiter))
|
||||
return;
|
||||
if (channel == null || usrMsg.IsAuthor())
|
||||
return;
|
||||
Ratelimiter limiter;
|
||||
if (!RatelimitingChannels.TryGetValue(channel.Id, out limiter))
|
||||
return;
|
||||
|
||||
if (limiter.CheckUserRatelimit(usrMsg.Author.Id))
|
||||
try { await usrMsg.DeleteAsync(); } catch (Exception ex) { _log.Warn(ex); }
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
if (limiter.CheckUserRatelimit(usrMsg.Author.Id))
|
||||
await usrMsg.DeleteAsync();
|
||||
}
|
||||
catch (Exception ex) { _log.Warn(ex); }
|
||||
};
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
@ -118,7 +119,7 @@ namespace NadekoBot.Modules.Administration
|
||||
MaxMessages = msg,
|
||||
PerSeconds = perSec,
|
||||
};
|
||||
if(RatelimitingChannels.TryAdd(channel.Id, toAdd))
|
||||
if (RatelimitingChannels.TryAdd(channel.Id, toAdd))
|
||||
{
|
||||
await channel.SendConfirmAsync("Slow mode initiated",
|
||||
$"Users can't send more than `{toAdd.MaxMessages} message(s)` every `{toAdd.PerSeconds} second(s)`.")
|
||||
@ -127,4 +128,4 @@ namespace NadekoBot.Modules.Administration
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -25,93 +25,85 @@ namespace NadekoBot.Modules.Administration
|
||||
NadekoBot.Client.UserLeft += UserLeft;
|
||||
_log = LogManager.GetCurrentClassLogger();
|
||||
}
|
||||
|
||||
private static Task UserLeft(IGuildUser user)
|
||||
//todo optimize ASAP
|
||||
private static async void UserLeft(IGuildUser user)
|
||||
{
|
||||
var leftTask = Task.Run(async () =>
|
||||
try
|
||||
{
|
||||
GuildConfig conf;
|
||||
using (var uow = DbHandler.UnitOfWork())
|
||||
{
|
||||
conf = uow.GuildConfigs.For(user.Guild.Id, set => set);
|
||||
}
|
||||
|
||||
if (!conf.SendChannelByeMessage) return;
|
||||
var channel = (await user.Guild.GetTextChannelsAsync()).SingleOrDefault(c => c.Id == conf.ByeMessageChannelId);
|
||||
|
||||
if (channel == null) //maybe warn the server owner that the channel is missing
|
||||
return;
|
||||
|
||||
var msg = conf.ChannelByeMessageText.Replace("%user%", user.Username).Replace("%id%", user.Id.ToString()).Replace("%server%", user.Guild.Name);
|
||||
if (string.IsNullOrWhiteSpace(msg))
|
||||
return;
|
||||
try
|
||||
{
|
||||
GuildConfig conf;
|
||||
using (var uow = DbHandler.UnitOfWork())
|
||||
var toDelete = await channel.SendMessageAsync(msg.SanitizeMentions()).ConfigureAwait(false);
|
||||
if (conf.AutoDeleteByeMessagesTimer > 0)
|
||||
{
|
||||
conf = uow.GuildConfigs.For(user.Guild.Id, set => set);
|
||||
toDelete.DeleteAfter(conf.AutoDeleteByeMessagesTimer);
|
||||
}
|
||||
|
||||
if (!conf.SendChannelByeMessage) return;
|
||||
var channel = (await user.Guild.GetTextChannelsAsync()).SingleOrDefault(c => c.Id == conf.ByeMessageChannelId);
|
||||
|
||||
if (channel == null) //maybe warn the server owner that the channel is missing
|
||||
return;
|
||||
|
||||
var msg = conf.ChannelByeMessageText.Replace("%user%", user.Username).Replace("%id%", user.Id.ToString()).Replace("%server%", user.Guild.Name);
|
||||
if (string.IsNullOrWhiteSpace(msg))
|
||||
return;
|
||||
try
|
||||
{
|
||||
var toDelete = await channel.SendMessageAsync(msg.SanitizeMentions()).ConfigureAwait(false);
|
||||
if (conf.AutoDeleteByeMessagesTimer > 0)
|
||||
{
|
||||
toDelete.DeleteAfter(conf.AutoDeleteByeMessagesTimer);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) { _log.Warn(ex); }
|
||||
}
|
||||
catch { }
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
catch (Exception ex) { _log.Warn(ex); }
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private static Task UserJoined(IGuildUser user)
|
||||
private static async void UserJoined(IGuildUser user)
|
||||
{
|
||||
var joinedTask = Task.Run(async () =>
|
||||
try
|
||||
{
|
||||
try
|
||||
GuildConfig conf;
|
||||
using (var uow = DbHandler.UnitOfWork())
|
||||
{
|
||||
GuildConfig conf;
|
||||
using (var uow = DbHandler.UnitOfWork())
|
||||
{
|
||||
conf = uow.GuildConfigs.For(user.Guild.Id, set => set);
|
||||
}
|
||||
conf = uow.GuildConfigs.For(user.Guild.Id, set => set);
|
||||
}
|
||||
|
||||
if (conf.SendChannelGreetMessage)
|
||||
if (conf.SendChannelGreetMessage)
|
||||
{
|
||||
var channel = (await user.Guild.GetTextChannelsAsync()).SingleOrDefault(c => c.Id == conf.GreetMessageChannelId);
|
||||
if (channel != null) //maybe warn the server owner that the channel is missing
|
||||
{
|
||||
var channel = (await user.Guild.GetTextChannelsAsync()).SingleOrDefault(c => c.Id == conf.GreetMessageChannelId);
|
||||
if (channel != null) //maybe warn the server owner that the channel is missing
|
||||
var msg = conf.ChannelGreetMessageText.Replace("%user%", user.Mention).Replace("%id%", user.Id.ToString()).Replace("%server%", user.Guild.Name);
|
||||
if (!string.IsNullOrWhiteSpace(msg))
|
||||
{
|
||||
var msg = conf.ChannelGreetMessageText.Replace("%user%", user.Mention).Replace("%id%", user.Id.ToString()).Replace("%server%", user.Guild.Name);
|
||||
if (!string.IsNullOrWhiteSpace(msg))
|
||||
try
|
||||
{
|
||||
try
|
||||
var toDelete = await channel.SendMessageAsync(msg.SanitizeMentions()).ConfigureAwait(false);
|
||||
if (conf.AutoDeleteGreetMessagesTimer > 0)
|
||||
{
|
||||
var toDelete = await channel.SendMessageAsync(msg.SanitizeMentions()).ConfigureAwait(false);
|
||||
if (conf.AutoDeleteGreetMessagesTimer > 0)
|
||||
{
|
||||
toDelete.DeleteAfter(conf.AutoDeleteGreetMessagesTimer);
|
||||
}
|
||||
toDelete.DeleteAfter(conf.AutoDeleteGreetMessagesTimer);
|
||||
}
|
||||
catch (Exception ex) { _log.Warn(ex); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (conf.SendDmGreetMessage)
|
||||
{
|
||||
var channel = await user.CreateDMChannelAsync();
|
||||
|
||||
if (channel != null)
|
||||
{
|
||||
var msg = conf.DmGreetMessageText.Replace("%user%", user.Username).Replace("%server%", user.Guild.Name);
|
||||
if (!string.IsNullOrWhiteSpace(msg))
|
||||
{
|
||||
await channel.SendConfirmAsync(msg).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex) { _log.Warn(ex); }
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
|
||||
if (conf.SendDmGreetMessage)
|
||||
{
|
||||
var channel = await user.CreateDMChannelAsync();
|
||||
|
||||
if (channel != null)
|
||||
{
|
||||
var msg = conf.DmGreetMessageText.Replace("%user%", user.Username).Replace("%server%", user.Guild.Name);
|
||||
if (!string.IsNullOrWhiteSpace(msg))
|
||||
{
|
||||
await channel.SendConfirmAsync(msg).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
@ -135,7 +127,7 @@ namespace NadekoBot.Modules.Administration
|
||||
{
|
||||
if (timer < 0 || timer > 600)
|
||||
return;
|
||||
|
||||
|
||||
using (var uow = DbHandler.UnitOfWork())
|
||||
{
|
||||
var conf = uow.GuildConfigs.For(id, set => set);
|
||||
@ -173,7 +165,7 @@ namespace NadekoBot.Modules.Administration
|
||||
}
|
||||
return enabled;
|
||||
}
|
||||
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[RequirePermission(GuildPermission.ManageGuild)]
|
||||
@ -343,7 +335,7 @@ namespace NadekoBot.Modules.Administration
|
||||
if (!sendByeEnabled)
|
||||
await channel.SendConfirmAsync($"ℹ️ Enable bye messsages by typing `{NadekoBot.ModulePrefixes[typeof(Administration).Name]}bye`").ConfigureAwait(false);
|
||||
}
|
||||
|
||||
|
||||
public static bool SetByeMessage(ulong guildId, ref string message)
|
||||
{
|
||||
message = message?.SanitizeMentions();
|
||||
@ -394,4 +386,4 @@ namespace NadekoBot.Modules.Administration
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -18,7 +18,7 @@ namespace NadekoBot.Modules.Administration
|
||||
public class VoicePlusTextCommands
|
||||
{
|
||||
private static Regex channelNameRegex = new Regex(@"[^a-zA-Z0-9 -]", RegexOptions.Compiled);
|
||||
|
||||
|
||||
private static ConcurrentHashSet<ulong> voicePlusTextCache { get; }
|
||||
static VoicePlusTextCommands()
|
||||
{
|
||||
@ -29,76 +29,73 @@ namespace NadekoBot.Modules.Administration
|
||||
NadekoBot.Client.UserVoiceStateUpdated += UserUpdatedEventHandler;
|
||||
}
|
||||
|
||||
private static Task UserUpdatedEventHandler(IUser iuser, IVoiceState before, IVoiceState after)
|
||||
private static async void UserUpdatedEventHandler(IUser iuser, IVoiceState before, IVoiceState after)
|
||||
{
|
||||
var user = (iuser as IGuildUser);
|
||||
var guild = user?.Guild;
|
||||
|
||||
if (guild == null)
|
||||
return Task.CompletedTask;
|
||||
var task = Task.Run(async () =>
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
var botUserPerms = guild.GetCurrentUser().GuildPermissions;
|
||||
|
||||
if (before.VoiceChannel == after.VoiceChannel) return;
|
||||
|
||||
if (!voicePlusTextCache.Contains(guild.Id))
|
||||
return;
|
||||
|
||||
if (!botUserPerms.ManageChannels || !botUserPerms.ManageRoles)
|
||||
{
|
||||
var botUserPerms = guild.GetCurrentUser().GuildPermissions;
|
||||
|
||||
if (before.VoiceChannel == after.VoiceChannel) return;
|
||||
|
||||
if (!voicePlusTextCache.Contains(guild.Id))
|
||||
return;
|
||||
|
||||
if (!botUserPerms.ManageChannels || !botUserPerms.ManageRoles)
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
await (await guild.GetOwnerAsync()).SendErrorAsync(
|
||||
"⚠️ I don't have **manage server** and/or **manage channels** permission," +
|
||||
$" so I cannot run `voice+text` on **{guild.Name}** server.").ConfigureAwait(false);
|
||||
}
|
||||
catch { }
|
||||
using (var uow = DbHandler.UnitOfWork())
|
||||
{
|
||||
uow.GuildConfigs.For(guild.Id, set => set).VoicePlusTextEnabled = false;
|
||||
voicePlusTextCache.TryRemove(guild.Id);
|
||||
await uow.CompleteAsync().ConfigureAwait(false);
|
||||
}
|
||||
return;
|
||||
await (await guild.GetOwnerAsync()).SendErrorAsync(
|
||||
"⚠️ I don't have **manage server** and/or **manage channels** permission," +
|
||||
$" so I cannot run `voice+text` on **{guild.Name}** server.").ConfigureAwait(false);
|
||||
}
|
||||
|
||||
|
||||
var beforeVch = before.VoiceChannel;
|
||||
if (beforeVch != null)
|
||||
catch { }
|
||||
using (var uow = DbHandler.UnitOfWork())
|
||||
{
|
||||
var textChannel = guild.GetTextChannels().Where(t => t.Name == GetChannelName(beforeVch.Name).ToLowerInvariant()).FirstOrDefault();
|
||||
if (textChannel != null)
|
||||
await textChannel.AddPermissionOverwriteAsync(user,
|
||||
new OverwritePermissions(readMessages: PermValue.Deny,
|
||||
sendMessages: PermValue.Deny)).ConfigureAwait(false);
|
||||
uow.GuildConfigs.For(guild.Id, set => set).VoicePlusTextEnabled = false;
|
||||
voicePlusTextCache.TryRemove(guild.Id);
|
||||
await uow.CompleteAsync().ConfigureAwait(false);
|
||||
}
|
||||
var afterVch = after.VoiceChannel;
|
||||
if (afterVch != null && guild.AFKChannelId != afterVch.Id)
|
||||
{
|
||||
var textChannel = guild.GetTextChannels()
|
||||
.Where(t => t.Name == GetChannelName(afterVch.Name).ToLowerInvariant())
|
||||
.FirstOrDefault();
|
||||
if (textChannel == null)
|
||||
{
|
||||
textChannel = (await guild.CreateTextChannelAsync(GetChannelName(afterVch.Name).ToLowerInvariant()).ConfigureAwait(false));
|
||||
await textChannel.AddPermissionOverwriteAsync(guild.EveryoneRole,
|
||||
new OverwritePermissions(readMessages: PermValue.Deny,
|
||||
sendMessages: PermValue.Deny)).ConfigureAwait(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var beforeVch = before.VoiceChannel;
|
||||
if (beforeVch != null)
|
||||
{
|
||||
var textChannel = guild.GetTextChannels().Where(t => t.Name == GetChannelName(beforeVch.Name).ToLowerInvariant()).FirstOrDefault();
|
||||
if (textChannel != null)
|
||||
await textChannel.AddPermissionOverwriteAsync(user,
|
||||
new OverwritePermissions(readMessages: PermValue.Allow,
|
||||
sendMessages: PermValue.Allow)).ConfigureAwait(false);
|
||||
}
|
||||
new OverwritePermissions(readMessages: PermValue.Deny,
|
||||
sendMessages: PermValue.Deny)).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
var afterVch = after.VoiceChannel;
|
||||
if (afterVch != null && guild.AFKChannelId != afterVch.Id)
|
||||
{
|
||||
Console.WriteLine(ex);
|
||||
var textChannel = guild.GetTextChannels()
|
||||
.Where(t => t.Name == GetChannelName(afterVch.Name).ToLowerInvariant())
|
||||
.FirstOrDefault();
|
||||
if (textChannel == null)
|
||||
{
|
||||
textChannel = (await guild.CreateTextChannelAsync(GetChannelName(afterVch.Name).ToLowerInvariant()).ConfigureAwait(false));
|
||||
await textChannel.AddPermissionOverwriteAsync(guild.EveryoneRole,
|
||||
new OverwritePermissions(readMessages: PermValue.Deny,
|
||||
sendMessages: PermValue.Deny)).ConfigureAwait(false);
|
||||
}
|
||||
await textChannel.AddPermissionOverwriteAsync(user,
|
||||
new OverwritePermissions(readMessages: PermValue.Allow,
|
||||
sendMessages: PermValue.Allow)).ConfigureAwait(false);
|
||||
}
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetChannelName(string voiceName) =>
|
||||
@ -187,4 +184,4 @@ namespace NadekoBot.Modules.Administration
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -172,7 +172,7 @@ namespace NadekoBot.Modules.CustomReactions
|
||||
{
|
||||
var txtStream = await customReactions.GroupBy(cr => cr.Trigger)
|
||||
.OrderBy(cr => cr.Key)
|
||||
.Select(cr => new { Trigger = cr.Key, Responses = cr.Select(y => y.Response).ToList() })
|
||||
.Select(cr => new { Trigger = cr.Key, Responses = cr.Select(y => new { id = y.Id, text = y.Response }).ToList() })
|
||||
.ToJson()
|
||||
.ToStream()
|
||||
.ConfigureAwait(false);
|
||||
@ -293,7 +293,7 @@ namespace NadekoBot.Modules.CustomReactions
|
||||
{
|
||||
await imsg.Channel.SendErrorAsync("No stats for that trigger found, no action taken.").ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
@ -302,7 +302,7 @@ namespace NadekoBot.Modules.CustomReactions
|
||||
if (page < 1)
|
||||
return;
|
||||
await imsg.Channel.EmbedAsync(ReactionStats.OrderByDescending(x => x.Value)
|
||||
.Skip((page - 1)*9)
|
||||
.Skip((page - 1) * 9)
|
||||
.Take(9)
|
||||
.Aggregate(new EmbedBuilder().WithOkColor().WithTitle($"Custom Reaction stats page #{page}"),
|
||||
(agg, cur) => agg.AddField(efb => efb.WithName(cur.Key).WithValue(cur.Value.ToString()).WithIsInline(true)))
|
||||
@ -310,4 +310,4 @@ namespace NadekoBot.Modules.CustomReactions
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -199,7 +199,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
{
|
||||
var wonAmount = winner.AmountBet * (participants.Count - 1);
|
||||
|
||||
await CurrencyHandler.AddCurrencyAsync(winner.User, "Won a Race", wonAmount, false).ConfigureAwait(false);
|
||||
await CurrencyHandler.AddCurrencyAsync(winner.User, "Won a Race", wonAmount, true).ConfigureAwait(false);
|
||||
await raceChannel.SendConfirmAsync("Animal Race", $"{winner.User.Mention} as {winner.Animal} **Won the race and {wonAmount}{CurrencySign}!**").ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
@ -209,15 +209,15 @@ namespace NadekoBot.Modules.Gambling
|
||||
|
||||
}
|
||||
|
||||
private Task Client_MessageReceived(IMessage imsg)
|
||||
private void Client_MessageReceived(IMessage imsg)
|
||||
{
|
||||
var msg = imsg as IUserMessage;
|
||||
if (msg == null)
|
||||
return Task.CompletedTask;
|
||||
return;
|
||||
if (msg.IsAuthor() || !(imsg.Channel is ITextChannel) || imsg.Channel != raceChannel)
|
||||
return Task.CompletedTask;
|
||||
return;
|
||||
messagesSinceGameStarted++;
|
||||
return Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
private async Task CheckForFullGameAsync(CancellationToken cancelToken)
|
||||
@ -248,7 +248,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
return;
|
||||
}
|
||||
if (amount > 0)
|
||||
if (!await CurrencyHandler.RemoveCurrencyAsync((IGuildUser)u, "BetRace", amount, true).ConfigureAwait(false))
|
||||
if (!await CurrencyHandler.RemoveCurrencyAsync((IGuildUser)u, "BetRace", amount, false).ConfigureAwait(false))
|
||||
{
|
||||
try { await raceChannel.SendErrorAsync($"{u.Mention} You don't have enough {Gambling.CurrencyName}s.").ConfigureAwait(false); } catch { }
|
||||
return;
|
||||
@ -277,10 +277,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
this.AmountBet = amount;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return User.GetHashCode();
|
||||
}
|
||||
public override int GetHashCode() => User.GetHashCode();
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
|
@ -3,6 +3,7 @@ using Discord.Commands;
|
||||
using NadekoBot.Attributes;
|
||||
using NadekoBot.Extensions;
|
||||
using NadekoBot.Services;
|
||||
using NLog;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
@ -73,9 +74,12 @@ namespace NadekoBot.Modules.Games
|
||||
|
||||
//text, votes
|
||||
private readonly ConcurrentDictionary<string, int> votes = new ConcurrentDictionary<string, int>();
|
||||
private readonly Logger _log;
|
||||
|
||||
public AcrophobiaGame(ITextChannel channel, int time)
|
||||
{
|
||||
this._log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
this.channel = channel;
|
||||
this.time = time;
|
||||
this.source = new CancellationTokenSource();
|
||||
@ -163,101 +167,100 @@ namespace NadekoBot.Modules.Games
|
||||
await End().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private Task PotentialAcro(IMessage arg)
|
||||
private async void PotentialAcro(IMessage arg)
|
||||
{
|
||||
var t = Task.Run(async () =>
|
||||
try
|
||||
{
|
||||
try
|
||||
var msg = arg as IUserMessage;
|
||||
if (msg == null || msg.Author.IsBot || msg.Channel.Id != channel.Id)
|
||||
return;
|
||||
|
||||
++spamCount;
|
||||
|
||||
var guildUser = (IGuildUser)msg.Author;
|
||||
|
||||
var input = msg.Content.ToUpperInvariant().Trim();
|
||||
|
||||
if (phase == AcroPhase.Submitting)
|
||||
{
|
||||
var msg = arg as IUserMessage;
|
||||
if (msg == null || msg.Author.IsBot || msg.Channel.Id != channel.Id)
|
||||
if (spamCount > 10)
|
||||
{
|
||||
spamCount = 0;
|
||||
try { await channel.EmbedAsync(GetEmbed().Build()).ConfigureAwait(false); }
|
||||
catch { }
|
||||
}
|
||||
//user didn't input something already
|
||||
IGuildUser throwaway;
|
||||
if (submissions.TryGetValue(input, out throwaway))
|
||||
return;
|
||||
var inputWords = input.Split(' '); //get all words
|
||||
|
||||
if (inputWords.Length != startingLetters.Length) // number of words must be the same as the number of the starting letters
|
||||
return;
|
||||
|
||||
++spamCount;
|
||||
|
||||
var guildUser = (IGuildUser)msg.Author;
|
||||
|
||||
var input = msg.Content.ToUpperInvariant().Trim();
|
||||
|
||||
if (phase == AcroPhase.Submitting)
|
||||
for (int i = 0; i < startingLetters.Length; i++)
|
||||
{
|
||||
if (spamCount > 10)
|
||||
{
|
||||
spamCount = 0;
|
||||
try { await channel.EmbedAsync(GetEmbed().Build()).ConfigureAwait(false); }
|
||||
catch { }
|
||||
}
|
||||
//user didn't input something already
|
||||
IGuildUser throwaway;
|
||||
if (submissions.TryGetValue(input, out throwaway))
|
||||
var letter = startingLetters[i];
|
||||
|
||||
if (!inputWords[i].StartsWith(letter.ToString())) // all first letters must match
|
||||
return;
|
||||
var inputWords = input.Split(' '); //get all words
|
||||
|
||||
if (inputWords.Length != startingLetters.Length) // number of words must be the same as the number of the starting letters
|
||||
return;
|
||||
|
||||
for (int i = 0; i < startingLetters.Length; i++)
|
||||
{
|
||||
var letter = startingLetters[i];
|
||||
|
||||
if (!inputWords[i].StartsWith(letter.ToString())) // all first letters must match
|
||||
return;
|
||||
}
|
||||
|
||||
//try adding it to the list of answers
|
||||
if (!submissions.TryAdd(input, guildUser))
|
||||
return;
|
||||
|
||||
// all good. valid input. answer recorded
|
||||
await channel.SendConfirmAsync("Acrophobia", $"{guildUser.Mention} submitted their sentence. ({submissions.Count} total)");
|
||||
try
|
||||
{
|
||||
await msg.DeleteAsync();
|
||||
}
|
||||
catch
|
||||
{
|
||||
await msg.DeleteAsync(); //try twice
|
||||
}
|
||||
}
|
||||
else if (phase == AcroPhase.Voting)
|
||||
|
||||
//try adding it to the list of answers
|
||||
if (!submissions.TryAdd(input, guildUser))
|
||||
return;
|
||||
|
||||
// all good. valid input. answer recorded
|
||||
await channel.SendConfirmAsync("Acrophobia", $"{guildUser.Mention} submitted their sentence. ({submissions.Count} total)");
|
||||
try
|
||||
{
|
||||
if (spamCount > 10)
|
||||
{
|
||||
spamCount = 0;
|
||||
try { await channel.EmbedAsync(GetEmbed().Build()).ConfigureAwait(false); }
|
||||
catch { }
|
||||
}
|
||||
|
||||
IGuildUser usr;
|
||||
//if (submissions.TryGetValue(input, out usr) && usr.Id != guildUser.Id)
|
||||
//{
|
||||
// if (!usersWhoVoted.Add(guildUser.Id))
|
||||
// return;
|
||||
// votes.AddOrUpdate(input, 1, (key, old) => ++old);
|
||||
// await channel.SendConfirmAsync("Acrophobia", $"{guildUser.Mention} cast their vote!").ConfigureAwait(false);
|
||||
// await msg.DeleteAsync().ConfigureAwait(false);
|
||||
// return;
|
||||
//}
|
||||
|
||||
int num;
|
||||
if (int.TryParse(input, out num) && num > 0 && num <= submissions.Count)
|
||||
{
|
||||
var kvp = submissions.Skip(num - 1).First();
|
||||
usr = kvp.Value;
|
||||
//can't vote for yourself, can't vote multiple times
|
||||
if (usr.Id == guildUser.Id || !usersWhoVoted.Add(guildUser.Id))
|
||||
return;
|
||||
votes.AddOrUpdate(kvp.Key, 1, (key, old) => ++old);
|
||||
await channel.SendConfirmAsync("Acrophobia", $"{guildUser.Mention} cast their vote!").ConfigureAwait(false);
|
||||
await msg.DeleteAsync().ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
await msg.DeleteAsync();
|
||||
}
|
||||
catch
|
||||
{
|
||||
await msg.DeleteAsync(); //try twice
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
else if (phase == AcroPhase.Voting)
|
||||
{
|
||||
if (spamCount > 10)
|
||||
{
|
||||
spamCount = 0;
|
||||
try { await channel.EmbedAsync(GetEmbed().Build()).ConfigureAwait(false); }
|
||||
catch { }
|
||||
}
|
||||
|
||||
IGuildUser usr;
|
||||
//if (submissions.TryGetValue(input, out usr) && usr.Id != guildUser.Id)
|
||||
//{
|
||||
// if (!usersWhoVoted.Add(guildUser.Id))
|
||||
// return;
|
||||
// votes.AddOrUpdate(input, 1, (key, old) => ++old);
|
||||
// await channel.SendConfirmAsync("Acrophobia", $"{guildUser.Mention} cast their vote!").ConfigureAwait(false);
|
||||
// await msg.DeleteAsync().ConfigureAwait(false);
|
||||
// return;
|
||||
//}
|
||||
|
||||
int num;
|
||||
if (int.TryParse(input, out num) && num > 0 && num <= submissions.Count)
|
||||
{
|
||||
var kvp = submissions.Skip(num - 1).First();
|
||||
usr = kvp.Value;
|
||||
//can't vote for yourself, can't vote multiple times
|
||||
if (usr.Id == guildUser.Id || !usersWhoVoted.Add(guildUser.Id))
|
||||
return;
|
||||
votes.AddOrUpdate(kvp.Key, 1, (key, old) => ++old);
|
||||
await channel.SendConfirmAsync("Acrophobia", $"{guildUser.Mention} cast their vote!").ConfigureAwait(false);
|
||||
await msg.DeleteAsync().ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.Warn(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task End()
|
||||
@ -279,7 +282,7 @@ namespace NadekoBot.Modules.Games
|
||||
|
||||
public void EnsureStopped()
|
||||
{
|
||||
NadekoBot.Client.MessageReceived -= PotentialAcro;
|
||||
NadekoBot.Client.MessageReceived -= PotentialAcro;
|
||||
if (!source.IsCancellationRequested)
|
||||
source.Cancel();
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
using NadekoBot.Extensions;
|
||||
using NadekoBot.Services;
|
||||
using Newtonsoft.Json;
|
||||
using NLog;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
@ -43,7 +44,8 @@ namespace NadekoBot.Modules.Games.Commands.Hangman
|
||||
.Concat(data.Things)
|
||||
.ToList();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
@ -64,12 +66,14 @@ namespace NadekoBot.Modules.Games.Commands.Hangman
|
||||
default:
|
||||
return data.All[rng.Next(0, data.All.Count)];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class HangmanGame
|
||||
{
|
||||
private readonly Logger _log;
|
||||
|
||||
public IMessageChannel GameChannel { get; }
|
||||
public HashSet<char> Guesses { get; } = new HashSet<char>();
|
||||
public HangmanObject Term { get; private set; }
|
||||
@ -97,6 +101,7 @@ namespace NadekoBot.Modules.Games.Commands.Hangman
|
||||
|
||||
public HangmanGame(IMessageChannel channel, HangmanTermPool.HangmanTermType type)
|
||||
{
|
||||
_log = LogManager.GetCurrentClassLogger();
|
||||
this.GameChannel = channel;
|
||||
this.TermType = type;
|
||||
}
|
||||
@ -124,17 +129,20 @@ namespace NadekoBot.Modules.Games.Commands.Hangman
|
||||
await GameChannel.EmbedAsync(embed.WithOkColor().Build()).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private Task PotentialGuess(IMessage msg)
|
||||
private async void PotentialGuess(IMessage msg)
|
||||
{
|
||||
if (msg.Channel != GameChannel)
|
||||
return Task.CompletedTask; // message's channel has to be the same as game's
|
||||
if (msg.Content.Length != 1) // message must be 1 char long
|
||||
try
|
||||
{
|
||||
if (++MessagesSinceLastPost > 10)
|
||||
if (!(msg is IUserMessage))
|
||||
return;
|
||||
|
||||
if (msg.Channel != GameChannel)
|
||||
return; // message's channel has to be the same as game's
|
||||
if (msg.Content.Length != 1) // message must be 1 char long
|
||||
{
|
||||
MessagesSinceLastPost = 0;
|
||||
Task.Run(async () =>
|
||||
if (++MessagesSinceLastPost > 10)
|
||||
{
|
||||
MessagesSinceLastPost = 0;
|
||||
try
|
||||
{
|
||||
await GameChannel.SendConfirmAsync("Hangman Game",
|
||||
@ -142,20 +150,12 @@ namespace NadekoBot.Modules.Games.Commands.Hangman
|
||||
footer: string.Join(" ", Guesses)).ConfigureAwait(false);
|
||||
}
|
||||
catch { }
|
||||
});
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(char.IsLetter(msg.Content[0]) || char.IsDigit(msg.Content[0])))// and a letter or a digit
|
||||
return Task.CompletedTask;
|
||||
if (!(char.IsLetter(msg.Content[0]) || char.IsDigit(msg.Content[0])))// and a letter or a digit
|
||||
return;
|
||||
|
||||
var guess = char.ToUpperInvariant(msg.Content[0]);
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var guess = char.ToUpperInvariant(msg.Content[0]);
|
||||
if (Guesses.Contains(guess))
|
||||
{
|
||||
MessagesSinceLastPost = 0;
|
||||
@ -176,12 +176,16 @@ namespace NadekoBot.Modules.Games.Commands.Hangman
|
||||
{
|
||||
try { await GameChannel.SendConfirmAsync("Hangman Game", $"{msg.Author.Mention} guessed a letter `{guess}`!").ConfigureAwait(false); } catch { }
|
||||
|
||||
await End().ConfigureAwait(false);
|
||||
await End().ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
MessagesSinceLastPost = 0;
|
||||
try { await GameChannel.SendConfirmAsync("Hangman Game", $"{msg.Author.Mention} guessed a letter `{guess}`!\n" + ScrambledWord + "\n" + GetHangman(),
|
||||
footer: string.Join(" ", Guesses)).ConfigureAwait(false); } catch { }
|
||||
try
|
||||
{
|
||||
await GameChannel.SendConfirmAsync("Hangman Game", $"{msg.Author.Mention} guessed a letter `{guess}`!\n" + ScrambledWord + "\n" + GetHangman(),
|
||||
footer: string.Join(" ", Guesses)).ConfigureAwait(false);
|
||||
}
|
||||
catch { }
|
||||
|
||||
}
|
||||
else
|
||||
@ -196,22 +200,16 @@ namespace NadekoBot.Modules.Games.Commands.Hangman
|
||||
}
|
||||
|
||||
}
|
||||
catch { }
|
||||
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
catch (Exception ex) { _log.Warn(ex); }
|
||||
}
|
||||
|
||||
public string GetHangman()
|
||||
{
|
||||
return
|
||||
$@"\_\_\_\_\_\_\_\_\_
|
||||
public string GetHangman() => $@"\_\_\_\_\_\_\_\_\_
|
||||
| |
|
||||
| |
|
||||
{(Errors > 0 ? "😲" : " ")} |
|
||||
{(Errors > 1 ? "/" : " ")} {(Errors > 2 ? "|" : " ")} {(Errors > 3 ? "\\" : " ")} |
|
||||
{(Errors > 4 ? "/" : " ")} {(Errors > 5 ? "\\" : " ")} |
|
||||
/-\";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -51,27 +51,27 @@ namespace NadekoBot.Modules.Games
|
||||
var conf = uow.BotConfig.GetOrCreate();
|
||||
var x =
|
||||
generationChannels = new ConcurrentHashSet<ulong>(NadekoBot.AllGuildConfigs
|
||||
.SelectMany(c => c.GenerateCurrencyChannelIds.Select(obj=>obj.ChannelId)));
|
||||
.SelectMany(c => c.GenerateCurrencyChannelIds.Select(obj => obj.ChannelId)));
|
||||
chance = conf.CurrencyGenerationChance;
|
||||
cooldown = conf.CurrencyGenerationCooldown;
|
||||
}
|
||||
}
|
||||
|
||||
private static Task PotentialFlowerGeneration(IMessage imsg)
|
||||
private static async void PotentialFlowerGeneration(IMessage imsg)
|
||||
{
|
||||
var msg = imsg as IUserMessage;
|
||||
if (msg == null || msg.IsAuthor() || msg.Author.IsBot)
|
||||
return Task.CompletedTask;
|
||||
|
||||
var channel = imsg.Channel as ITextChannel;
|
||||
if (channel == null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
if (!generationChannels.Contains(channel.Id))
|
||||
return Task.CompletedTask;
|
||||
|
||||
var t = Task.Run(async () =>
|
||||
try
|
||||
{
|
||||
var msg = imsg as IUserMessage;
|
||||
if (msg == null || msg.IsAuthor() || msg.Author.IsBot)
|
||||
return;
|
||||
|
||||
var channel = imsg.Channel as ITextChannel;
|
||||
if (channel == null)
|
||||
return;
|
||||
|
||||
if (!generationChannels.Contains(channel.Id))
|
||||
return;
|
||||
|
||||
var lastGeneration = lastGenerations.GetOrAdd(channel.Id, DateTime.MinValue);
|
||||
var rng = new NadekoRandom();
|
||||
|
||||
@ -83,20 +83,19 @@ namespace NadekoBot.Modules.Games
|
||||
if (num > 100)
|
||||
{
|
||||
lastGenerations.AddOrUpdate(channel.Id, DateTime.Now, (id, old) => DateTime.Now);
|
||||
try
|
||||
{
|
||||
var sent = await channel.SendFileAsync(
|
||||
GetRandomCurrencyImagePath(),
|
||||
$"❗ A random { Gambling.Gambling.CurrencyName } appeared! Pick it up by typing `{NadekoBot.ModulePrefixes[typeof(Games).Name]}pick`")
|
||||
.ConfigureAwait(false);
|
||||
plantedFlowers.AddOrUpdate(channel.Id, new List<IUserMessage>() { sent }, (id, old) => { old.Add(sent); return old; });
|
||||
}
|
||||
catch { }
|
||||
|
||||
|
||||
var sent = await channel.SendFileAsync(
|
||||
GetRandomCurrencyImagePath(),
|
||||
$"❗ A random { Gambling.Gambling.CurrencyName } appeared! Pick it up by typing `{NadekoBot.ModulePrefixes[typeof(Games).Name]}pick`")
|
||||
.ConfigureAwait(false);
|
||||
plantedFlowers.AddOrUpdate(channel.Id, new List<IUserMessage>() { sent }, (id, old) => { old.Add(sent); return old; });
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task Pick(IUserMessage imsg)
|
||||
@ -144,7 +143,7 @@ namespace NadekoBot.Modules.Games
|
||||
var file = GetRandomCurrencyImagePath();
|
||||
IUserMessage msg;
|
||||
var vowelFirst = new[] { 'a', 'e', 'i', 'o', 'u' }.Contains(Gambling.Gambling.CurrencyName[0]);
|
||||
|
||||
|
||||
var msgToSend = $"Oh how Nice! **{imsg.Author.Username}** planted {(vowelFirst ? "an" : "a")} {Gambling.Gambling.CurrencyName}. Pick it using {NadekoBot.ModulePrefixes[typeof(Games).Name]}pick";
|
||||
if (file == null)
|
||||
{
|
||||
@ -156,7 +155,7 @@ namespace NadekoBot.Modules.Games
|
||||
}
|
||||
plantedFlowers.AddOrUpdate(channel.Id, new List<IUserMessage>() { msg }, (id, old) => { old.Add(msg); return old; });
|
||||
}
|
||||
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[RequirePermission(GuildPermission.ManageMessages)]
|
||||
|
@ -124,61 +124,57 @@ namespace NadekoBot.Modules.Games
|
||||
}
|
||||
}
|
||||
|
||||
private Task Vote(IMessage imsg)
|
||||
private async void Vote(IMessage imsg)
|
||||
{
|
||||
// has to be a user message
|
||||
var msg = imsg as IUserMessage;
|
||||
if (msg == null || msg.Author.IsBot)
|
||||
return Task.CompletedTask;
|
||||
|
||||
// has to be an integer
|
||||
int vote;
|
||||
if (!int.TryParse(imsg.Content, out vote))
|
||||
return Task.CompletedTask;
|
||||
if (vote < 1 || vote > answers.Length)
|
||||
return Task.CompletedTask;
|
||||
|
||||
var t = Task.Run(async () =>
|
||||
try
|
||||
{
|
||||
try
|
||||
// has to be a user message
|
||||
var msg = imsg as IUserMessage;
|
||||
if (msg == null || msg.Author.IsBot)
|
||||
return;
|
||||
|
||||
// has to be an integer
|
||||
int vote;
|
||||
if (!int.TryParse(imsg.Content, out vote))
|
||||
return;
|
||||
if (vote < 1 || vote > answers.Length)
|
||||
return;
|
||||
|
||||
IMessageChannel ch;
|
||||
if (isPublic)
|
||||
{
|
||||
IMessageChannel ch;
|
||||
if (isPublic)
|
||||
//if public, channel must be the same the poll started in
|
||||
if (originalMessage.Channel.Id != imsg.Channel.Id)
|
||||
return;
|
||||
ch = imsg.Channel;
|
||||
}
|
||||
else
|
||||
{
|
||||
//if private, channel must be dm channel
|
||||
if ((ch = msg.Channel as IDMChannel) == null)
|
||||
return;
|
||||
|
||||
// user must be a member of the guild this poll is in
|
||||
var guildUsers = await guild.GetUsersAsync().ConfigureAwait(false);
|
||||
if (!guildUsers.Any(u => u.Id == imsg.Author.Id))
|
||||
return;
|
||||
}
|
||||
|
||||
//user can vote only once
|
||||
if (participants.TryAdd(msg.Author.Id, vote))
|
||||
{
|
||||
if (!isPublic)
|
||||
{
|
||||
//if public, channel must be the same the poll started in
|
||||
if (originalMessage.Channel.Id != imsg.Channel.Id)
|
||||
return;
|
||||
ch = imsg.Channel;
|
||||
await ch.SendConfirmAsync($"Thanks for voting **{msg.Author.Username}**.").ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
//if private, channel must be dm channel
|
||||
if ((ch = msg.Channel as IDMChannel) == null)
|
||||
return;
|
||||
|
||||
// user must be a member of the guild this poll is in
|
||||
var guildUsers = await guild.GetUsersAsync().ConfigureAwait(false);
|
||||
if (!guildUsers.Any(u => u.Id == imsg.Author.Id))
|
||||
return;
|
||||
}
|
||||
|
||||
//user can vote only once
|
||||
if (participants.TryAdd(msg.Author.Id, vote))
|
||||
{
|
||||
if (!isPublic)
|
||||
{
|
||||
await ch.SendConfirmAsync($"Thanks for voting **{msg.Author.Username}**.").ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
var toDelete = await ch.SendConfirmAsync($"{msg.Author.Mention} cast their vote.").ConfigureAwait(false);
|
||||
toDelete.DeleteAfter(5);
|
||||
}
|
||||
var toDelete = await ch.SendConfirmAsync($"{msg.Author.Mention} cast their vote.").ConfigureAwait(false);
|
||||
toDelete.DeleteAfter(5);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
@ -105,42 +105,39 @@ namespace NadekoBot.Modules.Games
|
||||
NadekoBot.Client.MessageReceived += AnswerReceived;
|
||||
}
|
||||
|
||||
private Task AnswerReceived(IMessage imsg)
|
||||
private async void AnswerReceived(IMessage imsg)
|
||||
{
|
||||
if (imsg.Author.IsBot)
|
||||
return Task.CompletedTask;
|
||||
var msg = imsg as IUserMessage;
|
||||
if (msg == null)
|
||||
return Task.CompletedTask;
|
||||
var t = Task.Run(async () =>
|
||||
try
|
||||
{
|
||||
try
|
||||
if (imsg.Author.IsBot)
|
||||
return;
|
||||
var msg = imsg as IUserMessage;
|
||||
if (msg == null)
|
||||
return;
|
||||
|
||||
if (this.Channel == null || this.Channel.Id != this.Channel.Id) return;
|
||||
|
||||
var guess = msg.Content;
|
||||
|
||||
var distance = CurrentSentence.LevenshteinDistance(guess);
|
||||
var decision = Judge(distance, guess.Length);
|
||||
if (decision && !finishedUserIds.Contains(msg.Author.Id))
|
||||
{
|
||||
if (this.Channel == null || this.Channel.Id != this.Channel.Id) return;
|
||||
|
||||
var guess = msg.Content;
|
||||
|
||||
var distance = CurrentSentence.LevenshteinDistance(guess);
|
||||
var decision = Judge(distance, guess.Length);
|
||||
if (decision && !finishedUserIds.Contains(msg.Author.Id))
|
||||
var wpm = CurrentSentence.Length / WORD_VALUE / sw.Elapsed.Seconds * 60;
|
||||
finishedUserIds.Add(msg.Author.Id);
|
||||
await Extensions.Extensions.EmbedAsync(this.Channel, (Discord.API.Embed)new EmbedBuilder().WithColor((uint)NadekoBot.OkColor)
|
||||
.WithTitle((string)$"{msg.Author} finished the race!")
|
||||
.AddField(efb => efb.WithName("Place").WithValue($"#{finishedUserIds.Count}").WithIsInline(true))
|
||||
.AddField(efb => efb.WithName("WPM").WithValue($"{wpm:F2} *[{sw.Elapsed.Seconds.ToString()}sec]*").WithIsInline(true))
|
||||
.AddField(efb => efb.WithName((string)"Errors").WithValue((string)distance.ToString()).WithIsInline((bool)true))
|
||||
.Build()).ConfigureAwait(false);
|
||||
if (finishedUserIds.Count % 4 == 0)
|
||||
{
|
||||
var wpm = CurrentSentence.Length / WORD_VALUE / sw.Elapsed.Seconds * 60;
|
||||
finishedUserIds.Add(msg.Author.Id);
|
||||
await Extensions.Extensions.EmbedAsync(this.Channel, (Discord.API.Embed)new EmbedBuilder().WithColor((uint)NadekoBot.OkColor)
|
||||
.WithTitle((string)$"{msg.Author} finished the race!")
|
||||
.AddField(efb => efb.WithName("Place").WithValue($"#{finishedUserIds.Count}").WithIsInline(true))
|
||||
.AddField(efb => efb.WithName("WPM").WithValue($"{wpm:F2} *[{sw.Elapsed.Seconds.ToString()}sec]*").WithIsInline(true))
|
||||
.AddField(efb => efb.WithName((string)"Errors").WithValue((string)distance.ToString()).WithIsInline((bool)true))
|
||||
.Build()).ConfigureAwait(false);
|
||||
if (finishedUserIds.Count % 4 == 0)
|
||||
{
|
||||
await Extensions.Extensions.SendConfirmAsync(this.Channel, (string)$":exclamation: A lot of people finished, here is the text for those still typing:\n\n**{Format.Sanitize((string)CurrentSentence.Replace((string)" ", (string)" \x200B")).SanitizeMentions()}**").ConfigureAwait(false);
|
||||
}
|
||||
await Extensions.Extensions.SendConfirmAsync(this.Channel, (string)$":exclamation: A lot of people finished, here is the text for those still typing:\n\n**{Format.Sanitize((string)CurrentSentence.Replace((string)" ", (string)" \x200B")).SanitizeMentions()}**").ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
catch (Exception ex) { _log.Warn(ex); }
|
||||
}
|
||||
|
||||
private bool Judge(int errors, int textLength) => errors <= textLength / 25;
|
||||
|
@ -142,49 +142,48 @@ namespace NadekoBot.Modules.Games.Trivia
|
||||
try { await channel.SendConfirmAsync("Trivia Game", "Stopping after this question.").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
||||
}
|
||||
|
||||
private Task PotentialGuess(IMessage imsg)
|
||||
private async void PotentialGuess(IMessage imsg)
|
||||
{
|
||||
if (imsg.Author.IsBot)
|
||||
return Task.CompletedTask;
|
||||
var umsg = imsg as IUserMessage;
|
||||
if (umsg == null)
|
||||
return Task.CompletedTask;
|
||||
var t = Task.Run(async () =>
|
||||
try
|
||||
{
|
||||
if (imsg.Author.IsBot)
|
||||
return;
|
||||
|
||||
var umsg = imsg as IUserMessage;
|
||||
if (umsg == null)
|
||||
return;
|
||||
|
||||
var textChannel = umsg.Channel as ITextChannel;
|
||||
if (textChannel == null || textChannel.Guild != guild)
|
||||
return;
|
||||
|
||||
var guildUser = (IGuildUser)umsg.Author;
|
||||
|
||||
var guess = false;
|
||||
await _guessLock.WaitAsync().ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
var textChannel = umsg.Channel as ITextChannel;
|
||||
if (textChannel == null || textChannel.Guild != guild)
|
||||
return;
|
||||
|
||||
var guildUser = (IGuildUser)umsg.Author;
|
||||
|
||||
var guess = false;
|
||||
await _guessLock.WaitAsync().ConfigureAwait(false);
|
||||
try
|
||||
if (GameActive && CurrentQuestion.IsAnswerCorrect(umsg.Content) && !triviaCancelSource.IsCancellationRequested)
|
||||
{
|
||||
if (GameActive && CurrentQuestion.IsAnswerCorrect(umsg.Content) && !triviaCancelSource.IsCancellationRequested)
|
||||
{
|
||||
Users.AddOrUpdate(guildUser, 1, (gu, old) => ++old);
|
||||
guess = true;
|
||||
}
|
||||
Users.AddOrUpdate(guildUser, 1, (gu, old) => ++old);
|
||||
guess = true;
|
||||
}
|
||||
finally { _guessLock.Release(); }
|
||||
if (!guess) return;
|
||||
triviaCancelSource.Cancel();
|
||||
|
||||
|
||||
if (Users[guildUser] == WinRequirement) {
|
||||
ShouldStopGame = true;
|
||||
await channel.SendConfirmAsync("Trivia Game", $"{guildUser.Mention} guessed it and WON the game! The answer was: **{CurrentQuestion.Answer}**").ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
await channel.SendConfirmAsync("Trivia Game", $"{guildUser.Mention} guessed it! The answer was: **{CurrentQuestion.Answer}**").ConfigureAwait(false);
|
||||
|
||||
}
|
||||
catch (Exception ex) { _log.Warn(ex); }
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
finally { _guessLock.Release(); }
|
||||
if (!guess) return;
|
||||
triviaCancelSource.Cancel();
|
||||
|
||||
|
||||
if (Users[guildUser] == WinRequirement)
|
||||
{
|
||||
ShouldStopGame = true;
|
||||
await channel.SendConfirmAsync("Trivia Game", $"{guildUser.Mention} guessed it and WON the game! The answer was: **{CurrentQuestion.Answer}**").ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
await channel.SendConfirmAsync("Trivia Game", $"{guildUser.Mention} guessed it! The answer was: **{CurrentQuestion.Answer}**").ConfigureAwait(false);
|
||||
|
||||
}
|
||||
catch (Exception ex) { _log.Warn(ex); }
|
||||
}
|
||||
|
||||
public string GetLeaderboard()
|
||||
|
@ -81,7 +81,7 @@ namespace NadekoBot.Modules.Games.Trivia
|
||||
|
||||
private static string Scramble(string word)
|
||||
{
|
||||
var letters = word.ToArray();
|
||||
var letters = word.ToCharArray();
|
||||
var count = 0;
|
||||
for (var i = 0; i < letters.Length; i++)
|
||||
{
|
||||
@ -98,7 +98,7 @@ namespace NadekoBot.Modules.Games.Trivia
|
||||
if (letters[i] != ' ')
|
||||
letters[i] = '_';
|
||||
}
|
||||
return string.Join(" ", letters);
|
||||
return string.Join(" \x200B", new string(letters).Replace(" ", " \x200B").AsEnumerable());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,16 @@ namespace NadekoBot.Modules.Music.Classes
|
||||
/// Player will prioritize different queuer name
|
||||
/// over the song position in the playlist
|
||||
/// </summary>
|
||||
public bool FairPlay { get; set; } = true;
|
||||
public bool FairPlay { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Song will stop playing after this amount of time.
|
||||
/// To prevent people queueing radio or looped songs
|
||||
/// while other people want to listen to other songs too.
|
||||
/// </summary>
|
||||
public uint MaxPlaytimeSeconds { get; set; } = 0;
|
||||
|
||||
public TimeSpan TotalPlaytime => new TimeSpan(playlist.Sum(s => s.TotalTime.Ticks));
|
||||
|
||||
/// <summary>
|
||||
/// Users who recently got their music wish
|
||||
@ -64,7 +73,9 @@ namespace NadekoBot.Modules.Music.Classes
|
||||
public bool Autoplay { get; set; } = false;
|
||||
public uint MaxQueueSize { get; set; } = 0;
|
||||
|
||||
private ConcurrentQueue<Action> actionQueue { get; set; } = new ConcurrentQueue<Action>();
|
||||
private ConcurrentQueue<Action> actionQueue { get; } = new ConcurrentQueue<Action>();
|
||||
|
||||
public string PrettyVolume => $"🔉 {(int)(Volume * 100)}%";
|
||||
|
||||
public MusicPlayer(IVoiceChannel startingVoiceChannel, float? defaultVolume)
|
||||
{
|
||||
|
@ -47,29 +47,11 @@ namespace NadekoBot.Modules.Music.Classes
|
||||
|
||||
public string PrettyFullTime => PrettyCurrentTime + " / " + PrettyTotalTime;
|
||||
|
||||
//public string PrettyName => $"**[{SongInfo.Title.TrimTo(70)}]({SongInfo.Query})**";
|
||||
|
||||
public string PrettyName {
|
||||
get {
|
||||
switch (SongInfo.ProviderType)
|
||||
{
|
||||
case MusicType.Normal:
|
||||
return $"**[{SongInfo.Title.TrimTo(70)}]({SongInfo.Query})**";
|
||||
case MusicType.Soundcloud:
|
||||
return $"**[{SongInfo.Title.TrimTo(70)}]({SongInfo.Query})**";
|
||||
case MusicType.Local:
|
||||
return $"**{SongInfo.Title.TrimTo(70)}**";
|
||||
case MusicType.Radio:
|
||||
return $"**{SongInfo.Title.TrimTo(70)}**";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
public string PrettyName => $"**[{SongInfo.Title.TrimTo(65)}]({songUrl})**";
|
||||
|
||||
public string PrettyInfo => $"{PrettyTotalTime} | {PrettyProvider} | {QueuerName}";
|
||||
public string PrettyInfo => $"{MusicPlayer.PrettyVolume} | {PrettyTotalTime} | {PrettyProvider} | {QueuerName}";
|
||||
|
||||
public string PrettyFullName => $"{PrettyName}\n\t\t*{PrettyInfo}*";
|
||||
public string PrettyFullName => $"{PrettyName}\n\t\t`{PrettyTotalTime} | {PrettyProvider} | {QueuerName}`";
|
||||
|
||||
public string PrettyCurrentTime => CurrentTime.ToString(@"mm\:ss");
|
||||
|
||||
@ -86,36 +68,36 @@ namespace NadekoBot.Modules.Music.Classes
|
||||
|
||||
public string Thumbnail {
|
||||
get {
|
||||
switch (SongInfo.Provider)
|
||||
switch (SongInfo.ProviderType)
|
||||
{
|
||||
case "YouTube":
|
||||
case MusicType.Radio:
|
||||
//todo have videoid in songinfo from the start
|
||||
var videoId = Regex.Match(SongInfo.Query, "<=v=[a-zA-Z0-9-]+(?=&)|(?<=[0-9])[^&\n]+|(?<=v=)[^&\n]+");
|
||||
return $"https://img.youtube.com/vi/{ videoId }/0.jpg";
|
||||
case "SoundCloud":
|
||||
return SongInfo.AlbumArt;
|
||||
case "Local File":
|
||||
return $"https://cdn.discordapp.com/attachments/155726317222887425/261850914783100928/1482522077_music.png"; //test links
|
||||
case "Radio Stream":
|
||||
return $"https://cdn.discordapp.com/attachments/155726317222887425/261850925063340032/1482522097_radio.png"; //test links
|
||||
default:
|
||||
case MusicType.Normal:
|
||||
return $"https://cdn.discordapp.com/attachments/155726317222887425/261850925063340032/1482522097_radio.png"; //test links
|
||||
case MusicType.Local:
|
||||
return $"https://cdn.discordapp.com/attachments/155726317222887425/261850914783100928/1482522077_music.png"; //test links
|
||||
case MusicType.Soundcloud:
|
||||
return SongInfo.AlbumArt;
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string songURL {
|
||||
|
||||
private string songUrl {
|
||||
get {
|
||||
switch (SongInfo.ProviderType)
|
||||
{
|
||||
case MusicType.Normal:
|
||||
return SongInfo.Query;
|
||||
case MusicType.Soundcloud:
|
||||
return SongInfo.Query;
|
||||
return SongInfo.Query;
|
||||
case MusicType.Local:
|
||||
return $"https://google.com/search?q={ WebUtility.UrlEncode(SongInfo.Title).Replace(' ', '+') }";
|
||||
return $"https://google.com/search?q={ WebUtility.UrlEncode(SongInfo.Title).Replace(' ', '+') }";
|
||||
case MusicType.Radio:
|
||||
return $"https://google.com/search?q={SongInfo.Title}";
|
||||
return $"https://google.com/search?q={SongInfo.Title}";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
@ -143,7 +125,7 @@ namespace NadekoBot.Modules.Music.Classes
|
||||
{
|
||||
var s = new Song(SongInfo);
|
||||
s.MusicPlayer = MusicPlayer;
|
||||
s.QueuerName = QueuerName;
|
||||
s.QueuerName = QueuerName;
|
||||
return s;
|
||||
}
|
||||
|
||||
@ -203,7 +185,8 @@ namespace NadekoBot.Modules.Music.Classes
|
||||
int nextTime = Environment.TickCount + milliseconds;
|
||||
|
||||
byte[] buffer = new byte[frameBytes];
|
||||
while (!cancelToken.IsCancellationRequested)
|
||||
while (!cancelToken.IsCancellationRequested && //song canceled for whatever reason
|
||||
!(MusicPlayer.MaxPlaytimeSeconds != 0 && CurrentTime.TotalSeconds >= MusicPlayer.MaxPlaytimeSeconds)) // or exceedded max playtime
|
||||
{
|
||||
//Console.WriteLine($"Read: {songBuffer.ReadPosition}\nWrite: {songBuffer.WritePosition}\nContentLength:{songBuffer.ContentLength}\n---------");
|
||||
var read = await inStream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
|
||||
|
@ -36,17 +36,15 @@ namespace NadekoBot.Modules.Music
|
||||
Directory.CreateDirectory(MusicDataPath);
|
||||
}
|
||||
|
||||
private Task Client_UserVoiceStateUpdated(IUser iusr, IVoiceState oldState, IVoiceState newState)
|
||||
private void Client_UserVoiceStateUpdated(IUser iusr, IVoiceState oldState, IVoiceState newState)
|
||||
{
|
||||
var usr = iusr as IGuildUser;
|
||||
if (usr == null ||
|
||||
oldState.VoiceChannel == newState.VoiceChannel)
|
||||
return Task.CompletedTask;
|
||||
|
||||
return;
|
||||
MusicPlayer player;
|
||||
if (!MusicPlayers.TryGetValue(usr.Guild.Id, out player))
|
||||
return Task.CompletedTask;
|
||||
|
||||
return;
|
||||
if ((player.PlaybackVoiceChannel == newState.VoiceChannel && //if joined first, and player paused, unpause
|
||||
player.Paused &&
|
||||
player.PlaybackVoiceChannel.GetUsers().Count == 2) || // keep in mind bot is in the channel (+1)
|
||||
@ -56,7 +54,7 @@ namespace NadekoBot.Modules.Music
|
||||
{
|
||||
player.TogglePause();
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
@ -193,6 +191,8 @@ namespace NadekoBot.Modules.Music
|
||||
int startAt = itemsPerPage * (page - 1);
|
||||
var number = 0 + startAt;
|
||||
|
||||
var total = musicPlayer.TotalPlaytime;
|
||||
var maxPlaytime = musicPlayer.MaxPlaytimeSeconds;
|
||||
var embed = new EmbedBuilder()
|
||||
.WithAuthor(eab => eab.WithName($"Player Queue - Page {page}")
|
||||
.WithMusicIcon())
|
||||
@ -200,7 +200,9 @@ namespace NadekoBot.Modules.Music
|
||||
.Skip(startAt)
|
||||
.Take(10)
|
||||
.Select(v => $"`{++number}.` {v.PrettyFullName}")))
|
||||
.WithFooter(ef => ef.WithText($"{musicPlayer.Playlist.Count} tracks currently queued."))
|
||||
.WithFooter(ef => ef.WithText($"{musicPlayer.PrettyVolume} | {musicPlayer.Playlist.Count} " +
|
||||
$"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {total.Minutes}m {total.Seconds}s | " +
|
||||
(musicPlayer.FairPlay? "✔️fairplay" : "✖️fairplay") + $" | " + (maxPlaytime == 0 ? "unlimited" : $"{maxPlaytime}s limit")))
|
||||
.WithOkColor();
|
||||
|
||||
if (musicPlayer.RepeatSong)
|
||||
@ -232,15 +234,12 @@ namespace NadekoBot.Modules.Music
|
||||
return;
|
||||
try { await musicPlayer.UpdateSongDurationsAsync().ConfigureAwait(false); } catch { }
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
.WithAuthor(eab => eab.WithName("Now Playing")
|
||||
.WithMusicIcon())
|
||||
.WithTitle(currentSong.SongInfo.Title)
|
||||
.WithDescription(currentSong.PrettyFullTime)
|
||||
.WithFooter(ef => ef.WithText($"{currentSong.PrettyProvider} | {currentSong.QueuerName}"))
|
||||
.WithOkColor()
|
||||
.WithThumbnail(tn => tn.Url = currentSong.Thumbnail)
|
||||
.WithUrl(currentSong.songURL);
|
||||
var embed = new EmbedBuilder().WithOkColor()
|
||||
.WithAuthor(eab => eab.WithName("Now Playing").WithMusicIcon())
|
||||
.WithDescription(currentSong.PrettyName)
|
||||
.WithThumbnail(tn => tn.Url = currentSong.Thumbnail)
|
||||
.WithFooter(ef => ef.WithText(musicPlayer.PrettyVolume + " | " + currentSong.PrettyFullTime + $" | {currentSong.PrettyProvider} | {currentSong.QueuerName}"));
|
||||
|
||||
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@ -327,28 +326,28 @@ namespace NadekoBot.Modules.Music
|
||||
var count = ids.Count();
|
||||
|
||||
var msg = await channel.SendMessageAsync($"🎵 Attempting to queue **{count}** songs".SnPl(count) + "...").ConfigureAwait(false);
|
||||
|
||||
var cancelSource = new CancellationTokenSource();
|
||||
|
||||
var cancelSource = new CancellationTokenSource();
|
||||
|
||||
var gusr = (IGuildUser)umsg.Author;
|
||||
|
||||
while (ids.Any() && !cancelSource.IsCancellationRequested)
|
||||
|
||||
while (ids.Any() && !cancelSource.IsCancellationRequested)
|
||||
{
|
||||
var tasks = Task.WhenAll(ids.Take(5).Select(async id =>
|
||||
{
|
||||
if (cancelSource.Token.IsCancellationRequested)
|
||||
return;
|
||||
try
|
||||
{
|
||||
await QueueSong(gusr, channel, gusr.VoiceChannel, id, true).ConfigureAwait(false);
|
||||
}
|
||||
catch (SongNotFoundException) { }
|
||||
catch { try { cancelSource.Cancel(); } catch { } }
|
||||
}));
|
||||
return;
|
||||
try
|
||||
{
|
||||
await QueueSong(gusr, channel, gusr.VoiceChannel, id, true).ConfigureAwait(false);
|
||||
}
|
||||
catch (SongNotFoundException) { }
|
||||
catch { try { cancelSource.Cancel(); } catch { } }
|
||||
}));
|
||||
|
||||
await Task.WhenAny(tasks, Task.Delay(Timeout.Infinite, cancelSource.Token));
|
||||
ids = ids.Skip(5);
|
||||
}
|
||||
await Task.WhenAny(tasks, Task.Delay(Timeout.Infinite, cancelSource.Token));
|
||||
ids = ids.Skip(5);
|
||||
}
|
||||
|
||||
await msg.ModifyAsync(m => m.Content = "✅ Playlist queue complete.").ConfigureAwait(false);
|
||||
}
|
||||
@ -404,7 +403,7 @@ namespace NadekoBot.Modules.Music
|
||||
var dir = new DirectoryInfo(arg);
|
||||
var fileEnum = dir.GetFiles("*", SearchOption.AllDirectories)
|
||||
.Where(x => !x.Attributes.HasFlag(FileAttributes.Hidden | FileAttributes.System));
|
||||
var gusr = (IGuildUser)umsg.Author;
|
||||
var gusr = (IGuildUser)umsg.Author;
|
||||
foreach (var file in fileEnum)
|
||||
{
|
||||
try
|
||||
@ -488,7 +487,7 @@ namespace NadekoBot.Modules.Music
|
||||
.AddField(fb => fb.WithName("**Song Position**").WithValue($"#{num}").WithIsInline(true))
|
||||
.AddField(fb => fb.WithName("**Song Name**").WithValue(song.PrettyName).WithIsInline(true))
|
||||
.WithFooter(ef => ef.WithText($"{song.PrettyProvider} | {song.QueuerName}"))
|
||||
.WithErrorColor();
|
||||
.WithErrorColor();
|
||||
|
||||
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
|
||||
}
|
||||
@ -546,7 +545,7 @@ namespace NadekoBot.Modules.Music
|
||||
.WithAuthor(eab => eab.WithName("Song Moved").WithMusicIcon())
|
||||
.AddField(fb => fb.WithName("**From Position**").WithValue($"#{n1}").WithIsInline(true))
|
||||
.AddField(fb => fb.WithName("**To Position**").WithValue($"#{n2}").WithIsInline(true))
|
||||
.WithFooter(ef => ef.WithText($"{s.PrettyProvider} | {s.QueuerName}"))
|
||||
.WithFooter(ef => ef.WithText($"{s.PrettyProvider} | {s.QueuerName}"))
|
||||
.WithOkColor();
|
||||
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
|
||||
}
|
||||
@ -558,13 +557,29 @@ namespace NadekoBot.Modules.Music
|
||||
var channel = (ITextChannel)umsg.Channel;
|
||||
MusicPlayer musicPlayer;
|
||||
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer))
|
||||
{
|
||||
return;
|
||||
}
|
||||
musicPlayer.MaxQueueSize = size;
|
||||
await channel.SendConfirmAsync($"🎵 Max queue set to {(size == 0 ? ("unlimited") : size + " tracks")}.");
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task SetMaxPlaytime(IUserMessage imsg, uint seconds)
|
||||
{
|
||||
if (seconds < 15 && seconds != 0)
|
||||
return;
|
||||
|
||||
var channel = (ITextChannel)imsg.Channel;
|
||||
MusicPlayer musicPlayer;
|
||||
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer))
|
||||
return;
|
||||
musicPlayer.MaxPlaytimeSeconds = seconds;
|
||||
if(seconds == 0)
|
||||
await channel.SendConfirmAsync($"🎵 Max playtime has no limit now.");
|
||||
else
|
||||
await channel.SendConfirmAsync($"🎵 Max playtime set to {seconds} seconds.");
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task ReptCurSong(IUserMessage umsg)
|
||||
@ -583,7 +598,7 @@ namespace NadekoBot.Modules.Music
|
||||
.WithOkColor()
|
||||
.WithAuthor(eab => eab.WithMusicIcon().WithName("🔂 Repeating track"))
|
||||
.WithDescription(currentSong.PrettyName)
|
||||
.WithFooter(ef => ef.WithText(currentSong.PrettyInfo))
|
||||
.WithFooter(ef => ef.WithText(currentSong.PrettyInfo))
|
||||
.Build()).ConfigureAwait(false);
|
||||
else
|
||||
await channel.SendConfirmAsync($"🔂 Current track repeat stopped.")
|
||||
@ -658,9 +673,9 @@ namespace NadekoBot.Modules.Music
|
||||
}
|
||||
IUserMessage msg = null;
|
||||
try { msg = await channel.SendMessageAsync($"🎶 Attempting to load **{mpl.Songs.Count}** songs...").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
||||
|
||||
var usr = (IGuildUser)umsg.Author;
|
||||
foreach (var item in mpl.Songs)
|
||||
|
||||
var usr = (IGuildUser)umsg.Author;
|
||||
foreach (var item in mpl.Songs)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -815,7 +830,7 @@ namespace NadekoBot.Modules.Music
|
||||
{
|
||||
if (finishedMessage != null)
|
||||
finishedMessage.DeleteAfter(0);
|
||||
|
||||
|
||||
finishedMessage = await textCh.EmbedAsync(new EmbedBuilder().WithOkColor()
|
||||
.WithAuthor(eab => eab.WithName("Finished Song").WithMusicIcon())
|
||||
.WithDescription(song.PrettyName)
|
||||
@ -831,13 +846,13 @@ namespace NadekoBot.Modules.Music
|
||||
catch { }
|
||||
};
|
||||
IUserMessage playingMessage = null;
|
||||
|
||||
|
||||
mp.OnStarted += async (player, song) =>
|
||||
{
|
||||
try { await mp.UpdateSongDurationsAsync().ConfigureAwait(false); } catch { }
|
||||
var sender = player as MusicPlayer;
|
||||
if (sender == null)
|
||||
return;
|
||||
return;
|
||||
try
|
||||
{
|
||||
if (playingMessage != null)
|
||||
@ -846,7 +861,7 @@ namespace NadekoBot.Modules.Music
|
||||
playingMessage = await textCh.EmbedAsync(new EmbedBuilder().WithOkColor()
|
||||
.WithAuthor(eab => eab.WithName("Playing Song").WithMusicIcon())
|
||||
.WithDescription(song.PrettyName)
|
||||
.WithFooter(ef => ef.WithText($"🔉 {(int)(sender.Volume * 100)}% | {song.PrettyInfo}"))
|
||||
.WithFooter(ef => ef.WithText(song.PrettyInfo))
|
||||
.Build())
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
@ -886,7 +901,7 @@ namespace NadekoBot.Modules.Music
|
||||
}
|
||||
catch (PlaylistFullException)
|
||||
{
|
||||
try { await textCh.SendConfirmAsync($"🎵 Queue is full at **{musicPlayer.MaxQueueSize}/{musicPlayer.MaxQueueSize}**. "); } catch { }
|
||||
try { await textCh.SendConfirmAsync($"🎵 Queue is full at **{musicPlayer.MaxQueueSize}/{musicPlayer.MaxQueueSize}**."); } catch { }
|
||||
throw;
|
||||
}
|
||||
if (!silent)
|
||||
@ -895,9 +910,9 @@ namespace NadekoBot.Modules.Music
|
||||
{
|
||||
//var queuedMessage = await textCh.SendConfirmAsync($"🎵 Queued **{resolvedSong.SongInfo.Title}** at `#{musicPlayer.Playlist.Count + 1}`").ConfigureAwait(false);
|
||||
var queuedMessage = await textCh.EmbedAsync(new EmbedBuilder().WithOkColor()
|
||||
.WithAuthor(eab => eab.WithName("Queued Song").WithMusicIcon())
|
||||
.WithDescription($"{resolvedSong.PrettyName}\nQueue #{musicPlayer.Playlist.Count + 1}")
|
||||
.WithThumbnail(tn => tn.Url = resolvedSong.Thumbnail)
|
||||
.WithAuthor(eab => eab.WithName("Queued Song #" + (musicPlayer.Playlist.Count + 1)).WithMusicIcon())
|
||||
.WithDescription($"{resolvedSong.PrettyName}\nQueue ")
|
||||
.WithThumbnail(tn => tn.Url = resolvedSong.Thumbnail)
|
||||
.WithFooter(ef => ef.WithText(resolvedSong.PrettyProvider))
|
||||
.Build())
|
||||
.ConfigureAwait(false);
|
||||
|
@ -10,6 +10,7 @@ using System.Net.Http;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml.Linq;
|
||||
using NadekoBot.Extensions;
|
||||
using System.Xml;
|
||||
|
||||
namespace NadekoBot.Modules.NSFW
|
||||
{
|
||||
@ -32,7 +33,7 @@ namespace NadekoBot.Modules.NSFW
|
||||
|
||||
var rng = new NadekoRandom();
|
||||
Task<string> provider = Task.FromResult("");
|
||||
switch (rng.Next(0,4))
|
||||
switch (rng.Next(0, 4))
|
||||
{
|
||||
case 0:
|
||||
provider = GetDanbooruImageLink(tag);
|
||||
@ -56,6 +57,7 @@ namespace NadekoBot.Modules.NSFW
|
||||
await channel.SendMessageAsync(link).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task HentaiBomb(IUserMessage umsg, [Remainder] string tag = null)
|
||||
@ -65,7 +67,7 @@ namespace NadekoBot.Modules.NSFW
|
||||
tag = tag?.Trim() ?? "";
|
||||
tag = "rating%3Aexplicit+" + tag;
|
||||
|
||||
var links = await Task.WhenAll(GetGelbooruImageLink(tag),
|
||||
var links = await Task.WhenAll(GetGelbooruImageLink(tag),
|
||||
GetDanbooruImageLink(tag),
|
||||
GetKonachanImageLink(tag),
|
||||
GetYandereImageLink(tag)).ConfigureAwait(false);
|
||||
@ -78,39 +80,7 @@ namespace NadekoBot.Modules.NSFW
|
||||
|
||||
await channel.SendMessageAsync(String.Join("\n\n", links)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public static async Task<string> GetYandereImageLink(string tag)
|
||||
{
|
||||
var rng = new NadekoRandom();
|
||||
var url =
|
||||
$"https://yande.re/post.xml?" +
|
||||
$"limit=25" +
|
||||
$"&page={rng.Next(0, 15)}" +
|
||||
$"&tags={tag.Replace(" ", "_")}";
|
||||
using (var http = new HttpClient())
|
||||
{
|
||||
var webpage = await http.GetStringAsync(url).ConfigureAwait(false);
|
||||
var matches = Regex.Matches(webpage, "file_url=\"(?<url>.*?)\"");
|
||||
//var rating = Regex.Matches(webpage, "rating=\"(?<rate>.*?)\"");
|
||||
if (matches.Count == 0)
|
||||
return null;
|
||||
return matches[rng.Next(0, matches.Count)].Groups["url"].Value;
|
||||
}
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task Yandere(IUserMessage umsg, [Remainder] string tag = null)
|
||||
{
|
||||
var channel = (ITextChannel)umsg.Channel;
|
||||
|
||||
tag = tag?.Trim() ?? "";
|
||||
var link = await GetYandereImageLink(tag).ConfigureAwait(false);
|
||||
if (string.IsNullOrWhiteSpace(link))
|
||||
await channel.SendErrorAsync("No results found.").ConfigureAwait(false);
|
||||
else
|
||||
await channel.SendMessageAsync(link).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
@ -119,54 +89,38 @@ namespace NadekoBot.Modules.NSFW
|
||||
var channel = (ITextChannel)umsg.Channel;
|
||||
|
||||
tag = tag?.Trim() ?? "";
|
||||
var link = await GetDanbooruImageLink(tag).ConfigureAwait(false);
|
||||
if (string.IsNullOrWhiteSpace(link))
|
||||
await channel.SendErrorAsync("No results found.").ConfigureAwait(false);
|
||||
|
||||
var url = await GetDanbooruImageLink(tag).ConfigureAwait(false);
|
||||
|
||||
if (url == null)
|
||||
await channel.SendErrorAsync(umsg.Author.Mention + " No results.");
|
||||
else
|
||||
await channel.SendMessageAsync(link).ConfigureAwait(false);
|
||||
await channel.EmbedAsync(new EmbedBuilder().WithOkColor()
|
||||
.WithDescription(umsg.Author.Mention + " " + tag)
|
||||
.WithImageUrl(url)
|
||||
.WithFooter(efb => efb.WithText("Danbooru"))
|
||||
.Build()).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task Konachan(IUserMessage umsg, [Remainder] string tag = null)
|
||||
{
|
||||
var channel = (ITextChannel)umsg.Channel;
|
||||
|
||||
tag = tag?.Trim() ?? "";
|
||||
var link = await GetKonachanImageLink(tag).ConfigureAwait(false);
|
||||
if (string.IsNullOrWhiteSpace(link))
|
||||
await channel.SendErrorAsync("No results found.").ConfigureAwait(false);
|
||||
else
|
||||
await channel.SendMessageAsync(link).ConfigureAwait(false);
|
||||
}
|
||||
public Task Yandere(IUserMessage umsg, [Remainder] string tag = null)
|
||||
=> Searches.Searches.InternalDapiSearch(tag, Searches.Searches.DapiSearchType.Yandere);
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task Gelbooru(IUserMessage umsg, [Remainder] string tag = null)
|
||||
{
|
||||
var channel = (ITextChannel)umsg.Channel;
|
||||
|
||||
tag = tag?.Trim() ?? "";
|
||||
var link = await GetGelbooruImageLink(tag).ConfigureAwait(false);
|
||||
if (string.IsNullOrWhiteSpace(link))
|
||||
await channel.SendErrorAsync("No results found.").ConfigureAwait(false);
|
||||
else
|
||||
await channel.SendMessageAsync(link).ConfigureAwait(false);
|
||||
}
|
||||
public Task Konachan(IUserMessage umsg, [Remainder] string tag = null)
|
||||
=> Searches.Searches.InternalDapiCommand(umsg, tag, Searches.Searches.DapiSearchType.Konachan);
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task Rule34(IUserMessage umsg, [Remainder] string tag = null)
|
||||
{
|
||||
var channel = (ITextChannel)umsg.Channel;
|
||||
public Task Gelbooru(IUserMessage umsg, [Remainder] string tag = null)
|
||||
=> Searches.Searches.InternalDapiCommand(umsg, tag, Searches.Searches.DapiSearchType.Gelbooru);
|
||||
|
||||
tag = tag?.Trim() ?? "";
|
||||
var link = await GetRule34ImageLink(tag).ConfigureAwait(false);
|
||||
if (string.IsNullOrWhiteSpace(link))
|
||||
await channel.SendErrorAsync("No results found.").ConfigureAwait(false);
|
||||
else
|
||||
await channel.SendMessageAsync(link).ConfigureAwait(false);
|
||||
}
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public Task Rule34(IUserMessage umsg, [Remainder] string tag = null)
|
||||
=> Searches.Searches.InternalDapiCommand(umsg, tag, Searches.Searches.DapiSearchType.Rule34);
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
@ -175,11 +129,17 @@ namespace NadekoBot.Modules.NSFW
|
||||
var channel = (ITextChannel)umsg.Channel;
|
||||
|
||||
tag = tag?.Trim() ?? "";
|
||||
var link = await GetE621ImageLink(tag).ConfigureAwait(false);
|
||||
if (string.IsNullOrWhiteSpace(link))
|
||||
await channel.SendErrorAsync("No results found.").ConfigureAwait(false);
|
||||
|
||||
var url = await GetE621ImageLink(tag).ConfigureAwait(false);
|
||||
|
||||
if (url == null)
|
||||
await channel.SendErrorAsync(umsg.Author.Mention + " No results.");
|
||||
else
|
||||
await channel.SendMessageAsync(link).ConfigureAwait(false);
|
||||
await channel.EmbedAsync(new EmbedBuilder().WithOkColor()
|
||||
.WithDescription(umsg.Author.Mention + " " + tag)
|
||||
.WithImageUrl(url)
|
||||
.WithFooter(efb => efb.WithText("e621"))
|
||||
.Build()).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
@ -232,99 +192,61 @@ namespace NadekoBot.Modules.NSFW
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<string> GetKonachanImageLink(string tag)
|
||||
{
|
||||
var rng = new NadekoRandom();
|
||||
|
||||
var link = $"http://konachan.com/post?" +
|
||||
$"page={rng.Next(0, 5)}";
|
||||
if (!string.IsNullOrWhiteSpace(tag))
|
||||
link += $"&tags={tag.Replace(" ", "_")}";
|
||||
using (var http = new HttpClient())
|
||||
{
|
||||
var webpage = await http.GetStringAsync(link).ConfigureAwait(false);
|
||||
var matches = Regex.Matches(webpage, "<a class=\"directlink largeimg\" href=\"(?<ll>.*?)\">");
|
||||
|
||||
if (matches.Count == 0)
|
||||
return null;
|
||||
return "http:" + matches[rng.Next(0, matches.Count)].Groups["ll"].Value;
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<string> GetDanbooruImageLink(string tag)
|
||||
{
|
||||
var rng = new NadekoRandom();
|
||||
|
||||
if (tag == "loli") //loli doesn't work for some reason atm
|
||||
tag = "flat_chest";
|
||||
|
||||
var link = $"http://danbooru.donmai.us/posts?" +
|
||||
$"page={rng.Next(0, 15)}";
|
||||
if (!string.IsNullOrWhiteSpace(tag))
|
||||
link += $"&tags={tag.Replace(" ", "_")}";
|
||||
using (var http = new HttpClient())
|
||||
{
|
||||
var webpage = await http.GetStringAsync(link).ConfigureAwait(false);
|
||||
var matches = Regex.Matches(webpage, "data-large-file-url=\"(?<id>.*?)\"");
|
||||
|
||||
if (matches.Count == 0)
|
||||
return null;
|
||||
return $"http://danbooru.donmai.us" +
|
||||
$"{matches[rng.Next(0, matches.Count)].Groups["id"].Value}";
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<string> GetGelbooruImageLink(string tag)
|
||||
{
|
||||
using (var http = new HttpClient())
|
||||
{
|
||||
http.AddFakeHeaders();
|
||||
|
||||
var webpage = await http.GetStringAsync("http://gelbooru.com/index.php?page=dapi&s=post&q=index&limit=100&tags="+ tag.Replace(" ", "_")).ConfigureAwait(false);
|
||||
var matches = Regex.Matches(webpage, "file_url=\"(?<url>.*?)\"");
|
||||
if (matches.Count == 0)
|
||||
return null;
|
||||
|
||||
var rng = new NadekoRandom();
|
||||
var match = matches[rng.Next(0, matches.Count)];
|
||||
return matches[rng.Next(0, matches.Count)].Groups["url"].Value;
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<string> GetRule34ImageLink(string tag)
|
||||
{
|
||||
var rng = new NadekoRandom();
|
||||
var url =
|
||||
$"http://rule34.xxx/index.php?page=dapi&s=post&q=index&limit=100&tags={tag.Replace(" ", "_")}";
|
||||
using (var http = new HttpClient())
|
||||
{
|
||||
var webpage = await http.GetStringAsync(url).ConfigureAwait(false);
|
||||
var matches = Regex.Matches(webpage, "file_url=\"(?<url>.*?)\"");
|
||||
if (matches.Count == 0)
|
||||
return null;
|
||||
var match = matches[rng.Next(0, matches.Count)];
|
||||
return "http:" + matches[rng.Next(0, matches.Count)].Groups["url"].Value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static async Task<string> GetE621ImageLink(string tags)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var http = new HttpClient())
|
||||
{
|
||||
http.AddFakeHeaders();
|
||||
var data = await http.GetStreamAsync("http://e621.net/post/index.xml?tags=" + Uri.EscapeUriString(tags) + "%20order:random&limit=1");
|
||||
var doc = XDocument.Load(data);
|
||||
return doc.Descendants("file_url").FirstOrDefault().Value;
|
||||
var data = await http.GetStreamAsync("https://danbooru.donmai.us/posts.xml?limit=100&tags=" + tag);
|
||||
var doc = new XmlDocument();
|
||||
doc.Load(data);
|
||||
var nodes = doc.GetElementsByTagName("file-url");
|
||||
|
||||
var node = nodes[new NadekoRandom().Next(0, nodes.Count)];
|
||||
return "https://danbooru.donmai.us" + node.InnerText;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch
|
||||
{
|
||||
Console.WriteLine("Error in e621 search: \n" + ex);
|
||||
return "Error, do you have too many tags?";
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static async Task<string> GetE621ImageLink(string tag)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var http = new HttpClient())
|
||||
{
|
||||
http.AddFakeHeaders();
|
||||
var data = await http.GetStreamAsync("http://e621.net/post/index.xml?tags=" + tag);
|
||||
var doc = new XmlDocument();
|
||||
doc.Load(data);
|
||||
var nodes = doc.GetElementsByTagName("file_url");
|
||||
|
||||
var node = nodes[new NadekoRandom().Next(0, nodes.Count)];
|
||||
return node.InnerText;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Task<string> GetYandereImageLink(string tag) =>
|
||||
Searches.Searches.InternalDapiSearch(tag, Searches.Searches.DapiSearchType.Yandere);
|
||||
|
||||
public static Task<string> GetKonachanImageLink(string tag) =>
|
||||
Searches.Searches.InternalDapiSearch(tag, Searches.Searches.DapiSearchType.Konachan);
|
||||
|
||||
public static Task<string> GetGelbooruImageLink(string tag) =>
|
||||
Searches.Searches.InternalDapiSearch(tag, Searches.Searches.DapiSearchType.Gelbooru);
|
||||
|
||||
public static Task<string> GetRule34ImageLink(string tag) =>
|
||||
Searches.Searches.InternalDapiSearch(tag, Searches.Searches.DapiSearchType.Rule34);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NadekoBot.Modules.Searches.Commands.Models
|
||||
{
|
||||
public class Audio
|
||||
{
|
||||
public string url { get; set; }
|
||||
}
|
||||
|
||||
public class Example
|
||||
{
|
||||
public List<Audio> audio { get; set; }
|
||||
public string text { get; set; }
|
||||
}
|
||||
|
||||
public class GramaticalInfo
|
||||
{
|
||||
public string type { get; set; }
|
||||
}
|
||||
|
||||
public class Sens
|
||||
{
|
||||
public object Definition { get; set; }
|
||||
public List<Example> Examples { get; set; }
|
||||
public GramaticalInfo Gramatical_info { get; set; }
|
||||
}
|
||||
|
||||
public class Result
|
||||
{
|
||||
public string Part_of_speech { get; set; }
|
||||
public List<Sens> Senses { get; set; }
|
||||
public string Url { get; set; }
|
||||
}
|
||||
|
||||
public class DefineModel
|
||||
{
|
||||
public List<Result> Results { get; set; }
|
||||
}
|
||||
}
|
@ -28,18 +28,17 @@ namespace NadekoBot.Modules.Searches
|
||||
TranslatedChannels = new ConcurrentDictionary<ulong, bool>();
|
||||
UserLanguages = new ConcurrentDictionary<UserChannelPair, string>();
|
||||
|
||||
NadekoBot.Client.MessageReceived += (msg) =>
|
||||
NadekoBot.Client.MessageReceived += async (msg) =>
|
||||
{
|
||||
var umsg = msg as IUserMessage;
|
||||
if(umsg == null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
bool autoDelete;
|
||||
if (!TranslatedChannels.TryGetValue(umsg.Channel.Id, out autoDelete))
|
||||
return Task.CompletedTask;
|
||||
|
||||
var t = Task.Run(async () =>
|
||||
try
|
||||
{
|
||||
var umsg = msg as IUserMessage;
|
||||
if (umsg == null)
|
||||
return;
|
||||
|
||||
bool autoDelete;
|
||||
if (!TranslatedChannels.TryGetValue(umsg.Channel.Id, out autoDelete))
|
||||
return;
|
||||
var key = new UserChannelPair()
|
||||
{
|
||||
UserId = umsg.Author.Id,
|
||||
@ -50,18 +49,13 @@ namespace NadekoBot.Modules.Searches
|
||||
if (!UserLanguages.TryGetValue(key, out langs))
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
var text = await TranslateInternal(umsg, langs, umsg.Resolve(UserMentionHandling.Ignore), true)
|
||||
.ConfigureAwait(false);
|
||||
if (autoDelete)
|
||||
try { await umsg.DeleteAsync().ConfigureAwait(false); } catch { }
|
||||
await umsg.Channel.SendConfirmAsync($"{umsg.Author.Mention} `:` "+text.Replace("<@ ", "<@").Replace("<@! ", "<@!")).ConfigureAwait(false);
|
||||
}
|
||||
catch { }
|
||||
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
var text = await TranslateInternal(umsg, langs, umsg.Resolve(UserMentionHandling.Ignore), true)
|
||||
.ConfigureAwait(false);
|
||||
if (autoDelete)
|
||||
try { await umsg.DeleteAsync().ConfigureAwait(false); } catch { }
|
||||
await umsg.Channel.SendConfirmAsync($"{umsg.Author.Mention} `:` " + text.Replace("<@ ", "<@").Replace("<@! ", "<@!")).ConfigureAwait(false);
|
||||
}
|
||||
catch { }
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,8 @@ using AngleSharp.Parser.Html;
|
||||
using AngleSharp;
|
||||
using AngleSharp.Dom.Html;
|
||||
using AngleSharp.Dom;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace NadekoBot.Modules.Searches
|
||||
{
|
||||
@ -470,6 +472,42 @@ namespace NadekoBot.Modules.Searches
|
||||
}
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task Define(IUserMessage msg, [Remainder] string word)
|
||||
{
|
||||
var channel = (ITextChannel)msg.Channel;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(word))
|
||||
return;
|
||||
|
||||
using (var http = new HttpClient())
|
||||
{
|
||||
var res = await http.GetStringAsync("http://api.pearson.com/v2/dictionaries/entries?headword=" + WebUtility.UrlEncode(word.Trim())).ConfigureAwait(false);
|
||||
|
||||
var data = JsonConvert.DeserializeObject<DefineModel>(res);
|
||||
|
||||
var sense = data.Results.Where(x => x.Senses != null && x.Senses[0].Definition != null).FirstOrDefault()?.Senses[0];
|
||||
|
||||
if (sense?.Definition == null)
|
||||
return;
|
||||
|
||||
string definition = sense.Definition.ToString();
|
||||
if (!(sense.Definition is string))
|
||||
definition = ((JArray)JToken.Parse(sense.Definition.ToString())).First.ToString();
|
||||
|
||||
var embed = new EmbedBuilder().WithOkColor()
|
||||
.WithTitle("Define: " + word)
|
||||
.WithDescription(definition)
|
||||
.WithFooter(efb => efb.WithText(sense.Gramatical_info?.type));
|
||||
|
||||
if (sense.Examples != null)
|
||||
embed.AddField(efb => efb.WithName("Example").WithValue(sense.Examples.First().text));
|
||||
|
||||
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task Hashtag(IUserMessage umsg, [Remainder] string query = null)
|
||||
@ -558,17 +596,8 @@ namespace NadekoBot.Modules.Searches
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task Safebooru(IUserMessage umsg, [Remainder] string tag = null)
|
||||
{
|
||||
var channel = (ITextChannel)umsg.Channel;
|
||||
|
||||
tag = tag?.Trim() ?? "";
|
||||
var link = await GetSafebooruImageLink(tag).ConfigureAwait(false);
|
||||
if (link == null)
|
||||
await channel.SendErrorAsync("No results.");
|
||||
else
|
||||
await channel.SendMessageAsync(link).ConfigureAwait(false);
|
||||
}
|
||||
public Task Safebooru(IUserMessage umsg, [Remainder] string tag = null)
|
||||
=> InternalDapiCommand(umsg, tag, DapiSearchType.Safebooru);
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
@ -648,22 +677,6 @@ namespace NadekoBot.Modules.Searches
|
||||
await channel.SendMessageAsync(await NadekoBot.Google.ShortenUrl(usr.AvatarUrl).ConfigureAwait(false)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public static async Task<string> GetSafebooruImageLink(string tag)
|
||||
{
|
||||
var rng = new NadekoRandom();
|
||||
var url =
|
||||
$"http://safebooru.org/index.php?page=dapi&s=post&q=index&limit=100&tags={tag.Replace(" ", "_")}";
|
||||
using (var http = new HttpClient())
|
||||
{
|
||||
var webpage = await http.GetStringAsync(url).ConfigureAwait(false);
|
||||
var matches = Regex.Matches(webpage, "file_url=\"(?<url>.*?)\"");
|
||||
if (matches.Count == 0)
|
||||
return null;
|
||||
var match = matches[rng.Next(0, matches.Count)];
|
||||
return "http:" + matches[rng.Next(0, matches.Count)].Groups["url"].Value;
|
||||
}
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task Wikia(IUserMessage umsg, string target, [Remainder] string query = null)
|
||||
@ -772,6 +785,77 @@ namespace NadekoBot.Modules.Searches
|
||||
}
|
||||
}
|
||||
|
||||
public enum DapiSearchType
|
||||
{
|
||||
Safebooru,
|
||||
Gelbooru,
|
||||
Konachan,
|
||||
Rule34,
|
||||
Yandere
|
||||
}
|
||||
|
||||
public static async Task InternalDapiCommand(IUserMessage umsg, string tag, DapiSearchType type)
|
||||
{
|
||||
var channel = (ITextChannel)umsg.Channel;
|
||||
|
||||
tag = tag?.Trim() ?? "";
|
||||
|
||||
var url = await InternalDapiSearch(tag, type).ConfigureAwait(false);
|
||||
|
||||
if (url == null)
|
||||
await channel.SendErrorAsync(umsg.Author.Mention + " No results.");
|
||||
else
|
||||
await channel.EmbedAsync(new EmbedBuilder().WithOkColor()
|
||||
.WithDescription(umsg.Author.Mention + " " + tag)
|
||||
.WithImageUrl(url)
|
||||
.WithFooter(efb => efb.WithText(type.ToString()))
|
||||
.Build()).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public static async Task<string> InternalDapiSearch(string tag, DapiSearchType type)
|
||||
{
|
||||
tag = tag?.Replace(" ", "_");
|
||||
string website = "";
|
||||
switch (type)
|
||||
{
|
||||
case DapiSearchType.Safebooru:
|
||||
website = $"https://safebooru.org/index.php?page=dapi&s=post&q=index&limit=100&tags={tag}";
|
||||
break;
|
||||
case DapiSearchType.Gelbooru:
|
||||
website = $"http://gelbooru.com/index.php?page=dapi&s=post&q=index&limit=100&tags={tag}";
|
||||
break;
|
||||
case DapiSearchType.Rule34:
|
||||
website = $"https://rule34.xxx/index.php?page=dapi&s=post&q=index&limit=100&tags={tag}";
|
||||
break;
|
||||
case DapiSearchType.Konachan:
|
||||
website = $"https://konachan.com/post.xml?s=post&q=index&limit=100&tags={tag}";
|
||||
break;
|
||||
case DapiSearchType.Yandere:
|
||||
website = $"https://yande.re/post.xml?limit=100&tags={tag}";
|
||||
break;
|
||||
}
|
||||
try
|
||||
{
|
||||
using (var http = new HttpClient())
|
||||
{
|
||||
http.AddFakeHeaders();
|
||||
var data = await http.GetStreamAsync(website);
|
||||
var doc = new XmlDocument();
|
||||
doc.Load(data);
|
||||
|
||||
var node = doc.LastChild.ChildNodes[new NadekoRandom().Next(0, doc.LastChild.ChildNodes.Count)];
|
||||
|
||||
var url = node.Attributes["file_url"].Value;
|
||||
if (!url.StartsWith("http"))
|
||||
url = "https:" + url;
|
||||
return url;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public static async Task<bool> ValidateQuery(ITextChannel ch, string query)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(query.Trim())) return true;
|
||||
|
@ -95,5 +95,31 @@ namespace NadekoBot.Modules.Utility
|
||||
.WithOkColor();
|
||||
await msg.Channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[OwnerOnly]
|
||||
public async Task Activity(IUserMessage imsg, int page = 1)
|
||||
{
|
||||
const int activityPerPage = 15;
|
||||
page -= 1;
|
||||
|
||||
if (page < 0)
|
||||
return;
|
||||
|
||||
int startCount = page * activityPerPage;
|
||||
|
||||
StringBuilder str = new StringBuilder();
|
||||
foreach (var kvp in NadekoBot.CommandHandler.UserMessagesSent.OrderByDescending(kvp => kvp.Value).Skip(page*activityPerPage).Take(activityPerPage))
|
||||
{
|
||||
str.AppendLine($"`{++startCount}.` **{kvp.Key}** [{kvp.Value/NadekoBot.Stats.GetUptime().TotalSeconds:F2}/s] - {kvp.Value} total");
|
||||
}
|
||||
|
||||
await imsg.Channel.EmbedAsync(new EmbedBuilder().WithTitle($"Activity Page #{page}")
|
||||
.WithOkColor()
|
||||
.WithFooter(efb => efb.WithText($"{NadekoBot.CommandHandler.UserMessagesSent.Count} users total."))
|
||||
.WithDescription(str.ToString())
|
||||
.Build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
81
src/NadekoBot/Resources/CommandStrings.Designer.cs
generated
81
src/NadekoBot/Resources/CommandStrings.Designer.cs
generated
@ -113,6 +113,33 @@ namespace NadekoBot.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to activity.
|
||||
/// </summary>
|
||||
public static string activity_cmd {
|
||||
get {
|
||||
return ResourceManager.GetString("activity_cmd", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Checks for spammers..
|
||||
/// </summary>
|
||||
public static string activity_desc {
|
||||
get {
|
||||
return ResourceManager.GetString("activity_desc", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to `{0}activity`.
|
||||
/// </summary>
|
||||
public static string activity_usage {
|
||||
get {
|
||||
return ResourceManager.GetString("activity_usage", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to addcustreact acr.
|
||||
/// </summary>
|
||||
@ -2003,6 +2030,33 @@ namespace NadekoBot.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to define def.
|
||||
/// </summary>
|
||||
public static string define_cmd {
|
||||
get {
|
||||
return ResourceManager.GetString("define_cmd", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Finds a definition of a word..
|
||||
/// </summary>
|
||||
public static string define_desc {
|
||||
get {
|
||||
return ResourceManager.GetString("define_desc", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to `{0}def heresy`.
|
||||
/// </summary>
|
||||
public static string define_usage {
|
||||
get {
|
||||
return ResourceManager.GetString("define_usage", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to defvol dv.
|
||||
/// </summary>
|
||||
@ -6350,6 +6404,33 @@ namespace NadekoBot.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to setmaxplaytime smp.
|
||||
/// </summary>
|
||||
public static string setmaxplaytime_cmd {
|
||||
get {
|
||||
return ResourceManager.GetString("setmaxplaytime_cmd", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Sets a maximum number of seconds (>14) a song can run before being skipped automatically. Set 0 to have no limit..
|
||||
/// </summary>
|
||||
public static string setmaxplaytime_desc {
|
||||
get {
|
||||
return ResourceManager.GetString("setmaxplaytime_desc", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to `{0}smp 0` or `{0}smp 270`.
|
||||
/// </summary>
|
||||
public static string setmaxplaytime_usage {
|
||||
get {
|
||||
return ResourceManager.GetString("setmaxplaytime_usage", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to setmaxqueue smq.
|
||||
/// </summary>
|
||||
|
@ -2817,4 +2817,31 @@
|
||||
<data name="fairplay_usage" xml:space="preserve">
|
||||
<value>`{0}fp`</value>
|
||||
</data>
|
||||
<data name="define_cmd" xml:space="preserve">
|
||||
<value>define def</value>
|
||||
</data>
|
||||
<data name="define_desc" xml:space="preserve">
|
||||
<value>Finds a definition of a word.</value>
|
||||
</data>
|
||||
<data name="define_usage" xml:space="preserve">
|
||||
<value>`{0}def heresy`</value>
|
||||
</data>
|
||||
<data name="setmaxplaytime_cmd" xml:space="preserve">
|
||||
<value>setmaxplaytime smp</value>
|
||||
</data>
|
||||
<data name="setmaxplaytime_desc" xml:space="preserve">
|
||||
<value>Sets a maximum number of seconds (>14) a song can run before being skipped automatically. Set 0 to have no limit.</value>
|
||||
</data>
|
||||
<data name="setmaxplaytime_usage" xml:space="preserve">
|
||||
<value>`{0}smp 0` or `{0}smp 270`</value>
|
||||
</data>
|
||||
<data name="activity_cmd" xml:space="preserve">
|
||||
<value>activity</value>
|
||||
</data>
|
||||
<data name="activity_desc" xml:space="preserve">
|
||||
<value>Checks for spammers.</value>
|
||||
</data>
|
||||
<data name="activity_usage" xml:space="preserve">
|
||||
<value>`{0}activity`</value>
|
||||
</data>
|
||||
</root>
|
@ -16,20 +16,15 @@ using NadekoBot.Modules.Help;
|
||||
using static NadekoBot.Modules.Administration.Administration;
|
||||
using NadekoBot.Modules.CustomReactions;
|
||||
using NadekoBot.Modules.Games;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace NadekoBot.Services
|
||||
{
|
||||
public class IGuildUserComparer : IEqualityComparer<IGuildUser>
|
||||
{
|
||||
public bool Equals(IGuildUser x, IGuildUser y)
|
||||
{
|
||||
return x.Id == y.Id;
|
||||
}
|
||||
public bool Equals(IGuildUser x, IGuildUser y) => x.Id == y.Id;
|
||||
|
||||
public int GetHashCode(IGuildUser obj)
|
||||
{
|
||||
return obj.Id.GetHashCode();
|
||||
}
|
||||
public int GetHashCode(IGuildUser obj) => obj.Id.GetHashCode();
|
||||
}
|
||||
public class CommandHandler
|
||||
{
|
||||
@ -39,7 +34,10 @@ namespace NadekoBot.Services
|
||||
|
||||
private List<IDMChannel> ownerChannels { get; set; }
|
||||
|
||||
public event Func<IUserMessage,Command, Task> CommandExecuted = delegate { return Task.CompletedTask; };
|
||||
public event Func<IUserMessage, Command, Task> CommandExecuted = delegate { return Task.CompletedTask; };
|
||||
|
||||
//userid/msg count
|
||||
public ConcurrentDictionary<ulong, uint> UserMessagesSent { get; } = new ConcurrentDictionary<ulong, uint>();
|
||||
|
||||
public CommandHandler(ShardedDiscordClient client, CommandService commandService)
|
||||
{
|
||||
@ -64,46 +62,31 @@ namespace NadekoBot.Services
|
||||
_client.MessageReceived += MessageReceivedHandler;
|
||||
}
|
||||
|
||||
private Task MessageReceivedHandler(IMessage msg)
|
||||
private async void MessageReceivedHandler(IMessage msg)
|
||||
{
|
||||
var usrMsg = msg as IUserMessage;
|
||||
if (usrMsg == null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
if (usrMsg.Author.IsBot || !NadekoBot.Ready) //no bots
|
||||
return Task.CompletedTask;
|
||||
|
||||
var throwaway = Task.Run(async () =>
|
||||
try
|
||||
{
|
||||
var usrMsg = msg as IUserMessage;
|
||||
if (usrMsg == null)
|
||||
return;
|
||||
|
||||
if (!usrMsg.IsAuthor())
|
||||
UserMessagesSent.AddOrUpdate(usrMsg.Author.Id, 1, (key, old) => ++old);
|
||||
|
||||
if (usrMsg.Author.IsBot || !NadekoBot.Ready) //no bots
|
||||
return;
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
|
||||
try
|
||||
|
||||
var guild = (msg.Channel as ITextChannel)?.Guild;
|
||||
|
||||
if (guild != null && guild.OwnerId != usrMsg.Author.Id)
|
||||
{
|
||||
var guild = (msg.Channel as ITextChannel)?.Guild;
|
||||
|
||||
if (guild != null && guild.OwnerId != usrMsg.Author.Id)
|
||||
if (Permissions.FilterCommands.InviteFilteringChannels.Contains(usrMsg.Channel.Id) ||
|
||||
Permissions.FilterCommands.InviteFilteringServers.Contains(guild.Id))
|
||||
{
|
||||
if (Permissions.FilterCommands.InviteFilteringChannels.Contains(usrMsg.Channel.Id) ||
|
||||
Permissions.FilterCommands.InviteFilteringServers.Contains(guild.Id))
|
||||
{
|
||||
if (usrMsg.Content.IsDiscordInvite())
|
||||
{
|
||||
try
|
||||
{
|
||||
await usrMsg.DeleteAsync().ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
_log.Warn("I do not have permission to filter invites in channel with id " + usrMsg.Channel.Id, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var filteredWords = Permissions.FilterCommands.FilteredWordsForChannel(usrMsg.Channel.Id, guild.Id).Concat(Permissions.FilterCommands.FilteredWordsForServer(guild.Id));
|
||||
var wordsInMessage = usrMsg.Content.ToLowerInvariant().Split(' ');
|
||||
if (filteredWords.Any(w => wordsInMessage.Contains(w)))
|
||||
if (usrMsg.Content.IsDiscordInvite())
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -112,108 +95,122 @@ namespace NadekoBot.Services
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
_log.Warn("I do not have permission to filter words in channel with id " + usrMsg.Channel.Id, ex);
|
||||
_log.Warn("I do not have permission to filter invites in channel with id " + usrMsg.Channel.Id, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BlacklistItem blacklistedItem;
|
||||
if ((blacklistedItem = Permissions.BlacklistCommands.BlacklistedItems.FirstOrDefault(bi =>
|
||||
(bi.Type == BlacklistItem.BlacklistType.Server && bi.ItemId == guild?.Id) ||
|
||||
(bi.Type == BlacklistItem.BlacklistType.Channel && bi.ItemId == msg.Channel.Id) ||
|
||||
(bi.Type == BlacklistItem.BlacklistType.User && bi.ItemId == usrMsg.Author.Id))) != null)
|
||||
var filteredWords = Permissions.FilterCommands.FilteredWordsForChannel(usrMsg.Channel.Id, guild.Id).Concat(Permissions.FilterCommands.FilteredWordsForServer(guild.Id));
|
||||
var wordsInMessage = usrMsg.Content.ToLowerInvariant().Split(' ');
|
||||
if (filteredWords.Any(w => wordsInMessage.Contains(w)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var cleverbotExecuted = await Games.CleverBotCommands.TryAsk(usrMsg);
|
||||
|
||||
if (cleverbotExecuted)
|
||||
return;
|
||||
}
|
||||
catch (Exception ex) { _log.Warn(ex, "Error in cleverbot"); }
|
||||
|
||||
try
|
||||
{
|
||||
// maybe this message is a custom reaction
|
||||
var crExecuted = await CustomReactions.TryExecuteCustomReaction(usrMsg).ConfigureAwait(false);
|
||||
|
||||
//if it was, don't execute the command
|
||||
if (crExecuted)
|
||||
return;
|
||||
}
|
||||
catch { }
|
||||
|
||||
var t = await ExecuteCommand(usrMsg, usrMsg.Content, guild, usrMsg.Author, MultiMatchHandling.Best);
|
||||
var command = t.Item1;
|
||||
var permCache = t.Item2;
|
||||
var result = t.Item3;
|
||||
sw.Stop();
|
||||
var channel = (usrMsg.Channel as ITextChannel);
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
await CommandExecuted(usrMsg, command);
|
||||
_log.Info("Command Executed after {4}s\n\t" +
|
||||
"User: {0}\n\t" +
|
||||
"Server: {1}\n\t" +
|
||||
"Channel: {2}\n\t" +
|
||||
"Message: {3}",
|
||||
usrMsg.Author + " [" + usrMsg.Author.Id + "]", // {0}
|
||||
(channel == null ? "PRIVATE" : channel.Guild.Name + " [" + channel.Guild.Id + "]"), // {1}
|
||||
(channel == null ? "PRIVATE" : channel.Name + " [" + channel.Id + "]"), // {2}
|
||||
usrMsg.Content, // {3}
|
||||
sw.Elapsed.TotalSeconds // {4}
|
||||
);
|
||||
}
|
||||
else if (!result.IsSuccess && result.Error != CommandError.UnknownCommand)
|
||||
{
|
||||
_log.Warn("Command Errored after {5}s\n\t" +
|
||||
"User: {0}\n\t" +
|
||||
"Server: {1}\n\t" +
|
||||
"Channel: {2}\n\t" +
|
||||
"Message: {3}\n\t" +
|
||||
"Error: {4}",
|
||||
usrMsg.Author + " [" + usrMsg.Author.Id + "]", // {0}
|
||||
(channel == null ? "PRIVATE" : channel.Guild.Name + " [" + channel.Guild.Id + "]"), // {1}
|
||||
(channel == null ? "PRIVATE" : channel.Name + " [" + channel.Id + "]"), // {2}
|
||||
usrMsg.Content,// {3}
|
||||
result.ErrorReason, // {4}
|
||||
sw.Elapsed.TotalSeconds // {5}
|
||||
);
|
||||
if (guild != null && command != null && result.Error == CommandError.Exception)
|
||||
try
|
||||
{
|
||||
if (permCache != null && permCache.Verbose)
|
||||
try { await msg.Channel.SendMessageAsync("⚠️ " + result.ErrorReason).ConfigureAwait(false); } catch { }
|
||||
await usrMsg.DeleteAsync().ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (msg.Channel is IPrivateChannel)
|
||||
catch (HttpException ex)
|
||||
{
|
||||
//rofl, gotta do this to prevent this message from occuring on polls
|
||||
int vote;
|
||||
if (int.TryParse(msg.Content, out vote)) return;
|
||||
|
||||
await msg.Channel.SendMessageAsync(Help.DMHelpString).ConfigureAwait(false);
|
||||
|
||||
await DMForwardCommands.HandleDMForwarding(msg, ownerChannels);
|
||||
_log.Warn("I do not have permission to filter words in channel with id " + usrMsg.Channel.Id, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
BlacklistItem blacklistedItem;
|
||||
if ((blacklistedItem = Permissions.BlacklistCommands.BlacklistedItems.FirstOrDefault(bi =>
|
||||
(bi.Type == BlacklistItem.BlacklistType.Server && bi.ItemId == guild?.Id) ||
|
||||
(bi.Type == BlacklistItem.BlacklistType.Channel && bi.ItemId == msg.Channel.Id) ||
|
||||
(bi.Type == BlacklistItem.BlacklistType.User && bi.ItemId == usrMsg.Author.Id))) != null)
|
||||
{
|
||||
_log.Warn(ex, "Error in CommandHandler");
|
||||
if (ex.InnerException != null)
|
||||
_log.Warn(ex.InnerException, "Inner Exception of the error in CommandHandler");
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
try
|
||||
{
|
||||
var cleverbotExecuted = await Games.CleverBotCommands.TryAsk(usrMsg);
|
||||
|
||||
if (cleverbotExecuted)
|
||||
return;
|
||||
}
|
||||
catch (Exception ex) { _log.Warn(ex, "Error in cleverbot"); }
|
||||
|
||||
try
|
||||
{
|
||||
// maybe this message is a custom reaction
|
||||
var crExecuted = await CustomReactions.TryExecuteCustomReaction(usrMsg).ConfigureAwait(false);
|
||||
|
||||
//if it was, don't execute the command
|
||||
if (crExecuted)
|
||||
return;
|
||||
}
|
||||
catch { }
|
||||
|
||||
var t = await ExecuteCommand(usrMsg, usrMsg.Content, guild, usrMsg.Author, MultiMatchHandling.Best);
|
||||
var command = t.Item1;
|
||||
var permCache = t.Item2;
|
||||
var result = t.Item3;
|
||||
sw.Stop();
|
||||
var channel = (usrMsg.Channel as ITextChannel);
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
await CommandExecuted(usrMsg, command);
|
||||
_log.Info("Command Executed after {4}s\n\t" +
|
||||
"User: {0}\n\t" +
|
||||
"Server: {1}\n\t" +
|
||||
"Channel: {2}\n\t" +
|
||||
"Message: {3}",
|
||||
usrMsg.Author + " [" + usrMsg.Author.Id + "]", // {0}
|
||||
(channel == null ? "PRIVATE" : channel.Guild.Name + " [" + channel.Guild.Id + "]"), // {1}
|
||||
(channel == null ? "PRIVATE" : channel.Name + " [" + channel.Id + "]"), // {2}
|
||||
usrMsg.Content, // {3}
|
||||
sw.Elapsed.TotalSeconds // {4}
|
||||
);
|
||||
}
|
||||
else if (!result.IsSuccess && result.Error != CommandError.UnknownCommand)
|
||||
{
|
||||
_log.Warn("Command Errored after {5}s\n\t" +
|
||||
"User: {0}\n\t" +
|
||||
"Server: {1}\n\t" +
|
||||
"Channel: {2}\n\t" +
|
||||
"Message: {3}\n\t" +
|
||||
"Error: {4}",
|
||||
usrMsg.Author + " [" + usrMsg.Author.Id + "]", // {0}
|
||||
(channel == null ? "PRIVATE" : channel.Guild.Name + " [" + channel.Guild.Id + "]"), // {1}
|
||||
(channel == null ? "PRIVATE" : channel.Name + " [" + channel.Id + "]"), // {2}
|
||||
usrMsg.Content,// {3}
|
||||
result.ErrorReason, // {4}
|
||||
sw.Elapsed.TotalSeconds // {5}
|
||||
);
|
||||
if (guild != null && command != null && result.Error == CommandError.Exception)
|
||||
{
|
||||
if (permCache != null && permCache.Verbose)
|
||||
try { await msg.Channel.SendMessageAsync("⚠️ " + result.ErrorReason).ConfigureAwait(false); } catch { }
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (msg.Channel is IPrivateChannel)
|
||||
{
|
||||
//rofl, gotta do this to prevent this message from occuring on polls
|
||||
int vote;
|
||||
if (int.TryParse(msg.Content, out vote)) return;
|
||||
|
||||
await msg.Channel.SendMessageAsync(Help.DMHelpString).ConfigureAwait(false);
|
||||
|
||||
await DMForwardCommands.HandleDMForwarding(msg, ownerChannels);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.Warn(ex, "Error in CommandHandler");
|
||||
if (ex.InnerException != null)
|
||||
_log.Warn(ex.InnerException, "Inner Exception of the error in CommandHandler");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Tuple<Command, PermissionCache, IResult>> ExecuteCommand(IUserMessage message, string input, IGuild guild, IUser user, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Best) {
|
||||
public async Task<Tuple<Command, PermissionCache, IResult>> ExecuteCommand(IUserMessage message, string input, IGuild guild, IUser user, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Best)
|
||||
{
|
||||
var searchResult = _commandService.Search(message, input);
|
||||
if (!searchResult.IsSuccess)
|
||||
return new Tuple<Command, PermissionCache, IResult>(null, null, searchResult);
|
||||
@ -312,4 +309,4 @@ namespace NadekoBot.Services
|
||||
Command = cmd;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -13,20 +13,20 @@ namespace NadekoBot
|
||||
private DiscordSocketConfig discordSocketConfig;
|
||||
private Logger _log { get; }
|
||||
|
||||
public event Func<IGuildUser, Task> UserJoined = delegate { return Task.CompletedTask; };
|
||||
public event Func<IMessage, Task> MessageReceived = delegate { return Task.CompletedTask; };
|
||||
public event Func<IGuildUser, Task> UserLeft = delegate { return Task.CompletedTask; };
|
||||
public event Func<IGuildUser, IGuildUser, Task> UserUpdated = delegate { return Task.CompletedTask; };
|
||||
public event Func<Optional<IMessage>, IMessage, Task> MessageUpdated = delegate { return Task.CompletedTask; };
|
||||
public event Func<ulong, Optional<IMessage>, Task> MessageDeleted = delegate { return Task.CompletedTask; };
|
||||
public event Func<IUser, IGuild, Task> UserBanned = delegate { return Task.CompletedTask; };
|
||||
public event Func<IUser, IGuild, Task> UserUnbanned = delegate { return Task.CompletedTask; };
|
||||
public event Func<IGuildUser, IPresence, IPresence, Task> UserPresenceUpdated = delegate { return Task.CompletedTask; };
|
||||
public event Func<IUser, IVoiceState, IVoiceState, Task> UserVoiceStateUpdated = delegate { return Task.CompletedTask; };
|
||||
public event Func<IChannel, Task> ChannelCreated = delegate { return Task.CompletedTask; };
|
||||
public event Func<IChannel, Task> ChannelDestroyed = delegate { return Task.CompletedTask; };
|
||||
public event Func<IChannel, IChannel, Task> ChannelUpdated = delegate { return Task.CompletedTask; };
|
||||
public event Func<Exception, Task> Disconnected = delegate { return Task.CompletedTask; };
|
||||
public event Action<IGuildUser> UserJoined = delegate { };
|
||||
public event Action<IMessage> MessageReceived = delegate { };
|
||||
public event Action<IGuildUser> UserLeft = delegate { };
|
||||
public event Action<IGuildUser, IGuildUser> UserUpdated = delegate { };
|
||||
public event Action<Optional<IMessage>, IMessage> MessageUpdated = delegate { };
|
||||
public event Action<ulong, Optional<IMessage>> MessageDeleted = delegate { };
|
||||
public event Action<IUser, IGuild> UserBanned = delegate { };
|
||||
public event Action<IUser, IGuild> UserUnbanned = delegate { };
|
||||
public event Action<IGuildUser, IPresence, IPresence> UserPresenceUpdated = delegate { };
|
||||
public event Action<IUser, IVoiceState, IVoiceState> UserVoiceStateUpdated = delegate { };
|
||||
public event Action<IChannel> ChannelCreated = delegate { };
|
||||
public event Action<IChannel> ChannelDestroyed = delegate { };
|
||||
public event Action<IChannel, IChannel> ChannelUpdated = delegate { };
|
||||
public event Action<Exception> Disconnected = delegate { };
|
||||
|
||||
private IReadOnlyList<DiscordSocketClient> Clients { get; }
|
||||
|
||||
@ -41,18 +41,19 @@ namespace NadekoBot
|
||||
discordSocketConfig.ShardId = i;
|
||||
var client = new DiscordSocketClient(discordSocketConfig);
|
||||
clientList.Add(client);
|
||||
client.UserJoined += async arg1 => await UserJoined(arg1);
|
||||
client.MessageReceived += async arg1 => await MessageReceived(arg1);
|
||||
client.UserLeft += async arg1 => await UserLeft(arg1);
|
||||
client.UserUpdated += async (arg1, gu2) => await UserUpdated(arg1, gu2);
|
||||
client.MessageUpdated += async (arg1, m2) => await MessageUpdated(arg1, m2);
|
||||
client.MessageDeleted += async (arg1, arg2) => await MessageDeleted(arg1, arg2);
|
||||
client.UserBanned += async (arg1, arg2) => await UserBanned(arg1, arg2);
|
||||
client.UserPresenceUpdated += async (arg1, arg2, arg3) => await UserPresenceUpdated(arg1, arg2, arg3);
|
||||
client.UserVoiceStateUpdated += async (arg1, arg2, arg3) => await UserVoiceStateUpdated(arg1, arg2, arg3);
|
||||
client.ChannelCreated += async arg => await ChannelCreated(arg);
|
||||
client.ChannelDestroyed += async arg => await ChannelDestroyed(arg);
|
||||
client.ChannelUpdated += async (arg1, arg2) => await ChannelUpdated(arg1, arg2);
|
||||
client.UserJoined += arg1 => { UserJoined(arg1); return Task.CompletedTask; };
|
||||
client.MessageReceived += arg1 => { MessageReceived(arg1); return Task.CompletedTask; };
|
||||
client.UserLeft += arg1 => { UserLeft(arg1); return Task.CompletedTask; };
|
||||
client.UserUpdated += (arg1, gu2) => { UserUpdated(arg1, gu2); return Task.CompletedTask; };
|
||||
client.MessageUpdated += (arg1, m2) => { MessageUpdated(arg1, m2); return Task.CompletedTask; };
|
||||
client.MessageDeleted += (arg1, arg2) => { MessageDeleted(arg1, arg2); return Task.CompletedTask; };
|
||||
client.UserBanned += (arg1, arg2) => { UserBanned(arg1, arg2); return Task.CompletedTask; };
|
||||
client.UserUnbanned += (arg1, arg2) => { UserUnbanned(arg1, arg2); return Task.CompletedTask; };
|
||||
client.UserPresenceUpdated += (arg1, arg2, arg3) => { UserPresenceUpdated(arg1, arg2, arg3); return Task.CompletedTask; };
|
||||
client.UserVoiceStateUpdated += (arg1, arg2, arg3) => { UserVoiceStateUpdated(arg1, arg2, arg3); return Task.CompletedTask; };
|
||||
client.ChannelCreated += arg => { ChannelCreated(arg); return Task.CompletedTask; };
|
||||
client.ChannelDestroyed += arg => { ChannelDestroyed(arg); return Task.CompletedTask; };
|
||||
client.ChannelUpdated += (arg1, arg2) => { ChannelUpdated(arg1, arg2); return Task.CompletedTask; };
|
||||
|
||||
_log.Info($"Shard #{i} initialized.");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user