Bot::Client: Rename classes and move to separate namespace
Bot::Client: Remove audio commands Delete Mod_Audio Create Mod_DiscordLoggermaster
parent
41c1a365a7
commit
d09924cb27
|
@ -24,38 +24,24 @@ using CommandFuncDict =
|
|||
|
||||
namespace ProjectGolan.Vrobot3
|
||||
{
|
||||
//
|
||||
// BotCommand
|
||||
//
|
||||
// Delegate type for bot commands.
|
||||
//
|
||||
public delegate void BotCommand(User usr, Channel channel, String msg);
|
||||
|
||||
//
|
||||
// CommandDict
|
||||
//
|
||||
// Dictionary of bot commands.
|
||||
//
|
||||
public class CommandDict : Dictionary<String, BotCommandStructure> {}
|
||||
|
||||
//
|
||||
// Bot
|
||||
//
|
||||
public partial class Bot
|
||||
{
|
||||
private readonly Dictionary<ulong, String> lastLine;
|
||||
private readonly IBotClient client;
|
||||
private readonly Client.IChatClient client;
|
||||
|
||||
public List<IBotModule> modules { get; private set; }
|
||||
public CommandFuncDict cmdfuncs { get; private set; }
|
||||
public readonly BotInfo info;
|
||||
|
||||
public bool isInAudioChannel => client.isInAudioChannel();
|
||||
public BotClientInfo clientInfo => client.info;
|
||||
public Client.ClientInfo clientInfo => client.info;
|
||||
public Client.IChatClient getClient() => client;
|
||||
|
||||
//
|
||||
// Bot constructor
|
||||
//
|
||||
public Bot(BotInfo info)
|
||||
{
|
||||
this.info = info;
|
||||
|
@ -65,8 +51,8 @@ namespace ProjectGolan.Vrobot3
|
|||
|
||||
switch(info.serverType)
|
||||
{
|
||||
case "IRC": this.client = new BotClientIRC(this); break;
|
||||
case "Discord": this.client = new BotClientDiscord(this); break;
|
||||
case "IRC": this.client = new Client.ClientIRC(this); break;
|
||||
case "Discord": this.client = new Client.ClientDiscord(this); break;
|
||||
default: throw new BotConfigurationException("Invalid server type.");
|
||||
}
|
||||
|
||||
|
@ -84,9 +70,6 @@ namespace ProjectGolan.Vrobot3
|
|||
cmdfuncs.Add(kvp.Key, Tuple.Create(mod, kvp.Value));
|
||||
}
|
||||
|
||||
//
|
||||
// client
|
||||
//
|
||||
public void connect() => client.connect();
|
||||
|
||||
public void action(Channel channel, String msg) =>
|
||||
|
@ -109,12 +92,6 @@ namespace ProjectGolan.Vrobot3
|
|||
public void reply(User usr, ulong id, String msg) =>
|
||||
message(id, usr.name + ": " + msg);
|
||||
|
||||
public void partAudioChannel() => client.partAudioChannel();
|
||||
public Task playAudioFile(String file) => client.playAudioFile(file);
|
||||
|
||||
//
|
||||
// disconnect
|
||||
//
|
||||
public void disconnect()
|
||||
{
|
||||
cmdfuncs.Clear();
|
||||
|
@ -122,24 +99,6 @@ namespace ProjectGolan.Vrobot3
|
|||
client.disconnect();
|
||||
}
|
||||
|
||||
//
|
||||
// joinAudioChannel
|
||||
//
|
||||
public async Task<bool> joinAudioChannel(User user)
|
||||
{
|
||||
var channel = client.getAudioChannel(user);
|
||||
if(channel != null)
|
||||
{
|
||||
await client.joinAudioChannel(channel);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// checkModPermissions
|
||||
//
|
||||
public bool checkModPermissions(Channel channel, Type mod)
|
||||
{
|
||||
String[] enables;
|
||||
|
|
|
@ -59,11 +59,11 @@ namespace ProjectGolan.Vrobot3
|
|||
return false;
|
||||
|
||||
if(attribute is BotModuleIRCAttribute &&
|
||||
!(client is BotClientIRC))
|
||||
!(client is Client.ClientIRC))
|
||||
return false;
|
||||
|
||||
if(attribute is BotModuleDiscordAttribute &&
|
||||
!(client is BotClientDiscord))
|
||||
!(client is Client.ClientDiscord))
|
||||
return false;
|
||||
|
||||
if(attribute is BotModuleRequiresAudioAttribute &&
|
||||
|
|
|
@ -13,12 +13,9 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ProjectGolan.Vrobot3
|
||||
namespace ProjectGolan.Vrobot3.Client
|
||||
{
|
||||
//
|
||||
// BotClientInfo
|
||||
//
|
||||
public class BotClientInfo
|
||||
public class ClientInfo
|
||||
{
|
||||
public bool hasAudio;
|
||||
public bool hasColors;
|
||||
|
@ -27,17 +24,14 @@ namespace ProjectGolan.Vrobot3
|
|||
public bool shortMessages;
|
||||
}
|
||||
|
||||
//
|
||||
// IBotClient
|
||||
//
|
||||
public abstract class IBotClient
|
||||
public abstract class IChatClient
|
||||
{
|
||||
protected Bot bot;
|
||||
public BotClientInfo info { get; protected set; }
|
||||
public ClientInfo info { get; protected set; }
|
||||
|
||||
protected IBotClient(Bot bot)
|
||||
protected IChatClient(Bot bot)
|
||||
{
|
||||
this.info = new BotClientInfo();
|
||||
this.info = new ClientInfo();
|
||||
this.bot = bot;
|
||||
}
|
||||
|
||||
|
@ -58,16 +52,6 @@ namespace ProjectGolan.Vrobot3
|
|||
|
||||
// user
|
||||
public abstract bool userPermitted(User usr, BotRole role);
|
||||
|
||||
// audio
|
||||
public virtual ChannelAudio getAudioChannel(User usr) =>
|
||||
new ChannelAudio();
|
||||
public virtual async Task joinAudioChannel(ChannelAudio channel) =>
|
||||
await Task.FromResult(0);
|
||||
public virtual void partAudioChannel() {}
|
||||
public virtual bool isInAudioChannel() => false;
|
||||
public virtual async Task playAudioFile(String file) =>
|
||||
await Task.FromResult(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,24 +15,15 @@ using System.Linq;
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Diagnostics;
|
||||
using Discord.Audio;
|
||||
|
||||
namespace ProjectGolan.Vrobot3
|
||||
namespace ProjectGolan.Vrobot3.Client
|
||||
{
|
||||
//
|
||||
// BotClientDiscord
|
||||
//
|
||||
public class BotClientDiscord : IBotClient
|
||||
public class ClientDiscord : IChatClient
|
||||
{
|
||||
private Discord.DiscordClient client;
|
||||
private Discord.Audio.IAudioClient audioClient;
|
||||
private Discord.Server server;
|
||||
public Discord.DiscordClient client;
|
||||
public Discord.Server server;
|
||||
|
||||
//
|
||||
// BotClientDiscord constructor
|
||||
//
|
||||
public BotClientDiscord(Bot bot) :
|
||||
base(bot)
|
||||
public ClientDiscord(Bot bot) : base(bot)
|
||||
{
|
||||
this.client = new Discord.DiscordClient();
|
||||
|
||||
|
@ -61,24 +52,16 @@ namespace ProjectGolan.Vrobot3
|
|||
bot.onMessage(usr, channel, evt.Message.Text);
|
||||
}
|
||||
};
|
||||
|
||||
this.client.UsingAudio(x => x.Mode = AudioMode.Outgoing);
|
||||
}
|
||||
|
||||
//
|
||||
// getUser
|
||||
//
|
||||
private Discord.User getUser(User usr)
|
||||
public Discord.User getUser(User usr)
|
||||
{
|
||||
if(server == null)
|
||||
server = client.GetServer(ulong.Parse(bot.info.serverAddr));
|
||||
return server.GetUser(ulong.Parse(usr.hostname));
|
||||
}
|
||||
|
||||
//
|
||||
// checkRole
|
||||
//
|
||||
private bool checkRole(User usr, String[] strings)
|
||||
public bool checkRole(User usr, String[] strings)
|
||||
{
|
||||
var duser = getUser(usr);
|
||||
|
||||
|
@ -102,9 +85,6 @@ namespace ProjectGolan.Vrobot3
|
|||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// connect
|
||||
//
|
||||
public override void connect()
|
||||
{
|
||||
Console.WriteLine("{0}: Creating connection.", bot.info.serverName);
|
||||
|
@ -115,42 +95,26 @@ namespace ProjectGolan.Vrobot3
|
|||
});
|
||||
}
|
||||
|
||||
//
|
||||
// disconnect
|
||||
//
|
||||
public override void disconnect()
|
||||
{
|
||||
if(client != null)
|
||||
{
|
||||
partAudioChannel();
|
||||
client.Disconnect();
|
||||
client = null;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// sendAction
|
||||
//
|
||||
public override void sendAction(Channel channel, String msg) =>
|
||||
client.GetChannel(channel.id)?.SendMessage(
|
||||
"_" + Discord.Format.Escape(msg) + "_");
|
||||
"_" + Discord.Format.Escape(msg ?? String.Empty) + "_");
|
||||
|
||||
//
|
||||
// sendMessage
|
||||
//
|
||||
public override void sendMessage(Channel channel, String msg) =>
|
||||
client.GetChannel(channel.id)?.SendMessage(Discord.Format.Escape(msg));
|
||||
client.GetChannel(channel.id)?.SendMessage(Discord.Format.Escape(msg ?? String.Empty));
|
||||
|
||||
//
|
||||
// sendMessageRaw
|
||||
//
|
||||
public override void sendMessageRaw(Channel channel, String msg) =>
|
||||
sendMessage(channel,
|
||||
"```" + Discord.Format.Escape(msg ?? String.Empty) + "```");
|
||||
|
||||
//
|
||||
// getChannel
|
||||
//
|
||||
public override Channel getChannel(ulong id)
|
||||
{
|
||||
var dchannel = client.GetChannel(id);
|
||||
|
@ -160,104 +124,10 @@ namespace ProjectGolan.Vrobot3
|
|||
return channel;
|
||||
}
|
||||
|
||||
//
|
||||
// userPermitted
|
||||
//
|
||||
public override bool userPermitted(User usr, BotRole role) =>
|
||||
role == BotRole.User ||
|
||||
(role == BotRole.HalfAdmin && checkRole(usr, bot.info.roles.halfadmin)) ||
|
||||
(role == BotRole.Admin && checkRole(usr, bot.info.roles.admin));
|
||||
|
||||
//
|
||||
// getAudioChannel
|
||||
//
|
||||
public override ChannelAudio getAudioChannel(User usr)
|
||||
{
|
||||
var dchannel = getUser(usr).VoiceChannel;
|
||||
if(dchannel == null) return null;
|
||||
var channel = new ChannelAudio{};
|
||||
channel.id = dchannel.Id;
|
||||
channel.name = dchannel.Name;
|
||||
return channel;
|
||||
}
|
||||
|
||||
//
|
||||
// joinAudioChannel
|
||||
//
|
||||
public override async Task joinAudioChannel(ChannelAudio channel)
|
||||
{
|
||||
if(channel == null)
|
||||
return;
|
||||
|
||||
var dchannel = client.GetChannel(channel.id);
|
||||
if(!isInAudioChannel())
|
||||
audioClient = await dchannel.JoinAudio();
|
||||
else
|
||||
await audioClient.Join(dchannel);
|
||||
}
|
||||
|
||||
//
|
||||
// partAudioChannel
|
||||
//
|
||||
public override void partAudioChannel()
|
||||
{
|
||||
if(isInAudioChannel())
|
||||
{
|
||||
audioClient.Clear();
|
||||
audioClient.Wait();
|
||||
audioClient.Disconnect();
|
||||
}
|
||||
audioClient = null;
|
||||
}
|
||||
|
||||
//
|
||||
// isInAudioChannel
|
||||
//
|
||||
public override bool isInAudioChannel() =>
|
||||
audioClient?.State == Discord.ConnectionState.Connected;
|
||||
|
||||
//
|
||||
// playAudioFile
|
||||
//
|
||||
public override async Task playAudioFile(String file)
|
||||
{
|
||||
if(!isInAudioChannel()) return;
|
||||
|
||||
var proc = Process.Start(new ProcessStartInfo{
|
||||
FileName = "ffmpeg",
|
||||
Arguments = $"-i {file} -f s16le -ar 48000 -ac 2 " +
|
||||
"-loglevel quiet pipe:1",
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = false,
|
||||
CreateNoWindow = true
|
||||
});
|
||||
|
||||
var buf = new byte[3840 * 32];
|
||||
var ostream = audioClient.OutputStream;
|
||||
var istream = proc?.StandardOutput.BaseStream;
|
||||
|
||||
try
|
||||
{
|
||||
int count;
|
||||
while(proc?.HasExited == false &&
|
||||
(count = await istream.ReadAsync(buf, 0, buf.Length)) != 0)
|
||||
{
|
||||
Thread.Sleep(8);
|
||||
await ostream.WriteAsync(buf, 0, count);
|
||||
}
|
||||
}
|
||||
catch(OperationCanceledException)
|
||||
{
|
||||
Console.WriteLine("{0}: Canceled audio stream.",
|
||||
bot.info.serverName);
|
||||
}
|
||||
finally
|
||||
{
|
||||
istream?.Dispose();
|
||||
ostream.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,18 +12,11 @@
|
|||
|
||||
using System;
|
||||
|
||||
namespace ProjectGolan.Vrobot3
|
||||
namespace ProjectGolan.Vrobot3.Client
|
||||
{
|
||||
//
|
||||
// BotClientIRC
|
||||
//
|
||||
public class BotClientIRC : IBotClient
|
||||
public class ClientIRC : IChatClient
|
||||
{
|
||||
//
|
||||
// BotClientIRC constructor
|
||||
//
|
||||
public BotClientIRC(Bot bot) :
|
||||
base(bot)
|
||||
public ClientIRC(Bot bot) : base(bot)
|
||||
{
|
||||
this.info.hasAudio = false;
|
||||
this.info.hasColors = true;
|
||||
|
|
|
@ -1,185 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright © 2016 Project Golan
|
||||
//
|
||||
// See "LICENSE" for more information.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Audio-based commands.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ProjectGolan.Vrobot3.Modules
|
||||
{
|
||||
//
|
||||
// Mod_Audio
|
||||
//
|
||||
[BotModuleRequiresAudio, BotModuleDisabled]
|
||||
public class Mod_Audio : IBotModule
|
||||
{
|
||||
//
|
||||
// QueueItem
|
||||
//
|
||||
class QueueItem
|
||||
{
|
||||
private Utils.URI uri;
|
||||
|
||||
public QueueItem(Utils.URI uri)
|
||||
{
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
public override String ToString() => String.Empty;
|
||||
}
|
||||
|
||||
//
|
||||
// Queue
|
||||
//
|
||||
class Queue
|
||||
{
|
||||
private TimeSpan curTime;
|
||||
private List<QueueItem> items;
|
||||
private int pos;
|
||||
|
||||
public Queue()
|
||||
{
|
||||
this.curTime = new TimeSpan();
|
||||
this.items = new List<QueueItem>();
|
||||
this.pos = 0;
|
||||
}
|
||||
|
||||
public bool addItem(Utils.URI uri)
|
||||
{
|
||||
var item = new QueueItem(uri);
|
||||
items.Add(item);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly String[] validMethods =
|
||||
{ "http", "https", "ftp", "ftps" };
|
||||
private Queue queue = new Queue();
|
||||
|
||||
//
|
||||
// Mod_Audio constructor
|
||||
//
|
||||
public Mod_Audio(Bot bot_) :
|
||||
base(bot_)
|
||||
{
|
||||
commands["queue"] = new BotCommandStructure{
|
||||
cmd = cmdQueue,
|
||||
help = "Add an item (or items) to the audio queue.\n" +
|
||||
"Syntax: .queue uri...\n" +
|
||||
"Example: .queue https://www.youtube.com/watch?v=13pL0TiOiHM"
|
||||
};
|
||||
|
||||
commands["play"] = new BotCommandStructure{
|
||||
cmd = cmdPlay,
|
||||
help = "Set the currently playing item in the queue. " +
|
||||
"If a URL is given, queues and plays that.\n" +
|
||||
"Syntax: .play [number|uri]\n" +
|
||||
"Example: .play 5\n" +
|
||||
"Example: .play https://www.youtube.com/watch?v=13pL0TiOiHM"
|
||||
};
|
||||
|
||||
commands["lsqueue"] = new BotCommandStructure{
|
||||
cmd = cmdListQueue,
|
||||
help = "Lists queue items.\n" +
|
||||
"Syntax: .lsqueue"
|
||||
};
|
||||
|
||||
commands["summon"] = new BotCommandStructure{
|
||||
cmd = cmdSummon,
|
||||
help = "Makes the bot join your audio channel.\n" +
|
||||
"Syntax: .summon"
|
||||
};
|
||||
|
||||
commands["vanquish"] = new BotCommandStructure{
|
||||
cmd = cmdVanquish,
|
||||
help = "Makes the bot leave their audio channel.\n" +
|
||||
"Syntax: %vanquish",
|
||||
role = BotRole.HalfAdmin
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// summon
|
||||
//
|
||||
private async Task<bool> summon(User usr, Channel channel)
|
||||
{
|
||||
if(bot.isInAudioChannel)
|
||||
return true;
|
||||
|
||||
if(!await bot.joinAudioChannel(usr))
|
||||
{
|
||||
bot.reply(usr, channel,
|
||||
"Couldn't find audio channel. " +
|
||||
"If you are already in an audio channel, please reconnect to " +
|
||||
"it and try again.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// cmdQueue
|
||||
//
|
||||
public void cmdQueue(User usr, Channel channel, String msg)
|
||||
{
|
||||
var uris = Utils.URI.Matches(msg);
|
||||
|
||||
if(uris == null)
|
||||
throw new CommandArgumentException("no valid URIs");
|
||||
|
||||
int loadPass = 0;
|
||||
foreach(var uri_ in uris)
|
||||
{
|
||||
var uri = uri_;
|
||||
if(uri.method == String.Empty)
|
||||
uri.method = "http";
|
||||
|
||||
if(validMethods.Contains(uri.method) &&
|
||||
queue.addItem(uri))
|
||||
loadPass++;
|
||||
}
|
||||
|
||||
bot.reply(usr, channel,
|
||||
$"Added {loadPass} item{loadPass != 1 ? "s" : ""} to the queue.");
|
||||
}
|
||||
|
||||
//
|
||||
// cmdPlay
|
||||
//
|
||||
public void cmdPlay(User usr, Channel channel, String msg)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// cmdListQueue
|
||||
//
|
||||
public void cmdListQueue(User usr, Channel channel, String msg)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// cmdSummon
|
||||
//
|
||||
public void cmdSummon(User usr, Channel channel, String msg) =>
|
||||
summon(usr, channel);
|
||||
|
||||
//
|
||||
// cmdVanquish
|
||||
//
|
||||
public void cmdVanquish(User usr, Channel channel, String msg) =>
|
||||
bot.partAudioChannel();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,294 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright © 2016 Project Golan
|
||||
//
|
||||
// See "LICENSE" for more information.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Logging.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
delegate void HaxFn(String name, String vname);
|
||||
|
||||
namespace ProjectGolan.Vrobot3.Modules
|
||||
{
|
||||
[BotModuleDiscord]
|
||||
public class Mod_DiscordLogger : IBotModule
|
||||
{
|
||||
public Mod_DiscordLogger(Bot bot) : base(bot)
|
||||
{
|
||||
var client = bot.getClient() as Client.ClientDiscord;
|
||||
|
||||
client.client.ChannelCreated +=
|
||||
catchFunc<Discord.ChannelEventArgs>(
|
||||
async (_, e) =>
|
||||
await logMsg(e.Server, "Channel created", getChannel(e.Channel)));
|
||||
|
||||
client.client.ChannelDestroyed +=
|
||||
catchFunc<Discord.ChannelEventArgs>(
|
||||
async (_, e) =>
|
||||
await logMsg(e.Server, "Channel destroyed", getChannel(e.Channel)));
|
||||
|
||||
client.client.ChannelUpdated +=
|
||||
catchFunc<Discord.ChannelUpdatedEventArgs>(async (_, e) =>
|
||||
{
|
||||
var delta = getChannelDelta(e.Before, e.After);
|
||||
if(delta != String.Empty)
|
||||
await logMsg(e.Server, "Channel updated", delta);
|
||||
});
|
||||
|
||||
client.client.MessageDeleted +=
|
||||
catchFunc<Discord.MessageEventArgs>(async (_, e) =>
|
||||
{
|
||||
if(!e.Message.User.IsBot)
|
||||
await verMsg(e.Server, "Message deleted", getMessage(e.Message));
|
||||
});
|
||||
|
||||
client.client.MessageUpdated +=
|
||||
catchFunc<Discord.MessageUpdatedEventArgs>(async (_, e) =>
|
||||
{
|
||||
var delta = getMessageDelta(e.Before, e.After);
|
||||
if(delta != String.Empty)
|
||||
await verMsg(e.Server, "Message edited", delta);
|
||||
});
|
||||
|
||||
client.client.UserBanned +=
|
||||
catchFunc<Discord.UserEventArgs>(async (_, e) =>
|
||||
await logMsg(e.Server, "User banned", getUser(e.User)));
|
||||
|
||||
client.client.UserUnbanned +=
|
||||
catchFunc<Discord.UserEventArgs>(async (_, e) =>
|
||||
await logMsg(e.Server, "User unbanned", getUser(e.User)));
|
||||
|
||||
client.client.UserJoined +=
|
||||
catchFunc<Discord.UserEventArgs>(async (_, e) =>
|
||||
await logMsg(e.Server, "User joined", getUser(e.User)));
|
||||
|
||||
client.client.UserLeft +=
|
||||
catchFunc<Discord.UserEventArgs>(async (_, e) =>
|
||||
await logMsg(e.Server, "User removed", getUser(e.User)));
|
||||
|
||||
client.client.UserUpdated +=
|
||||
catchFunc<Discord.UserUpdatedEventArgs>(async (_, e) =>
|
||||
{
|
||||
var delta = getUserDelta(e.Before, e.After);
|
||||
if(delta != String.Empty)
|
||||
await verMsg(e.Server, "User updated", delta);
|
||||
});
|
||||
}
|
||||
|
||||
private EventHandler<T> catchFunc<T>(EventHandler<T> fn)
|
||||
{
|
||||
return (object sender, T evt) =>
|
||||
{
|
||||
try
|
||||
{fn(sender, evt);}
|
||||
catch(System.Exception)
|
||||
{}
|
||||
};
|
||||
}
|
||||
|
||||
private String yesno(bool arg) => arg ? "Yes" : "No";
|
||||
|
||||
private String getTime(DateTime time)
|
||||
{
|
||||
var offs = TimeZoneInfo.Local.GetUtcOffset(time);
|
||||
return $"{time.ToShortDateString()} {time.ToLongTimeString()} " +
|
||||
$"UTC{offs.Hours.ToString("+#;-#;0")}:{offs.Minutes}";
|
||||
}
|
||||
|
||||
private String discordEscape(String str) =>
|
||||
Discord.Format.Escape(str ?? String.Empty);
|
||||
|
||||
private String getChannel(Discord.Channel channel) =>
|
||||
$"`Name :` {discordEscape(channel.Name)}\n" +
|
||||
$"`Topic :` {discordEscape(channel.Topic)}\n" +
|
||||
$"`Id :` `{channel.Id}`\n" +
|
||||
$"`Position :` `{channel.Position}`\n" +
|
||||
$"`Type :` {channel.Type.ToString()}";
|
||||
|
||||
private String getUser(Discord.User user) =>
|
||||
$"`Username :` {discordEscape(user.Name)}\n" +
|
||||
$"`Nickname :` {discordEscape(user.Nickname)}\n" +
|
||||
$"`Id :` `{user.Id}`\n" +
|
||||
$"`Is Bot :` {yesno(user.IsBot)}\n" +
|
||||
$"`Joined At :` {getTime(user.JoinedAt)}";
|
||||
|
||||
private String getMessage(Discord.Message msg) =>
|
||||
$"`Time Sent :` {getTime(msg.Timestamp)}\n" +
|
||||
$"`Channel :` {discordEscape(msg.Channel.Name)}\n" +
|
||||
$"`Id :` `{msg.Id}`\n" +
|
||||
$"`Content :` {msg.Text}\n" +
|
||||
$"\nUser info:\n{getUser(msg.User)}";
|
||||
|
||||
private String getMessageDelta(Discord.Message bfr, Discord.Message aft)
|
||||
{
|
||||
if(bfr.Text == aft.Text) return String.Empty;
|
||||
return $"`Time Sent :` {getTime(aft.Timestamp)}\n" +
|
||||
$"`Channel :` {discordEscape(aft.Channel.Name)}\n" +
|
||||
$"`Id :` `{aft.Id}`\n" +
|
||||
$"`Old Content :` {bfr.Text}\n" +
|
||||
$"`New Content :` {aft.Text}\n" +
|
||||
$"\nUser info:\n{getUser(aft.User)}";
|
||||
}
|
||||
|
||||
private String getPermDelta(Discord.ServerPermissions bfr,
|
||||
Discord.ServerPermissions aft)
|
||||
{
|
||||
var outp = String.Empty;
|
||||
|
||||
if(bfr.RawValue != aft.RawValue)
|
||||
{
|
||||
outp += $"`Old Value :` `{bfr.RawValue}`\n";
|
||||
outp += $"`New Value :` `{aft.RawValue}`\n";
|
||||
|
||||
HaxFn fn = (String name, String vname) => {
|
||||
var a = (bool)typeof(Discord.ServerPermissions)
|
||||
.GetProperty(vname).GetValue(bfr);
|
||||
var b = (bool)typeof(Discord.ServerPermissions)
|
||||
.GetProperty(vname).GetValue(aft);
|
||||
if(a != b)
|
||||
outp += $"`{name}:` {yesno(b)}\n";
|
||||
};
|
||||
|
||||
fn("Create Invite", "CreateInstantInvite");
|
||||
fn("Ban Users ", "BanMembers");
|
||||
fn("Kick Users ", "KickMembers");
|
||||
fn("Edit Channels", "ManageChannels");
|
||||
fn("Edit Server ", "ManageServer");
|
||||
fn("Join Channels", "ReadMessages");
|
||||
fn("Send Messages", "SendMessages");
|
||||
fn("Send TTS ", "SendTTSMessages");
|
||||
fn("Edit Messages", "ManageMessages");
|
||||
fn("Embed Links ", "EmbedLinks");
|
||||
fn("Attach Files ", "AttachFiles");
|
||||
fn("Ping Everyone", "MentionEveryone");
|
||||
fn("Join Voice ", "Connect");
|
||||
fn("Speak ", "Speak");
|
||||
fn("Mute Users ", "MuteMembers");
|
||||
fn("Deafen Users ", "DeafenMembers");
|
||||
fn("Move Users ", "MoveMembers");
|
||||
fn("Use VA ", "UseVoiceActivation");
|
||||
fn("Change Nick ", "ChangeNickname");
|
||||
fn("Edit Nicks ", "ManageNicknames");
|
||||
fn("Edit Roles ", "ManageRoles");
|
||||
}
|
||||
return outp;
|
||||
}
|
||||
|
||||
private String getChannelDelta(Discord.Channel bfr, Discord.Channel aft)
|
||||
{
|
||||
var outp1 = String.Empty;
|
||||
var outp2 = String.Empty;
|
||||
if(bfr.Name != aft.Name)
|
||||
{
|
||||
outp1 += "Name changed.\n";
|
||||
if(!String.IsNullOrEmpty(bfr.Name))
|
||||
outp2 += $"`Old Name :` {discordEscape(bfr.Name)}\n";
|
||||
if(!String.IsNullOrEmpty(aft.Name))
|
||||
outp2 += $"`New Name :` {discordEscape(aft.Name)}\n";
|
||||
}
|
||||
if(bfr.Id != aft.Id)
|
||||
{
|
||||
outp1 += "Id changed.\n";
|
||||
outp2 += $"`Old Id :` `{bfr.Id}`\n";
|
||||
outp2 += $"`New Id :` `{aft.Id}`\n";
|
||||
}
|
||||
if(bfr.Topic != aft.Topic)
|
||||
{
|
||||
outp1 += "Topic changed.\n";
|
||||
if(!String.IsNullOrEmpty(bfr.Topic))
|
||||
outp2 += $"`Old Topic :` {discordEscape(bfr.Topic)}\n";
|
||||
if(!String.IsNullOrEmpty(aft.Topic))
|
||||
outp2 += $"`New Topic :` {discordEscape(aft.Topic)}\n";
|
||||
}
|
||||
if(bfr.Position != aft.Position)
|
||||
{
|
||||
outp1 += "Position changed.\n";
|
||||
outp2 += $"`Old Position :` `{bfr.Position}`\n";
|
||||
outp2 += $"`New Position :` `{aft.Position}`\n";
|
||||
}
|
||||
if(outp1 != String.Empty)
|
||||
outp2 += $"\nChannel info:\n{getChannel(aft)}\n";
|
||||
return outp1 + outp2.Trim();
|
||||
}
|
||||
|
||||
private String getUserDelta(Discord.User bfr, Discord.User aft)
|
||||
{
|
||||
var outp1 = String.Empty;
|
||||
var outp2 = String.Empty;
|
||||
var perm = getPermDelta(bfr.ServerPermissions, aft.ServerPermissions);
|
||||
if(bfr.Name != aft.Name)
|
||||
{
|
||||
outp1 += "Username changed.\n";
|
||||
if(!String.IsNullOrEmpty(bfr.Name))
|
||||
outp2 += $"`Old Username :` {discordEscape(bfr.Name)}\n";
|
||||
if(!String.IsNullOrEmpty(aft.Name))
|
||||
outp2 += $"`New Username :` {discordEscape(aft.Name)}\n";
|
||||
}
|
||||
if(bfr.Nickname != aft.Nickname)
|
||||
{
|
||||
outp1 += "Nickname changed.\n";
|
||||
if(!String.IsNullOrEmpty(bfr.Nickname))
|
||||
outp2 += $"`Old Nickname :` {discordEscape(bfr.Nickname)}\n";
|
||||
if(!String.IsNullOrEmpty(aft.Nickname))
|
||||
outp2 += $"`New Nickname :` {discordEscape(aft.Nickname)}\n";
|
||||
}
|
||||
if(bfr.AvatarId != aft.AvatarId)
|
||||
{
|
||||
outp1 += "Avatar changed.\n";
|
||||
outp2 += $"`Old Avatar Id:` `{bfr.AvatarId}`\n";
|
||||
outp2 += $"`New Avatar Id:` `{aft.AvatarId}`\n";
|
||||
outp2 += $"`Old AvatarUrl:` `{bfr.AvatarUrl}`\n";
|
||||
outp2 += $"`New AvatarUrl:` `{aft.AvatarUrl}`\n";
|
||||
}
|
||||
if(bfr.Discriminator != aft.Discriminator)
|
||||
{
|
||||
outp1 += "Unique Id changed.\n";
|
||||
outp2 += $"`Old Unique Id:` `{bfr.Discriminator}`\n";
|
||||
outp2 += $"`New Unique Id:` `{aft.Discriminator}`\n";
|
||||
}
|
||||
if(bfr.Id != aft.Id)
|
||||
{
|
||||
outp1 += "Id changed.\n";
|
||||
outp2 += $"`Old Id :` `{bfr.Id}`\n";
|
||||
outp2 += $"`New Id :` `{aft.Id}`\n";
|
||||
}
|
||||
if(!String.IsNullOrEmpty(perm))
|
||||
{
|
||||
outp1 += "Permissions changed.\n";
|
||||
outp2 += perm;
|
||||
}
|
||||
if(outp1 != String.Empty)
|
||||
outp2 += $"\nUser info:\n{getUser(aft)}\n";
|
||||
return outp1 + outp2.Trim();
|
||||
}
|
||||
|
||||
private async Task sndMsg(Discord.Server server, String name,
|
||||
String type, String msg)
|
||||
{
|
||||
if(server.Id.ToString() != bot.info.serverAddr) return;
|
||||
var log = server.FindChannels(name).FirstOrDefault();
|
||||
if(log == null) return;
|
||||
var time = getTime(DateTime.Now);
|
||||
if(msg.Length > 1800)
|
||||
await log.SendMessage($"{type} at {time}\n[Omitted, too long]");
|
||||
else
|
||||
await log.SendMessage($"{type} at {time}\n{msg}");
|
||||
}
|
||||
|
||||
private async Task logMsg(Discord.Server server, String type, String msg)
|
||||
=> await sndMsg(server, "log", type, msg);
|
||||
|
||||
private async Task verMsg(Discord.Server server, String type, String msg)
|
||||
=> await sndMsg(server, "log-v", type, msg);
|
||||
}
|
||||
}
|
||||
|
|
@ -79,7 +79,7 @@
|
|||
<Compile Include="Source/Client/Discord.cs" />
|
||||
<Compile Include="Source/Client/IRC.cs" />
|
||||
<Compile Include="Source/Modules/Mod_Admin.cs" />
|
||||
<Compile Include="Source/Modules/Mod_Audio.cs" />
|
||||
<Compile Include="Source/Modules/Mod_DiscordLogger.cs" />
|
||||
<Compile Include="Source/Modules/Mod_Fun.cs" />
|
||||
<Compile Include="Source/Modules/Mod_Utils.cs" />
|
||||
<Compile Include="Source/Modules/Mod_Idgames.cs" />
|
||||
|
|
Caricamento…
Fai riferimento in un nuovo problema