reorganized administration
This commit is contained in:
@ -4,19 +4,19 @@ using Discord.Modules;
|
||||
using NadekoBot.Classes;
|
||||
using NadekoBot.Classes._DataModels;
|
||||
using NadekoBot.Classes.Permissions;
|
||||
using NadekoBot.Commands;
|
||||
using NadekoBot.Extensions;
|
||||
using NadekoBot.Modules.Administration.Commands;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NadekoBot.Modules
|
||||
namespace NadekoBot.Modules.Administration
|
||||
{
|
||||
internal class Administration : DiscordModule
|
||||
internal class AdministrationModule : DiscordModule
|
||||
{
|
||||
public Administration()
|
||||
public AdministrationModule()
|
||||
{
|
||||
commands.Add(new ServerGreetCommand(this));
|
||||
commands.Add(new LogCommand(this));
|
@ -0,0 +1,110 @@
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using NadekoBot.Classes.Permissions;
|
||||
using NadekoBot.Commands;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace NadekoBot.Modules.Administration.Commands
|
||||
{
|
||||
class CrossServerTextChannel : DiscordCommand
|
||||
{
|
||||
public CrossServerTextChannel(DiscordModule module) : base(module)
|
||||
{
|
||||
NadekoBot.Client.MessageReceived += async (s, e) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (e.User.Id == NadekoBot.Client.CurrentUser.Id) return;
|
||||
foreach (var subscriber in Subscribers)
|
||||
{
|
||||
var set = subscriber.Value;
|
||||
if (!set.Contains(e.Channel))
|
||||
continue;
|
||||
foreach (var chan in set.Except(new[] { e.Channel }))
|
||||
{
|
||||
await chan.SendMessage(GetText(e.Server, e.Channel, e.User, e.Message));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
};
|
||||
NadekoBot.Client.MessageUpdated += async (s, e) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (e.After?.User?.Id == null || e.After.User.Id == NadekoBot.Client.CurrentUser.Id) return;
|
||||
foreach (var subscriber in Subscribers)
|
||||
{
|
||||
var set = subscriber.Value;
|
||||
if (!set.Contains(e.Channel))
|
||||
continue;
|
||||
foreach (var chan in set.Except(new[] { e.Channel }))
|
||||
{
|
||||
var msg = chan.Messages
|
||||
.FirstOrDefault(m =>
|
||||
m.RawText == GetText(e.Server, e.Channel, e.User, e.Before));
|
||||
if (msg != default(Message))
|
||||
await msg.Edit(GetText(e.Server, e.Channel, e.User, e.After));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch { }
|
||||
};
|
||||
}
|
||||
|
||||
private string GetText(Server server, Channel channel, User user, Message message) =>
|
||||
$"**{server.Name} | {channel.Name}** `{user.Name}`: " + message.RawText;
|
||||
|
||||
public static readonly ConcurrentDictionary<int, HashSet<Channel>> Subscribers = new ConcurrentDictionary<int, HashSet<Channel>>();
|
||||
|
||||
internal override void Init(CommandGroupBuilder cgb)
|
||||
{
|
||||
cgb.CreateCommand(Module.Prefix + "scsc")
|
||||
.Description("Starts an instance of cross server channel. You will get a token as a DM" +
|
||||
"that other people will use to tune in to the same instance")
|
||||
.AddCheck(SimpleCheckers.OwnerOnly())
|
||||
.Do(async e =>
|
||||
{
|
||||
var token = new Random().Next();
|
||||
var set = new HashSet<Channel>();
|
||||
if (Subscribers.TryAdd(token, set))
|
||||
{
|
||||
set.Add(e.Channel);
|
||||
await e.User.SendMessage("This is your CSC token:" + token.ToString());
|
||||
}
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Module.Prefix + "jcsc")
|
||||
.Description("Joins current channel to an instance of cross server channel using the token.")
|
||||
.Parameter("token")
|
||||
.AddCheck(SimpleCheckers.ManageServer())
|
||||
.Do(async e =>
|
||||
{
|
||||
int token;
|
||||
if (!int.TryParse(e.GetArg("token"), out token))
|
||||
return;
|
||||
HashSet<Channel> set;
|
||||
if (!Subscribers.TryGetValue(token, out set))
|
||||
return;
|
||||
set.Add(e.Channel);
|
||||
await e.Channel.SendMessage(":ok:");
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Module.Prefix + "lcsc")
|
||||
.Description("Leaves Cross server channel instance from this channel")
|
||||
.AddCheck(SimpleCheckers.ManageServer())
|
||||
.Do(async e =>
|
||||
{
|
||||
foreach (var subscriber in Subscribers)
|
||||
{
|
||||
subscriber.Value.Remove(e.Channel);
|
||||
}
|
||||
await e.Channel.SendMessage(":ok:");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
236
NadekoBot/Modules/Administration/Commands/LogCommand.cs
Normal file
236
NadekoBot/Modules/Administration/Commands/LogCommand.cs
Normal file
@ -0,0 +1,236 @@
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using NadekoBot.Classes;
|
||||
using NadekoBot.Classes.Permissions;
|
||||
using NadekoBot.Commands;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NadekoBot.Modules.Administration.Commands
|
||||
{
|
||||
internal class LogCommand : DiscordCommand
|
||||
{
|
||||
|
||||
private readonly ConcurrentDictionary<Server, Channel> logs = new ConcurrentDictionary<Server, Channel>();
|
||||
private readonly ConcurrentDictionary<Server, Channel> loggingPresences = new ConcurrentDictionary<Server, Channel>();
|
||||
private readonly ConcurrentDictionary<Channel, Channel> voiceChannelLog = new ConcurrentDictionary<Channel, Channel>();
|
||||
|
||||
public LogCommand(DiscordModule module) : base(module)
|
||||
{
|
||||
NadekoBot.Client.MessageReceived += MsgRecivd;
|
||||
NadekoBot.Client.MessageDeleted += MsgDltd;
|
||||
NadekoBot.Client.MessageUpdated += MsgUpdtd;
|
||||
NadekoBot.Client.UserUpdated += UsrUpdtd;
|
||||
NadekoBot.Client.UserBanned += UsrBanned;
|
||||
|
||||
|
||||
NadekoBot.Client.MessageReceived += async (s, e) =>
|
||||
{
|
||||
if (e.Channel.IsPrivate || e.User.Id == NadekoBot.Client.CurrentUser.Id)
|
||||
return;
|
||||
if (!SpecificConfigurations.Default.Of(e.Server.Id).SendPrivateMessageOnMention) return;
|
||||
try
|
||||
{
|
||||
var usr = e.Message.MentionedUsers.FirstOrDefault(u => u != e.User);
|
||||
if (usr?.Status != UserStatus.Offline)
|
||||
return;
|
||||
await e.Channel.SendMessage($"User `{usr.Name}` is offline. PM sent.");
|
||||
await usr.SendMessage(
|
||||
$"User `{e.User.Name}` mentioned you on " +
|
||||
$"`{e.Server.Name}` server while you were offline.\n" +
|
||||
$"`Message:` {e.Message.Text}");
|
||||
}
|
||||
catch { }
|
||||
};
|
||||
}
|
||||
|
||||
private async void UsrBanned(object sender, UserEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
Channel ch;
|
||||
if (!logs.TryGetValue(e.Server, out ch))
|
||||
return;
|
||||
await ch.SendMessage($"`User banned:` **{e.User.Name}** ({e.User.Id})");
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
public Func<CommandEventArgs, Task> DoFunc() => async e =>
|
||||
{
|
||||
Channel ch;
|
||||
if (!logs.TryRemove(e.Server, out ch))
|
||||
{
|
||||
logs.TryAdd(e.Server, e.Channel);
|
||||
await e.Channel.SendMessage($"**I WILL BEGIN LOGGING SERVER ACTIVITY IN THIS CHANNEL**");
|
||||
return;
|
||||
}
|
||||
|
||||
await e.Channel.SendMessage($"**NO LONGER LOGGING IN {ch.Mention} CHANNEL**");
|
||||
};
|
||||
|
||||
private async void MsgRecivd(object sender, MessageEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (e.Server == null || e.Channel.IsPrivate || e.User.Id == NadekoBot.Client.CurrentUser.Id)
|
||||
return;
|
||||
Channel ch;
|
||||
if (!logs.TryGetValue(e.Server, out ch) || e.Channel == ch)
|
||||
return;
|
||||
await ch.SendMessage($"`Type:` **Message received** `Time:` **{DateTime.Now}** `Channel:` **{e.Channel.Name}**\n`{e.User}:` {e.Message.Text}");
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
private async void MsgDltd(object sender, MessageEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (e.Server == null || e.Channel.IsPrivate || e.User.Id == NadekoBot.Client.CurrentUser.Id)
|
||||
return;
|
||||
Channel ch;
|
||||
if (!logs.TryGetValue(e.Server, out ch) || e.Channel == ch)
|
||||
return;
|
||||
await ch.SendMessage($"`Type:` **Message deleted** `Time:` **{DateTime.Now}** `Channel:` **{e.Channel.Name}**\n`{e.User}:` {e.Message.Text}");
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
private async void MsgUpdtd(object sender, MessageUpdatedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (e.Server == null || e.Channel.IsPrivate || e.User.Id == NadekoBot.Client.CurrentUser.Id)
|
||||
return;
|
||||
Channel ch;
|
||||
if (!logs.TryGetValue(e.Server, out ch) || e.Channel == ch)
|
||||
return;
|
||||
await ch.SendMessage($"`Type:` **Message updated** `Time:` **{DateTime.Now}** `Channel:` **{e.Channel.Name}**\n**BEFORE**: `{e.User}:` {e.Before.Text}\n---------------\n**AFTER**: `{e.User}:` {e.After.Text}");
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
private async void UsrUpdtd(object sender, UserUpdatedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
Channel ch;
|
||||
if (loggingPresences.TryGetValue(e.Server, out ch))
|
||||
if (e.Before.Status != e.After.Status)
|
||||
{
|
||||
await ch.SendMessage($"**{e.Before.Name}** is now **{e.After.Status}**.");
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
try
|
||||
{
|
||||
if (e.Before.VoiceChannel != null && voiceChannelLog.ContainsKey(e.Before.VoiceChannel))
|
||||
{
|
||||
if (e.After.VoiceChannel != e.Before.VoiceChannel)
|
||||
await voiceChannelLog[e.Before.VoiceChannel].SendMessage($"🎼`{e.Before.Name} has left the` {e.Before.VoiceChannel.Mention} `voice channel.`");
|
||||
}
|
||||
if (e.After.VoiceChannel != null && voiceChannelLog.ContainsKey(e.After.VoiceChannel))
|
||||
{
|
||||
if (e.After.VoiceChannel != e.Before.VoiceChannel)
|
||||
await voiceChannelLog[e.After.VoiceChannel].SendMessage($"🎼`{e.After.Name} has joined the`{e.After.VoiceChannel.Mention} `voice channel.`");
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
try
|
||||
{
|
||||
Channel ch;
|
||||
if (!logs.TryGetValue(e.Server, out ch))
|
||||
return;
|
||||
string str = $"`Type:` **User updated** `Time:` **{DateTime.Now}** `User:` **{e.Before.Name}**\n";
|
||||
if (e.Before.Name != e.After.Name)
|
||||
str += $"`New name:` **{e.After.Name}**";
|
||||
else if (e.Before.AvatarUrl != e.After.AvatarUrl)
|
||||
str += $"`New Avatar:` {e.After.AvatarUrl}";
|
||||
else if (e.Before.Status != e.After.Status)
|
||||
str += $"Status `{e.Before.Status}` -> `{e.After.Status}`";
|
||||
else
|
||||
return;
|
||||
await ch.SendMessage(str);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
internal override void Init(CommandGroupBuilder cgb)
|
||||
{
|
||||
|
||||
cgb.CreateCommand(Module.Prefix + "spmom")
|
||||
.Description("Toggles whether mentions of other offline users on your server will send a pm to them.")
|
||||
.AddCheck(SimpleCheckers.ManageServer())
|
||||
.Do(async e =>
|
||||
{
|
||||
var specificConfig = SpecificConfigurations.Default.Of(e.Server.Id);
|
||||
specificConfig.SendPrivateMessageOnMention =
|
||||
!specificConfig.SendPrivateMessageOnMention;
|
||||
if (specificConfig.SendPrivateMessageOnMention)
|
||||
await e.Channel.SendMessage(":ok: I will send private messages " +
|
||||
"to mentioned offline users.");
|
||||
else
|
||||
await e.Channel.SendMessage(":ok: I won't send private messages " +
|
||||
"to mentioned offline users anymore.");
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Module.Prefix + "logserver")
|
||||
.Description("Toggles logging in this channel. Logs every message sent/deleted/edited on the server. **Owner Only!**")
|
||||
.AddCheck(SimpleCheckers.OwnerOnly())
|
||||
.AddCheck(SimpleCheckers.ManageServer())
|
||||
.Do(DoFunc());
|
||||
|
||||
cgb.CreateCommand(Module.Prefix + "userpresence")
|
||||
.Description("Starts logging to this channel when someone from the server goes online/offline/idle. **Owner Only!**")
|
||||
.AddCheck(SimpleCheckers.OwnerOnly())
|
||||
.AddCheck(SimpleCheckers.ManageServer())
|
||||
.Do(async e =>
|
||||
{
|
||||
Channel ch;
|
||||
if (!loggingPresences.TryRemove(e.Server, out ch))
|
||||
{
|
||||
loggingPresences.TryAdd(e.Server, e.Channel);
|
||||
await e.Channel.SendMessage($"**User presence notifications enabled.**");
|
||||
return;
|
||||
}
|
||||
|
||||
await e.Channel.SendMessage($"**User presence notifications disabled.**");
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Module.Prefix + "voicepresence")
|
||||
.Description("Toggles logging to this channel whenever someone joins or leaves a voice channel you are in right now. **Owner Only!**")
|
||||
.Parameter("all", ParameterType.Optional)
|
||||
.AddCheck(SimpleCheckers.OwnerOnly())
|
||||
.AddCheck(SimpleCheckers.ManageServer())
|
||||
.Do(async e =>
|
||||
{
|
||||
|
||||
if (e.GetArg("all")?.ToLower() == "all")
|
||||
{
|
||||
foreach (var voiceChannel in e.Server.VoiceChannels)
|
||||
{
|
||||
voiceChannelLog.TryAdd(voiceChannel, e.Channel);
|
||||
}
|
||||
await e.Channel.SendMessage("Started logging user presence for **ALL** voice channels!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.User.VoiceChannel == null)
|
||||
{
|
||||
await e.Channel.SendMessage("💢 You are not in a voice channel right now. If you are, please rejoin it.");
|
||||
return;
|
||||
}
|
||||
Channel throwaway;
|
||||
if (!voiceChannelLog.TryRemove(e.User.VoiceChannel, out throwaway))
|
||||
{
|
||||
voiceChannelLog.TryAdd(e.User.VoiceChannel, e.Channel);
|
||||
await e.Channel.SendMessage($"`Logging user updates for` {e.User.VoiceChannel.Mention} `voice channel.`");
|
||||
}
|
||||
else
|
||||
await e.Channel.SendMessage($"`Stopped logging user updates for` {e.User.VoiceChannel.Mention} `voice channel.`");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
100
NadekoBot/Modules/Administration/Commands/MessageRepeater.cs
Normal file
100
NadekoBot/Modules/Administration/Commands/MessageRepeater.cs
Normal file
@ -0,0 +1,100 @@
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using NadekoBot.Classes.Permissions;
|
||||
using NadekoBot.Commands;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Timers;
|
||||
|
||||
namespace NadekoBot.Modules.Administration.Commands
|
||||
{
|
||||
class MessageRepeater : DiscordCommand
|
||||
{
|
||||
private readonly ConcurrentDictionary<Server, Repeater> repeaters = new ConcurrentDictionary<Server, Repeater>();
|
||||
private class Repeater
|
||||
{
|
||||
[Newtonsoft.Json.JsonIgnore]
|
||||
public Timer MessageTimer { get; set; }
|
||||
[Newtonsoft.Json.JsonIgnore]
|
||||
public Channel RepeatingChannel { get; set; }
|
||||
|
||||
public ulong RepeatingServerId { get; set; }
|
||||
public ulong RepeatingChannelId { get; set; }
|
||||
public string RepeatingMessage { get; set; }
|
||||
public int Interval { get; set; }
|
||||
|
||||
public Repeater Start()
|
||||
{
|
||||
MessageTimer = new Timer { Interval = Interval };
|
||||
MessageTimer.Elapsed += async (s, e) =>
|
||||
{
|
||||
var ch = RepeatingChannel;
|
||||
var msg = RepeatingMessage;
|
||||
if (ch != null && !string.IsNullOrWhiteSpace(msg))
|
||||
{
|
||||
try
|
||||
{
|
||||
await ch.SendMessage(msg);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
};
|
||||
return this;
|
||||
}
|
||||
}
|
||||
internal override void Init(CommandGroupBuilder cgb)
|
||||
{
|
||||
|
||||
cgb.CreateCommand(Module.Prefix + "repeat")
|
||||
.Description("Repeat a message every X minutes. If no parameters are specified, " +
|
||||
"repeat is disabled. Requires manage messages.")
|
||||
.Parameter("minutes", ParameterType.Optional)
|
||||
.Parameter("msg", ParameterType.Unparsed)
|
||||
.AddCheck(SimpleCheckers.ManageMessages())
|
||||
.Do(async e =>
|
||||
{
|
||||
var minutesStr = e.GetArg("minutes");
|
||||
var msg = e.GetArg("msg");
|
||||
|
||||
// if both null, disable
|
||||
if (string.IsNullOrWhiteSpace(msg) && string.IsNullOrWhiteSpace(minutesStr))
|
||||
{
|
||||
await e.Channel.SendMessage("Repeating disabled");
|
||||
Repeater rep;
|
||||
if (repeaters.TryGetValue(e.Server, out rep))
|
||||
rep.MessageTimer.Stop();
|
||||
return;
|
||||
}
|
||||
int minutes;
|
||||
if (!int.TryParse(minutesStr, out minutes) || minutes < 1 || minutes > 720)
|
||||
{
|
||||
await e.Channel.SendMessage("Invalid value");
|
||||
return;
|
||||
}
|
||||
|
||||
var repeater = repeaters.GetOrAdd(
|
||||
e.Server,
|
||||
s => new Repeater
|
||||
{
|
||||
Interval = minutes * 60 * 1000,
|
||||
RepeatingChannel = e.Channel,
|
||||
RepeatingChannelId = e.Channel.Id,
|
||||
RepeatingServerId = e.Server.Id,
|
||||
}.Start()
|
||||
);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(msg))
|
||||
repeater.RepeatingMessage = msg;
|
||||
|
||||
repeater.MessageTimer.Stop();
|
||||
repeater.MessageTimer.Start();
|
||||
|
||||
await e.Channel.SendMessage(String.Format("👌 Repeating `{0}` every " +
|
||||
"**{1}** minutes on {2} channel.",
|
||||
repeater.RepeatingMessage, minutes, repeater.RepeatingChannel));
|
||||
});
|
||||
}
|
||||
|
||||
public MessageRepeater(DiscordModule module) : base(module) { }
|
||||
}
|
||||
}
|
151
NadekoBot/Modules/Administration/Commands/PlayingRotate.cs
Normal file
151
NadekoBot/Modules/Administration/Commands/PlayingRotate.cs
Normal file
@ -0,0 +1,151 @@
|
||||
using Discord.Commands;
|
||||
using NadekoBot.Classes.JSONModels;
|
||||
using NadekoBot.Commands;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Timers;
|
||||
|
||||
namespace NadekoBot.Modules.Administration.Commands
|
||||
{
|
||||
internal class PlayingRotate : DiscordCommand
|
||||
{
|
||||
private static readonly Timer timer = new Timer(12000);
|
||||
|
||||
public static Dictionary<string, Func<string>> PlayingPlaceholders { get; } =
|
||||
new Dictionary<string, Func<string>> {
|
||||
{"%servers%", () => NadekoBot.Client.Servers.Count().ToString()},
|
||||
{"%users%", () => NadekoBot.Client.Servers.SelectMany(s => s.Users).Count().ToString()},
|
||||
{"%playing%", () => {
|
||||
var cnt = Music.MusicPlayers.Count(kvp => kvp.Value.CurrentSong != null);
|
||||
if (cnt != 1) return cnt.ToString();
|
||||
try {
|
||||
var mp = Music.MusicPlayers.FirstOrDefault();
|
||||
return mp.Value.CurrentSong.SongInfo.Title;
|
||||
}
|
||||
catch {
|
||||
return "No songs";
|
||||
}
|
||||
}
|
||||
},
|
||||
{"%queued%", () => Music.MusicPlayers.Sum(kvp => kvp.Value.Playlist.Count).ToString()},
|
||||
{"%trivia%", () => Trivia.RunningTrivias.Count.ToString()}
|
||||
};
|
||||
|
||||
private readonly object playingPlaceholderLock = new object();
|
||||
|
||||
public PlayingRotate(DiscordModule module) : base(module)
|
||||
{
|
||||
var i = -1;
|
||||
timer.Elapsed += (s, e) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
i++;
|
||||
var status = "";
|
||||
lock (playingPlaceholderLock)
|
||||
{
|
||||
if (PlayingPlaceholders.Count == 0)
|
||||
return;
|
||||
if (i >= PlayingPlaceholders.Count)
|
||||
{
|
||||
i = -1;
|
||||
return;
|
||||
}
|
||||
status = NadekoBot.Config.RotatingStatuses[i];
|
||||
status = PlayingPlaceholders.Aggregate(status,
|
||||
(current, kvp) => current.Replace(kvp.Key, kvp.Value()));
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(status))
|
||||
return;
|
||||
Task.Run(() => { NadekoBot.Client.SetGame(status); });
|
||||
}
|
||||
catch { }
|
||||
};
|
||||
|
||||
timer.Enabled = NadekoBot.Config.IsRotatingStatus;
|
||||
}
|
||||
|
||||
public Func<CommandEventArgs, Task> DoFunc() => async e =>
|
||||
{
|
||||
lock (playingPlaceholderLock)
|
||||
{
|
||||
if (timer.Enabled)
|
||||
timer.Stop();
|
||||
else
|
||||
timer.Start();
|
||||
NadekoBot.Config.IsRotatingStatus = timer.Enabled;
|
||||
ConfigHandler.SaveConfig();
|
||||
}
|
||||
await e.Channel.SendMessage($"❗`Rotating playing status has been {(timer.Enabled ? "enabled" : "disabled")}.`");
|
||||
};
|
||||
|
||||
internal override void Init(CommandGroupBuilder cgb)
|
||||
{
|
||||
cgb.CreateCommand(Module.Prefix + "rotateplaying")
|
||||
.Alias(Module.Prefix + "ropl")
|
||||
.Description("Toggles rotation of playing status of the dynamic strings you specified earlier.")
|
||||
.AddCheck(Classes.Permissions.SimpleCheckers.OwnerOnly())
|
||||
.Do(DoFunc());
|
||||
|
||||
cgb.CreateCommand(Module.Prefix + "addplaying")
|
||||
.Alias(Module.Prefix + "adpl")
|
||||
.Description("Adds a specified string to the list of playing strings to rotate. " +
|
||||
"Supported placeholders: " + string.Join(", ", PlayingPlaceholders.Keys))
|
||||
.Parameter("text", ParameterType.Unparsed)
|
||||
.AddCheck(Classes.Permissions.SimpleCheckers.OwnerOnly())
|
||||
.Do(async e =>
|
||||
{
|
||||
var arg = e.GetArg("text");
|
||||
if (string.IsNullOrWhiteSpace(arg))
|
||||
return;
|
||||
lock (playingPlaceholderLock)
|
||||
{
|
||||
NadekoBot.Config.RotatingStatuses.Add(arg);
|
||||
ConfigHandler.SaveConfig();
|
||||
}
|
||||
await e.Channel.SendMessage("🆗 `Added a new playing string.`");
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Module.Prefix + "listplaying")
|
||||
.Alias(Module.Prefix + "lipl")
|
||||
.Description("Lists all playing statuses with their corresponding number.")
|
||||
.AddCheck(Classes.Permissions.SimpleCheckers.OwnerOnly())
|
||||
.Do(async e =>
|
||||
{
|
||||
if (NadekoBot.Config.RotatingStatuses.Count == 0)
|
||||
await e.Channel.SendMessage("`There are no playing strings. " +
|
||||
"Add some with .addplaying [text] command.`");
|
||||
var sb = new StringBuilder();
|
||||
for (var i = 0; i < NadekoBot.Config.RotatingStatuses.Count; i++)
|
||||
{
|
||||
sb.AppendLine($"`{i + 1}.` {NadekoBot.Config.RotatingStatuses[i]}");
|
||||
}
|
||||
await e.Channel.SendMessage(sb.ToString());
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Module.Prefix + "removeplaying")
|
||||
.Alias(Module.Prefix + "repl", Module.Prefix + "rmpl")
|
||||
.Description("Removes a playing string on a given number.")
|
||||
.Parameter("number", ParameterType.Required)
|
||||
.AddCheck(Classes.Permissions.SimpleCheckers.OwnerOnly())
|
||||
.Do(async e =>
|
||||
{
|
||||
var arg = e.GetArg("number");
|
||||
int num;
|
||||
string str;
|
||||
lock (playingPlaceholderLock)
|
||||
{
|
||||
if (!int.TryParse(arg.Trim(), out num) || num <= 0 || num > NadekoBot.Config.RotatingStatuses.Count)
|
||||
return;
|
||||
str = NadekoBot.Config.RotatingStatuses[num - 1];
|
||||
NadekoBot.Config.RotatingStatuses.RemoveAt(num - 1);
|
||||
ConfigHandler.SaveConfig();
|
||||
}
|
||||
await e.Channel.SendMessage($"🆗 `Removed playing string #{num}`({str})");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
using Discord.Commands;
|
||||
using NadekoBot.Classes.Permissions;
|
||||
using NadekoBot.Commands;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace NadekoBot.Modules.Administration.Commands
|
||||
{
|
||||
internal class RatelimitCommand : DiscordCommand
|
||||
{
|
||||
|
||||
public static ConcurrentDictionary<ulong, ConcurrentDictionary<ulong, DateTime>> RatelimitingChannels = new ConcurrentDictionary<ulong, ConcurrentDictionary<ulong, DateTime>>();
|
||||
|
||||
private static readonly TimeSpan ratelimitTime = new TimeSpan(0, 0, 0, 5);
|
||||
|
||||
public RatelimitCommand(DiscordModule module) : base(module)
|
||||
{
|
||||
NadekoBot.Client.MessageReceived += async (s, e) =>
|
||||
{
|
||||
if (e.Channel.IsPrivate || e.User.Id == NadekoBot.Client.CurrentUser.Id)
|
||||
return;
|
||||
ConcurrentDictionary<ulong, DateTime> userTimePair;
|
||||
if (!RatelimitingChannels.TryGetValue(e.Channel.Id, out userTimePair)) return;
|
||||
DateTime lastMessageTime;
|
||||
if (userTimePair.TryGetValue(e.User.Id, out lastMessageTime))
|
||||
{
|
||||
if (DateTime.Now - lastMessageTime < ratelimitTime)
|
||||
{
|
||||
try
|
||||
{
|
||||
await e.Message.Delete();
|
||||
}
|
||||
catch { }
|
||||
return;
|
||||
}
|
||||
}
|
||||
userTimePair.AddOrUpdate(e.User.Id, id => DateTime.Now, (id, dt) => DateTime.Now);
|
||||
};
|
||||
}
|
||||
|
||||
internal override void Init(CommandGroupBuilder cgb)
|
||||
{
|
||||
cgb.CreateCommand(Module.Prefix + "slowmode")
|
||||
.Description("Toggles slow mode. When ON, users will be able to send only 1 message every 5 seconds.")
|
||||
.Parameter("minutes", ParameterType.Optional)
|
||||
.AddCheck(SimpleCheckers.ManageMessages())
|
||||
.Do(async e =>
|
||||
{
|
||||
//var minutesStr = e.GetArg("minutes");
|
||||
//if (string.IsNullOrWhiteSpace(minutesStr)) {
|
||||
// RatelimitingChannels.Remove(e.Channel.Id);
|
||||
// return;
|
||||
//}
|
||||
ConcurrentDictionary<ulong, DateTime> throwaway;
|
||||
if (RatelimitingChannels.TryRemove(e.Channel.Id, out throwaway))
|
||||
{
|
||||
await e.Channel.SendMessage("Slow mode disabled.");
|
||||
return;
|
||||
}
|
||||
if (RatelimitingChannels.TryAdd(e.Channel.Id, new ConcurrentDictionary<ulong, DateTime>()))
|
||||
{
|
||||
await e.Channel.SendMessage("Slow mode initiated. " +
|
||||
"Users can't send more than 1 message every 5 seconds.");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,159 @@
|
||||
using Discord.Commands;
|
||||
using NadekoBot.Classes;
|
||||
using NadekoBot.Classes.Permissions;
|
||||
using NadekoBot.Commands;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NadekoBot.Modules.Administration.Commands
|
||||
{
|
||||
internal class SelfAssignedRolesCommand : DiscordCommand
|
||||
{
|
||||
public SelfAssignedRolesCommand(DiscordModule module) : base(module) { }
|
||||
internal override void Init(CommandGroupBuilder cgb)
|
||||
{
|
||||
cgb.CreateCommand(".asar")
|
||||
.Description("Adds a role, or list of roles separated by whitespace" +
|
||||
"(use quotations for multiword roles) to the list of self-assignable roles.\n**Usage**: .asar Gamer")
|
||||
.Parameter("roles", ParameterType.Multiple)
|
||||
.AddCheck(SimpleCheckers.CanManageRoles)
|
||||
.Do(async e =>
|
||||
{
|
||||
var config = SpecificConfigurations.Default.Of(e.Server.Id);
|
||||
var msg = new StringBuilder();
|
||||
foreach (var arg in e.Args)
|
||||
{
|
||||
var role = e.Server.FindRoles(arg.Trim()).FirstOrDefault();
|
||||
if (role == null)
|
||||
msg.AppendLine($":anger:Role **{arg}** not found.");
|
||||
else {
|
||||
if (config.ListOfSelfAssignableRoles.Contains(role.Id))
|
||||
{
|
||||
msg.AppendLine($":anger:Role **{role.Name}** is already in the list.");
|
||||
continue;
|
||||
}
|
||||
config.ListOfSelfAssignableRoles.Add(role.Id);
|
||||
msg.AppendLine($":ok:Role **{role.Name}** added to the list.");
|
||||
}
|
||||
}
|
||||
await e.Channel.SendMessage(msg.ToString());
|
||||
});
|
||||
|
||||
cgb.CreateCommand(".rsar")
|
||||
.Description("Removes a specified role from the list of self-assignable roles.")
|
||||
.Parameter("role", ParameterType.Unparsed)
|
||||
.AddCheck(SimpleCheckers.CanManageRoles)
|
||||
.Do(async e =>
|
||||
{
|
||||
var roleName = e.GetArg("role")?.Trim();
|
||||
if (string.IsNullOrWhiteSpace(roleName))
|
||||
return;
|
||||
var role = e.Server.FindRoles(roleName).FirstOrDefault();
|
||||
if (role == null)
|
||||
{
|
||||
await e.Channel.SendMessage(":anger:That role does not exist.");
|
||||
return;
|
||||
}
|
||||
var config = SpecificConfigurations.Default.Of(e.Server.Id);
|
||||
if (!config.ListOfSelfAssignableRoles.Contains(role.Id))
|
||||
{
|
||||
await e.Channel.SendMessage(":anger:That role is not self-assignable.");
|
||||
return;
|
||||
}
|
||||
config.ListOfSelfAssignableRoles.Remove(role.Id);
|
||||
await e.Channel.SendMessage($":ok:**{role.Name}** has been removed from the list of self-assignable roles");
|
||||
});
|
||||
|
||||
cgb.CreateCommand(".lsar")
|
||||
.Description("Lits all self-assignable roles.")
|
||||
.Parameter("roles", ParameterType.Multiple)
|
||||
.Do(async e =>
|
||||
{
|
||||
var config = SpecificConfigurations.Default.Of(e.Server.Id);
|
||||
var msg = new StringBuilder($"There are `{config.ListOfSelfAssignableRoles.Count}` self assignable roles:\n");
|
||||
var toRemove = new HashSet<ulong>();
|
||||
foreach (var roleId in config.ListOfSelfAssignableRoles)
|
||||
{
|
||||
var role = e.Server.GetRole(roleId);
|
||||
if (role == null)
|
||||
{
|
||||
msg.Append($"`{roleId} not found. Cleaned up.`, ");
|
||||
toRemove.Add(roleId);
|
||||
}
|
||||
else {
|
||||
msg.Append($"**{role.Name}**, ");
|
||||
}
|
||||
}
|
||||
foreach (var id in toRemove)
|
||||
{
|
||||
config.ListOfSelfAssignableRoles.Remove(id);
|
||||
}
|
||||
await e.Channel.SendMessage(msg.ToString());
|
||||
});
|
||||
|
||||
cgb.CreateCommand(".iam")
|
||||
.Description("Adds a role to you that you choose. " +
|
||||
"Role must be on a list of self-assignable roles." +
|
||||
"\n**Usage**: .iam Gamer")
|
||||
.Parameter("role", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
var roleName = e.GetArg("role")?.Trim();
|
||||
if (string.IsNullOrWhiteSpace(roleName))
|
||||
return;
|
||||
var role = e.Server.FindRoles(roleName).FirstOrDefault();
|
||||
if (role == null)
|
||||
{
|
||||
await e.Channel.SendMessage(":anger:That role does not exist.");
|
||||
return;
|
||||
}
|
||||
var config = SpecificConfigurations.Default.Of(e.Server.Id);
|
||||
if (!config.ListOfSelfAssignableRoles.Contains(role.Id))
|
||||
{
|
||||
await e.Channel.SendMessage(":anger:That role is not self-assignable.");
|
||||
return;
|
||||
}
|
||||
if (e.User.HasRole(role))
|
||||
{
|
||||
await e.Channel.SendMessage($":anger:You already have {role.Name} role.");
|
||||
return;
|
||||
}
|
||||
await e.User.AddRoles(role);
|
||||
await e.Channel.SendMessage($":ok:You now have {role.Name} role.");
|
||||
});
|
||||
|
||||
cgb.CreateCommand(".iamn")
|
||||
.Alias(".iamnot")
|
||||
.Description("Removes a role to you that you choose. " +
|
||||
"Role must be on a list of self-assignable roles." +
|
||||
"\n**Usage**: .iamn Gamer")
|
||||
.Parameter("role", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
var roleName = e.GetArg("role")?.Trim();
|
||||
if (string.IsNullOrWhiteSpace(roleName))
|
||||
return;
|
||||
var role = e.Server.FindRoles(roleName).FirstOrDefault();
|
||||
if (role == null)
|
||||
{
|
||||
await e.Channel.SendMessage(":anger:That role does not exist.");
|
||||
return;
|
||||
}
|
||||
var config = SpecificConfigurations.Default.Of(e.Server.Id);
|
||||
if (!config.ListOfSelfAssignableRoles.Contains(role.Id))
|
||||
{
|
||||
await e.Channel.SendMessage(":anger:That role is not self-assignable.");
|
||||
return;
|
||||
}
|
||||
if (!e.User.HasRole(role))
|
||||
{
|
||||
await e.Channel.SendMessage($":anger:You don't have {role.Name} role.");
|
||||
return;
|
||||
}
|
||||
await e.User.RemoveRoles(role);
|
||||
await e.Channel.SendMessage($":ok:Successfuly removed {role.Name} role from you.");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
295
NadekoBot/Modules/Administration/Commands/ServerGreetCommand.cs
Normal file
295
NadekoBot/Modules/Administration/Commands/ServerGreetCommand.cs
Normal file
@ -0,0 +1,295 @@
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using NadekoBot.Commands;
|
||||
using NadekoBot.Extensions;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
|
||||
/* Voltana's legacy
|
||||
public class AsyncLazy<T> : Lazy<Task<T>>
|
||||
{
|
||||
public AsyncLazy(Func<T> valueFactory) :
|
||||
base(() => Task.Factory.StartNew(valueFactory)) { }
|
||||
|
||||
public AsyncLazy(Func<Task<T>> taskFactory) :
|
||||
base(() => Task.Factory.StartNew(() => taskFactory()).Unwrap()) { }
|
||||
|
||||
public TaskAwaiter<T> GetAwaiter() { return Value.GetAwaiter(); }
|
||||
}
|
||||
*/
|
||||
|
||||
namespace NadekoBot.Modules.Administration.Commands
|
||||
{
|
||||
internal class ServerGreetCommand : DiscordCommand
|
||||
{
|
||||
|
||||
public static ConcurrentDictionary<ulong, AnnounceControls> AnnouncementsDictionary;
|
||||
|
||||
public static long Greeted = 0;
|
||||
|
||||
public ServerGreetCommand(DiscordModule module) : base(module)
|
||||
{
|
||||
AnnouncementsDictionary = new ConcurrentDictionary<ulong, AnnounceControls>();
|
||||
|
||||
NadekoBot.Client.UserJoined += UserJoined;
|
||||
NadekoBot.Client.UserLeft += UserLeft;
|
||||
|
||||
var data = Classes.DbHandler.Instance.GetAllRows<Classes._DataModels.Announcement>();
|
||||
|
||||
if (!data.Any()) return;
|
||||
foreach (var obj in data)
|
||||
AnnouncementsDictionary.TryAdd((ulong)obj.ServerId, new AnnounceControls(obj));
|
||||
}
|
||||
|
||||
private async void UserLeft(object sender, UserEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!AnnouncementsDictionary.ContainsKey(e.Server.Id) ||
|
||||
!AnnouncementsDictionary[e.Server.Id].Bye) return;
|
||||
|
||||
var controls = AnnouncementsDictionary[e.Server.Id];
|
||||
var channel = NadekoBot.Client.GetChannel(controls.ByeChannel);
|
||||
var msg = controls.ByeText.Replace("%user%", "**" + e.User.Name + "**").Trim();
|
||||
if (string.IsNullOrEmpty(msg))
|
||||
return;
|
||||
|
||||
if (controls.ByePM)
|
||||
{
|
||||
Greeted++;
|
||||
try
|
||||
{
|
||||
await e.User.SendMessage($"`Farewell Message From {e.Server?.Name}`\n" + msg);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
else {
|
||||
if (channel == null) return;
|
||||
Greeted++;
|
||||
await channel.Send(msg);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private async void UserJoined(object sender, Discord.UserEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!AnnouncementsDictionary.ContainsKey(e.Server.Id) ||
|
||||
!AnnouncementsDictionary[e.Server.Id].Greet) return;
|
||||
|
||||
var controls = AnnouncementsDictionary[e.Server.Id];
|
||||
var channel = NadekoBot.Client.GetChannel(controls.GreetChannel);
|
||||
|
||||
var msg = controls.GreetText.Replace("%user%", e.User.Mention).Trim();
|
||||
if (string.IsNullOrEmpty(msg))
|
||||
return;
|
||||
if (controls.GreetPM)
|
||||
{
|
||||
Greeted++;
|
||||
await e.User.SendMessage($"`Welcome Message From {e.Server.Name}`\n" + msg);
|
||||
}
|
||||
else {
|
||||
if (channel == null) return;
|
||||
Greeted++;
|
||||
await channel.Send(msg);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
public class AnnounceControls
|
||||
{
|
||||
private Classes._DataModels.Announcement _model { get; }
|
||||
|
||||
public bool Greet {
|
||||
get { return _model.Greet; }
|
||||
set { _model.Greet = value; Save(); }
|
||||
}
|
||||
|
||||
public ulong GreetChannel {
|
||||
get { return (ulong)_model.GreetChannelId; }
|
||||
set { _model.GreetChannelId = (long)value; Save(); }
|
||||
}
|
||||
|
||||
public bool GreetPM {
|
||||
get { return _model.GreetPM; }
|
||||
set { _model.GreetPM = value; Save(); }
|
||||
}
|
||||
|
||||
public bool ByePM {
|
||||
get { return _model.ByePM; }
|
||||
set { _model.ByePM = value; Save(); }
|
||||
}
|
||||
|
||||
public string GreetText {
|
||||
get { return _model.GreetText; }
|
||||
set { _model.GreetText = value; Save(); }
|
||||
}
|
||||
|
||||
public bool Bye {
|
||||
get { return _model.Bye; }
|
||||
set { _model.Bye = value; Save(); }
|
||||
}
|
||||
public ulong ByeChannel {
|
||||
get { return (ulong)_model.ByeChannelId; }
|
||||
set { _model.ByeChannelId = (long)value; Save(); }
|
||||
}
|
||||
|
||||
public string ByeText {
|
||||
get { return _model.ByeText; }
|
||||
set { _model.ByeText = value; Save(); }
|
||||
}
|
||||
|
||||
public ulong ServerId {
|
||||
get { return (ulong)_model.ServerId; }
|
||||
set { _model.ServerId = (long)value; }
|
||||
}
|
||||
|
||||
public AnnounceControls(Classes._DataModels.Announcement model)
|
||||
{
|
||||
this._model = model;
|
||||
}
|
||||
|
||||
public AnnounceControls(ulong serverId)
|
||||
{
|
||||
this._model = new Classes._DataModels.Announcement();
|
||||
ServerId = serverId;
|
||||
}
|
||||
|
||||
internal bool ToggleBye(ulong id)
|
||||
{
|
||||
if (Bye)
|
||||
{
|
||||
return Bye = false;
|
||||
}
|
||||
else {
|
||||
ByeChannel = id;
|
||||
return Bye = true;
|
||||
}
|
||||
}
|
||||
|
||||
internal bool ToggleGreet(ulong id)
|
||||
{
|
||||
if (Greet)
|
||||
{
|
||||
return Greet = false;
|
||||
}
|
||||
else {
|
||||
GreetChannel = id;
|
||||
return Greet = true;
|
||||
}
|
||||
}
|
||||
internal bool ToggleGreetPM() => GreetPM = !GreetPM;
|
||||
internal bool ToggleByePM() => ByePM = !ByePM;
|
||||
|
||||
private void Save()
|
||||
{
|
||||
Classes.DbHandler.Instance.Save(_model);
|
||||
}
|
||||
}
|
||||
|
||||
internal override void Init(CommandGroupBuilder cgb)
|
||||
{
|
||||
|
||||
cgb.CreateCommand(Module.Prefix + "greet")
|
||||
.Description("Enables or Disables anouncements on the current channel when someone joins the server.")
|
||||
.Do(async e =>
|
||||
{
|
||||
if (!e.User.ServerPermissions.ManageServer) return;
|
||||
if (!AnnouncementsDictionary.ContainsKey(e.Server.Id))
|
||||
AnnouncementsDictionary.TryAdd(e.Server.Id, new AnnounceControls(e.Server.Id));
|
||||
|
||||
var controls = AnnouncementsDictionary[e.Server.Id];
|
||||
|
||||
if (controls.ToggleGreet(e.Channel.Id))
|
||||
await e.Channel.SendMessage("Greet announcements enabled on this channel.");
|
||||
else
|
||||
await e.Channel.SendMessage("Greet announcements disabled.");
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Module.Prefix + "greetmsg")
|
||||
.Description("Sets a new announce message. Type %user% if you want to mention the new member.\n**Usage**: .greetmsg Welcome to the server, %user%.")
|
||||
.Parameter("msg", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
if (!e.User.ServerPermissions.ManageServer) return;
|
||||
if (e.GetArg("msg") == null) return;
|
||||
if (!AnnouncementsDictionary.ContainsKey(e.Server.Id))
|
||||
AnnouncementsDictionary.TryAdd(e.Server.Id, new AnnounceControls(e.Server.Id));
|
||||
|
||||
AnnouncementsDictionary[e.Server.Id].GreetText = e.GetArg("msg");
|
||||
await e.Channel.SendMessage("New greet message set.");
|
||||
if (!AnnouncementsDictionary[e.Server.Id].Greet)
|
||||
await e.Channel.SendMessage("Enable greet messsages by typing `.greet`");
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Module.Prefix + "bye")
|
||||
.Description("Enables or Disables anouncements on the current channel when someone leaves the server.")
|
||||
.Do(async e =>
|
||||
{
|
||||
if (!e.User.ServerPermissions.ManageServer) return;
|
||||
if (!AnnouncementsDictionary.ContainsKey(e.Server.Id))
|
||||
AnnouncementsDictionary.TryAdd(e.Server.Id, new AnnounceControls(e.Server.Id));
|
||||
|
||||
var controls = AnnouncementsDictionary[e.Server.Id];
|
||||
|
||||
if (controls.ToggleBye(e.Channel.Id))
|
||||
await e.Channel.SendMessage("Bye announcements enabled on this channel.");
|
||||
else
|
||||
await e.Channel.SendMessage("Bye announcements disabled.");
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Module.Prefix + "byemsg")
|
||||
.Description("Sets a new announce leave message. Type %user% if you want to mention the new member.\n**Usage**: .byemsg %user% has left the server.")
|
||||
.Parameter("msg", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
if (!e.User.ServerPermissions.ManageServer) return;
|
||||
if (e.GetArg("msg") == null) return;
|
||||
if (!AnnouncementsDictionary.ContainsKey(e.Server.Id))
|
||||
AnnouncementsDictionary.TryAdd(e.Server.Id, new AnnounceControls(e.Server.Id));
|
||||
|
||||
AnnouncementsDictionary[e.Server.Id].ByeText = e.GetArg("msg");
|
||||
await e.Channel.SendMessage("New bye message set.");
|
||||
if (!AnnouncementsDictionary[e.Server.Id].Bye)
|
||||
await e.Channel.SendMessage("Enable bye messsages by typing `.bye`.");
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Module.Prefix + "byepm")
|
||||
.Description("Toggles whether the good bye messages will be sent in a PM or in the text channel.")
|
||||
.Do(async e =>
|
||||
{
|
||||
if (!e.User.ServerPermissions.ManageServer) return;
|
||||
if (!AnnouncementsDictionary.ContainsKey(e.Server.Id))
|
||||
AnnouncementsDictionary.TryAdd(e.Server.Id, new AnnounceControls(e.Server.Id));
|
||||
|
||||
AnnouncementsDictionary[e.Server.Id].ToggleByePM();
|
||||
if (AnnouncementsDictionary[e.Server.Id].ByePM)
|
||||
await e.Channel.SendMessage("Bye messages will be sent in a PM from now on.\n ⚠ Keep in mind this might fail if the user and the bot have no common servers after the user leaves.");
|
||||
else
|
||||
await e.Channel.SendMessage("Bye messages will be sent in a bound channel from now on.");
|
||||
if (!AnnouncementsDictionary[e.Server.Id].Bye)
|
||||
await e.Channel.SendMessage("Enable bye messsages by typing `.bye`, and set the bye message using `.byemsg`");
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Module.Prefix + "greetpm")
|
||||
.Description("Toggles whether the greet messages will be sent in a PM or in the text channel.")
|
||||
.Do(async e =>
|
||||
{
|
||||
if (!e.User.ServerPermissions.ManageServer) return;
|
||||
if (!AnnouncementsDictionary.ContainsKey(e.Server.Id))
|
||||
AnnouncementsDictionary.TryAdd(e.Server.Id, new AnnounceControls(e.Server.Id));
|
||||
|
||||
AnnouncementsDictionary[e.Server.Id].ToggleGreetPM();
|
||||
if (AnnouncementsDictionary[e.Server.Id].GreetPM)
|
||||
await e.Channel.SendMessage("Greet messages will be sent in a PM from now on.");
|
||||
else
|
||||
await e.Channel.SendMessage("Greet messages will be sent in a bound channel from now on.");
|
||||
if (!AnnouncementsDictionary[e.Server.Id].Greet)
|
||||
await e.Channel.SendMessage("Enable greet messsages by typing `.greet`, and set the greet message using `.greetmsg`");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using NadekoBot.Commands;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NadekoBot.Modules.Administration.Commands
|
||||
{
|
||||
internal class VoiceNotificationCommand : DiscordCommand
|
||||
{
|
||||
|
||||
//voicechannel/text channel
|
||||
private readonly ConcurrentDictionary<Channel, Channel> subscribers = new ConcurrentDictionary<Channel, Channel>();
|
||||
|
||||
public Func<CommandEventArgs, Task> DoFunc() => async e =>
|
||||
{
|
||||
var arg = e.GetArg("voice_name");
|
||||
if (string.IsNullOrWhiteSpace("voice_name"))
|
||||
return;
|
||||
var voiceChannel = e.Server.FindChannels(arg, ChannelType.Voice).FirstOrDefault();
|
||||
if (voiceChannel == null)
|
||||
return;
|
||||
if (subscribers.ContainsKey(voiceChannel))
|
||||
{
|
||||
await e.Channel.SendMessage("`Voice channel notifications disabled.`");
|
||||
return;
|
||||
}
|
||||
if (subscribers.TryAdd(voiceChannel, e.Channel))
|
||||
{
|
||||
await e.Channel.SendMessage("`Voice channel notifications enabled.`");
|
||||
}
|
||||
};
|
||||
|
||||
internal override void Init(CommandGroupBuilder cgb)
|
||||
{
|
||||
cgb.CreateCommand(Module.Prefix + "voicenotif")
|
||||
.Description("Enables notifications on who joined/left the voice channel.\n**Usage**:.voicenotif Karaoke club")
|
||||
.Parameter("voice_name", ParameterType.Unparsed)
|
||||
.Do(DoFunc());
|
||||
}
|
||||
|
||||
public VoiceNotificationCommand(DiscordModule module) : base(module) { }
|
||||
}
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using NadekoBot.Classes;
|
||||
using NadekoBot.Classes.Permissions;
|
||||
using NadekoBot.Commands;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using ChPermOverride = Discord.ChannelPermissionOverrides;
|
||||
|
||||
namespace NadekoBot.Modules.Administration.Commands
|
||||
{
|
||||
internal class VoicePlusTextCommand : DiscordCommand
|
||||
{
|
||||
|
||||
public VoicePlusTextCommand(DiscordModule module) : base(module)
|
||||
{
|
||||
// changing servers may cause bugs
|
||||
NadekoBot.Client.UserUpdated += async (sender, e) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (e.Server == null)
|
||||
return;
|
||||
var config = SpecificConfigurations.Default.Of(e.Server.Id);
|
||||
if (e.Before.VoiceChannel == e.After.VoiceChannel) return;
|
||||
if (!config.VoicePlusTextEnabled)
|
||||
return;
|
||||
var serverPerms = e.Server.GetUser(NadekoBot.Client.CurrentUser.Id)?.ServerPermissions;
|
||||
if (serverPerms == null)
|
||||
return;
|
||||
if (!serverPerms.Value.ManageChannels || !serverPerms.Value.ManageRoles)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
await e.Server.Owner.SendMessage(
|
||||
"I don't have manage server and/or Manage Channels permission," +
|
||||
$" so I cannot run voice+text on **{e.Server.Name}** server.");
|
||||
}
|
||||
catch { } // meh
|
||||
config.VoicePlusTextEnabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var beforeVch = e.Before.VoiceChannel;
|
||||
if (beforeVch != null)
|
||||
{
|
||||
var textChannel =
|
||||
e.Server.FindChannels(GetChannelName(beforeVch.Name), ChannelType.Text).FirstOrDefault();
|
||||
if (textChannel != null)
|
||||
await textChannel.AddPermissionsRule(e.Before,
|
||||
new ChPermOverride(readMessages: PermValue.Deny,
|
||||
sendMessages: PermValue.Deny));
|
||||
}
|
||||
var afterVch = e.After.VoiceChannel;
|
||||
if (afterVch != null)
|
||||
{
|
||||
var textChannel = e.Server.FindChannels(
|
||||
GetChannelName(afterVch.Name),
|
||||
ChannelType.Text)
|
||||
.FirstOrDefault();
|
||||
if (textChannel == null)
|
||||
{
|
||||
textChannel = (await e.Server.CreateChannel(GetChannelName(afterVch.Name), ChannelType.Text));
|
||||
await textChannel.AddPermissionsRule(e.Server.EveryoneRole,
|
||||
new ChPermOverride(readMessages: PermValue.Deny,
|
||||
sendMessages: PermValue.Deny));
|
||||
}
|
||||
await textChannel.AddPermissionsRule(e.After,
|
||||
new ChPermOverride(readMessages: PermValue.Allow,
|
||||
sendMessages: PermValue.Allow));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private string GetChannelName(string voiceName) =>
|
||||
voiceName.Replace(" ", "-").Trim() + "-voice";
|
||||
|
||||
internal override void Init(CommandGroupBuilder cgb)
|
||||
{
|
||||
cgb.CreateCommand(Module.Prefix + "v+t")
|
||||
.Alias(Module.Prefix + "voice+text")
|
||||
.Description("Creates a text channel for each voice channel only users in that voice channel can see." +
|
||||
"If you are server owner, keep in mind you will see them all the time regardless.")
|
||||
.AddCheck(SimpleCheckers.ManageChannels())
|
||||
.AddCheck(SimpleCheckers.CanManageRoles)
|
||||
.Do(async e =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var config = SpecificConfigurations.Default.Of(e.Server.Id);
|
||||
if (config.VoicePlusTextEnabled == true)
|
||||
{
|
||||
config.VoicePlusTextEnabled = false;
|
||||
foreach (var textChannel in e.Server.TextChannels.Where(c => c.Name.EndsWith("-voice")))
|
||||
{
|
||||
try
|
||||
{
|
||||
await textChannel.Delete();
|
||||
}
|
||||
catch
|
||||
{
|
||||
await
|
||||
e.Channel.SendMessage(
|
||||
":anger: Error: Most likely i don't have permissions to do this.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
await e.Channel.SendMessage("Successfuly removed voice + text feature.");
|
||||
return;
|
||||
}
|
||||
config.VoicePlusTextEnabled = true;
|
||||
await e.Channel.SendMessage("Successfuly enabled voice + text feature. " +
|
||||
"**Make sure the bot has manage roles and manage channels permissions**");
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await e.Channel.SendMessage(ex.ToString());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user