mirror of https://github.com/adamdruppe/arsd.git
supporting my chocobot
This commit is contained in:
parent
09af87971f
commit
f5d4818975
101
discord.d
101
discord.d
|
@ -99,6 +99,14 @@ class DiscordChannel : DiscordEntity {
|
||||||
override string restType() {
|
override string restType() {
|
||||||
return "channels";
|
return "channels";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sendMessage(string message) {
|
||||||
|
if(message.length == 0)
|
||||||
|
message = "empty message specified";
|
||||||
|
var msg = var.emptyObject;
|
||||||
|
msg.content = message;
|
||||||
|
rest.messages.POST(msg).result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/++
|
/++
|
||||||
|
@ -158,6 +166,22 @@ class DiscordUser : DiscordMentionable {
|
||||||
auto result = api.rest.guilds[role.guild.id].members[this.id].roles[role.id].DELETE().result;
|
auto result = api.rest.guilds[role.guild.id].members[this.id].roles[role.id].DELETE().result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DiscordChannel dmChannel_;
|
||||||
|
|
||||||
|
DiscordChannel dmChannel() {
|
||||||
|
if(dmChannel_ is null) {
|
||||||
|
var obj = var.emptyObject;
|
||||||
|
obj.recipient_id = this.id;
|
||||||
|
var result = this.api.rest.users["@me"].channels.POST(obj).result;
|
||||||
|
|
||||||
|
dmChannel_ = new DiscordChannel(api, result.id.get!string);//, result);
|
||||||
|
}
|
||||||
|
return dmChannel_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendMessage(string what) {
|
||||||
|
dmChannel.sendMessage(what);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/++
|
/++
|
||||||
|
@ -235,26 +259,44 @@ class SlashCommandHandler {
|
||||||
/++
|
/++
|
||||||
|
|
||||||
+/
|
+/
|
||||||
void reply(string message) scope {
|
void reply(string message, bool ephemeral = false) scope {
|
||||||
replyLowLevel(message);
|
replyLowLevel(message, ephemeral);
|
||||||
}
|
}
|
||||||
|
|
||||||
/++
|
/++
|
||||||
|
|
||||||
+/
|
+/
|
||||||
void replyWithError(in char[] message) scope {
|
void replyWithError(scope const(char)[] message) scope {
|
||||||
replyLowLevel(message.idup);
|
if(message.length == 0)
|
||||||
|
message = "I am error.";
|
||||||
|
replyLowLevel(message.idup, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void replyLowLevel(string message) scope {
|
enum MessageFlags : uint {
|
||||||
|
SUPPRESS_EMBEDS = (1 << 2), // skip the embedded content
|
||||||
|
EPHEMERAL = (1 << 6), // only visible to you
|
||||||
|
LOADING = (1 << 7), // the bot is "thinking"
|
||||||
|
SUPPRESS_NOTIFICATIONS = (1 << 12) // skip push/desktop notifications
|
||||||
|
}
|
||||||
|
|
||||||
|
void replyLowLevel(string message, bool ephemeral) scope {
|
||||||
|
if(message.length == 0)
|
||||||
|
message = "empty message";
|
||||||
var reply = var.emptyObject;
|
var reply = var.emptyObject;
|
||||||
reply.type = 4; // chat response in message. 5 can be answered quick and edited later if loading, 6 if quick answer, no loading message
|
reply.type = 4; // chat response in message. 5 can be answered quick and edited later if loading, 6 if quick answer, no loading message
|
||||||
var replyData = var.emptyObject;
|
var replyData = var.emptyObject;
|
||||||
replyData.content = message;
|
replyData.content = message;
|
||||||
|
replyData.flags = ephemeral ? (1 << 6) : 0;
|
||||||
reply.data = replyData;
|
reply.data = replyData;
|
||||||
|
try {
|
||||||
var result = api.rest.
|
var result = api.rest.
|
||||||
interactions[commandArgs.interactionId][commandArgs.interactionToken].callback
|
interactions[commandArgs.interactionId][commandArgs.interactionToken].callback
|
||||||
.POST(reply).result;
|
.POST(reply).result;
|
||||||
|
writeln(result.toString);
|
||||||
|
} catch(Exception e) {
|
||||||
|
import std.stdio; writeln(commandArgs);
|
||||||
|
writeln(e.toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,12 +323,22 @@ class SlashCommandHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
private {
|
private {
|
||||||
|
|
||||||
|
static void validateDiscordSlashCommandName(string name) {
|
||||||
|
foreach(ch; name) {
|
||||||
|
if(ch != '_' && !(ch >= 'a' && ch <= 'z'))
|
||||||
|
throw new InvalidArgumentsException("name", "discord names must be all lower-case with only letters and underscores", LimitedVariant(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static HandlerInfo makeHandler(alias handler, T)(T slashThis) {
|
static HandlerInfo makeHandler(alias handler, T)(T slashThis) {
|
||||||
HandlerInfo info;
|
HandlerInfo info;
|
||||||
|
|
||||||
// must be all lower case!
|
// must be all lower case!
|
||||||
info.name = __traits(identifier, handler);
|
info.name = __traits(identifier, handler);
|
||||||
|
|
||||||
|
validateDiscordSlashCommandName(info.name);
|
||||||
|
|
||||||
var cmd = var.emptyObject();
|
var cmd = var.emptyObject();
|
||||||
cmd.name = info.name;
|
cmd.name = info.name;
|
||||||
version(D_OpenD)
|
version(D_OpenD)
|
||||||
|
@ -309,6 +361,7 @@ class SlashCommandHandler {
|
||||||
foreach(idx, param; Params) {
|
foreach(idx, param; Params) {
|
||||||
var option = var.emptyObject;
|
var option = var.emptyObject;
|
||||||
auto name = __traits(identifier, Params[idx .. idx + 1]);
|
auto name = __traits(identifier, Params[idx .. idx + 1]);
|
||||||
|
validateDiscordSlashCommandName(name);
|
||||||
names ~= name;
|
names ~= name;
|
||||||
option.name = name;
|
option.name = name;
|
||||||
option.description = "desc";
|
option.description = "desc";
|
||||||
|
@ -329,9 +382,9 @@ class SlashCommandHandler {
|
||||||
static if(is(typeof(handler) Return == return)) {
|
static if(is(typeof(handler) Return == return)) {
|
||||||
static if(is(Return == void)) {
|
static if(is(Return == void)) {
|
||||||
__traits(child, slashThis, handler)(fargsFromJson!Params(api, names, args.interactionData, args).tupleof);
|
__traits(child, slashThis, handler)(fargsFromJson!Params(api, names, args.interactionData, args).tupleof);
|
||||||
sendHandlerReply("OK", replyHelper);
|
sendHandlerReply("OK", replyHelper, true);
|
||||||
} else {
|
} else {
|
||||||
sendHandlerReply(__traits(child, slashThis, handler)(fargsFromJson!Params(api, names, args.interactionData, args).tupleof), replyHelper);
|
sendHandlerReply(__traits(child, slashThis, handler)(fargsFromJson!Params(api, names, args.interactionData, args).tupleof), replyHelper, false);
|
||||||
}
|
}
|
||||||
} else static assert(0);
|
} else static assert(0);
|
||||||
};
|
};
|
||||||
|
@ -439,9 +492,9 @@ ync def something(interaction:discord.Interaction):
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sendHandlerReply(T)(T ret, scope InteractionReplyHelper replyHelper) {
|
static void sendHandlerReply(T)(T ret, scope InteractionReplyHelper replyHelper, bool ephemeral) {
|
||||||
import std.conv; // FIXME
|
import std.conv; // FIXME
|
||||||
replyHelper.reply(to!string(ret));
|
replyHelper.reply(to!string(ret), ephemeral);
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerAll(T)(T t) {
|
void registerAll(T)(T t) {
|
||||||
|
@ -482,7 +535,7 @@ class SendingUser : DiscordUser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SendingChannel : DiscordUser {
|
class SendingChannel : DiscordChannel {
|
||||||
private this(DiscordRestApi api, string id, var initialCache) {
|
private this(DiscordRestApi api, string id, var initialCache) {
|
||||||
super(api, id);
|
super(api, id);
|
||||||
}
|
}
|
||||||
|
@ -733,24 +786,46 @@ class DiscordGatewayConnection {
|
||||||
|
|
||||||
scope SlashCommandHandler.InteractionReplyHelper replyHelper = new SlashCommandHandler.InteractionReplyHelper(api, commandArgs);
|
scope SlashCommandHandler.InteractionReplyHelper replyHelper = new SlashCommandHandler.InteractionReplyHelper(api, commandArgs);
|
||||||
|
|
||||||
|
Exception throwExternally;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if(slashCommandHandler_ is null)
|
if(slashCommandHandler_ is null)
|
||||||
throw ArsdException!"No slash commands registered"();
|
throwExternally = ArsdException!"No slash commands registered"();
|
||||||
|
else {
|
||||||
auto cmdName = commandArgs.interactionData.name.get!string;
|
auto cmdName = commandArgs.interactionData.name.get!string;
|
||||||
if(auto pHandler = cmdName in slashCommandHandler_.handlers) {
|
if(auto pHandler = cmdName in slashCommandHandler_.handlers) {
|
||||||
(*pHandler)(commandArgs, replyHelper, api);
|
(*pHandler)(commandArgs, replyHelper, api);
|
||||||
} else {
|
} else {
|
||||||
throw ArsdException!"Unregistered slash command"(cmdName);
|
throwExternally = ArsdException!"Unregistered slash command"(cmdName);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
} catch(ArsdExceptionBase e) {
|
||||||
|
const(char)[] msg = e.message;
|
||||||
|
if(msg.length == 0)
|
||||||
|
msg = "I am error.";
|
||||||
|
|
||||||
|
e.getAdditionalPrintableInformation((string name, in char[] value) {
|
||||||
|
msg ~= ("\n");
|
||||||
|
msg ~= (name);
|
||||||
|
msg ~= (": ");
|
||||||
|
msg ~= (value);
|
||||||
|
});
|
||||||
|
|
||||||
|
replyHelper.replyWithError(msg);
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
replyHelper.replyWithError(e.message);
|
replyHelper.replyWithError(e.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(throwExternally !is null)
|
||||||
|
throw throwExternally;
|
||||||
break;
|
break;
|
||||||
case "READY":
|
case "READY":
|
||||||
this.session_id = data.session_id.get!string;
|
this.session_id = data.session_id.get!string;
|
||||||
this.resume_gateway_url = data.resume_gateway_url.get!string;
|
this.resume_gateway_url = data.resume_gateway_url.get!string;
|
||||||
this.applicationId_ = data.application.id.get!string;
|
this.applicationId_ = data.application.id.get!string;
|
||||||
|
|
||||||
|
if(slashCommandHandler_ !is null && applicationId.length)
|
||||||
|
slashCommandHandler_.register(api, applicationId);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Reference in New Issue