тонна гонвнокода
This commit is contained in:
parent
5ea0e943fb
commit
6b7bf681ae
25 changed files with 4396 additions and 228 deletions
105
source/commands/apod.d
Normal file
105
source/commands/apod.d
Normal file
|
@ -0,0 +1,105 @@
|
|||
module commands.apod;
|
||||
|
||||
import util, api, api_data;
|
||||
import commands.util;
|
||||
import main: db;
|
||||
|
||||
struct APOD {
|
||||
string url;
|
||||
string hdurl;
|
||||
string title;
|
||||
string explanation;
|
||||
}
|
||||
|
||||
struct APOD_internal {
|
||||
string subscribed_room;
|
||||
string mxc, title, body, mimetype;
|
||||
int untill, size, width, height;
|
||||
}
|
||||
|
||||
auto apod_get() {
|
||||
import asdf, api: upload;
|
||||
import gamut: Image;
|
||||
|
||||
MSG msg;
|
||||
Image img;
|
||||
auto data = mkrqst("https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY", null, null, true)
|
||||
.body.deserialize!APOD;
|
||||
auto image = mkrqst(data.hdurl, null, null, true);
|
||||
|
||||
img.loadFromMemory(image.body);
|
||||
msg.info.w = img.width;
|
||||
msg.info.h = img.height;
|
||||
msg.info.size = image.body.length;
|
||||
msg.info.mimetype = image.getHeader("Content-Type");
|
||||
|
||||
msg.url = upload(image.body);
|
||||
msg.msgtype = "m.image";
|
||||
msg.filename = data.hdurl;
|
||||
msg.body = data.title;
|
||||
msg.formatted_body = "<details><summary><b>"~data.title~"</b></summary><p>"~data.explanation~"</p></details>";
|
||||
return msg;
|
||||
}
|
||||
|
||||
// 🇮🇳🇮🇳🇮🇳 यह बकवास का एक बुरा टुकड़ा है, लेकिन मैं इसे ठीक करने के लिए बहुत आलसी हूं ।
|
||||
MSG cached_apod() {
|
||||
import core.stdc.time: time;
|
||||
|
||||
auto now = time(null);
|
||||
auto q = db.query("select * from apod where subscribed_room = 'CACHE'");
|
||||
|
||||
if (q.step) {
|
||||
APOD_internal data = q.get!APOD_internal;
|
||||
if (data.untill > now) {
|
||||
MSG msg = MSG(data.title, data.body);
|
||||
msg.url = data.mxc;
|
||||
msg.info.w = data.width;
|
||||
msg.info.h = data.height;
|
||||
msg.info.size = data.size;
|
||||
msg.info.mimetype = data.mimetype;
|
||||
msg.filename = data.title ~ ".jpg";
|
||||
msg.msgtype = "m.image";
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
|
||||
MSG msg = apod_get;
|
||||
db.exec("insert into apod
|
||||
(subscribed_room, width, height, size, mxc, mimetype, title, body, untill)
|
||||
values ('CACHE',?,?,?,?,?,?,?,?)
|
||||
on conflict (mxc) do update set
|
||||
mxc = excluded.mxc,
|
||||
body = excluded.body,
|
||||
size = excluded.size,
|
||||
title = excluded.title,
|
||||
width = excluded.width,
|
||||
height = excluded.height,
|
||||
mimetype = excluded.mimetype",
|
||||
msg.info.w, msg.info.h, msg.info.size, msg.url, msg.info.mimetype,
|
||||
msg.body, msg.formatted_body, now + Time.day);
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
@Command("Astronomy Picture Of the Day")
|
||||
auto apod(Arguments arg, EventWithoutRoomID* evt) {
|
||||
if (arg.parsed.length == 0) return cached_apod;
|
||||
|
||||
auto powerlevel = getUsrPL(evt.room, evt.sender);
|
||||
bool subscribed = db.query("select * from apod where subscribed_room = ?", evt.room).step;
|
||||
|
||||
if (powerlevel < 50) return MSG("Unauthorized");
|
||||
if (arg.parsed[0] == "subscribe") {
|
||||
if (subscribed)
|
||||
return MSG("Room is already subscribed to APOD.");
|
||||
db.exec("insert into apod (subscribed_room) values (?)", evt.room);
|
||||
return MSG("Room has been subcribed to APOD!");
|
||||
} else if (arg.parsed[0] == "unsubscribe") {
|
||||
if (subscribed) {
|
||||
db.exec("delete from apod where subscribed_room = ?", evt.room);
|
||||
return MSG("Room has been unsubscribed from APOD.");
|
||||
} else return MSG("Room is not subscribed to APOD.");
|
||||
}
|
||||
|
||||
return MSG("Unknown argument");
|
||||
}
|
51
source/commands/misc.d
Normal file
51
source/commands/misc.d
Normal file
|
@ -0,0 +1,51 @@
|
|||
module commands.misc;
|
||||
|
||||
import util, api_data;
|
||||
import commands.util;
|
||||
|
||||
@Command("хз", "хуй")
|
||||
string[2] huy = [":orehussmile:",
|
||||
`<img data-mx-emoticon height="32" alt=":orehussmile:" title=":orehussmile:"
|
||||
src="mxc://4d2.org/XvWYAuhASYRHtYvtspsrWvtU" >`];
|
||||
|
||||
@Command("Версия бота", "версия")
|
||||
string ver = "Neptune Alpha 1.0 :: https://git.macaw.me/skunky/neptune";
|
||||
|
||||
@Command("компвер")
|
||||
static string compver = "Compiler version: "~intToStr(__VERSION__);
|
||||
|
||||
|
||||
@Command("Измеряет пинг")
|
||||
auto ping(Arguments, EventWithoutRoomID* evt) {
|
||||
static enum Time: int {
|
||||
millisecond = 1,
|
||||
second = 1000,
|
||||
minute = 60 * second,
|
||||
hour = 60 * minute,
|
||||
day = 24 * hour,
|
||||
week = 7 * day,
|
||||
month = 4 * week,
|
||||
year = 12 * month
|
||||
}
|
||||
|
||||
import std.datetime: Clock, SysTime, unixTimeToStdTime;
|
||||
auto delay = (Clock.currTime() - SysTime(unixTimeToStdTime(0))).total!"msecs" - evt.origin_server_ts;
|
||||
|
||||
static foreach_reverse(unit; __traits(allMembers,Time))
|
||||
if (delay >= __traits(getMember, Time, unit)) // реализовать функцию floatToStr
|
||||
return MSG("PONG [" ~ intToStr(delay / __traits(getMember, Time, unit)) ~ ' ' ~ unit ~ "s]");
|
||||
return MSG("шота пошло не так");
|
||||
}
|
||||
|
||||
@Command("хз мне лень делать описание")
|
||||
auto echo(Arguments argz, EventWithoutRoomID* evt) {
|
||||
return MSG((argz.raw.length > 6) ? argz.raw[6..$] : "Too small MSG");
|
||||
}
|
||||
|
||||
// @Command("Отображает аватар пользователя")
|
||||
// auto avatar(Arguments argz, EventWithoutRoomID* evt) {
|
||||
// string url = cast (string) mkrqst(homeserver~"/_matrix/client/v3/profile/" ~
|
||||
// ((argz.parsed.length == 0) ? evt.sender : argz.parsed[0]) ~ "/avatar_url").body;
|
||||
// if (url == "{}") return MSG("User has no avatar");
|
||||
// return MSG(evt.sender, `<img src="`~url[15..$-2]~`">`);
|
||||
// }
|
128
source/commands/moderation.d
Normal file
128
source/commands/moderation.d
Normal file
|
@ -0,0 +1,128 @@
|
|||
module commands.moderation;
|
||||
|
||||
import util, api_data, api;
|
||||
import asdf;
|
||||
import core.stdc.time: time;
|
||||
import commands.util;
|
||||
|
||||
import main: db;
|
||||
|
||||
enum TimeErr: int {
|
||||
@("Not enough arguments") NotEnoughArguments = -1,
|
||||
@("Invalid date") InvalidDate = -2,
|
||||
@("Invalid unit") InvalidUnit = -3
|
||||
}
|
||||
|
||||
int parseTime(string str) @nogc pure {
|
||||
if (str.length < 2) return TimeErr.NotEnoughArguments;
|
||||
foreach (short c; str[0..$-1])
|
||||
if (!(c >= 48 && c <= 57))
|
||||
return TimeErr.InvalidDate;
|
||||
|
||||
static foreach(unit; __traits(allMembers, Time))
|
||||
if (str[$-1] == __traits(getAttributes, __traits(getMember, Time, unit))[0])
|
||||
return strToInt(str[0..$-1]) * __traits(getMember, Time, unit);
|
||||
|
||||
return TimeErr.InvalidUnit;
|
||||
}
|
||||
|
||||
@Command("Admin tools")
|
||||
MSG nctl(Arguments arg, EventWithoutRoomID* evt) {
|
||||
if (arg.parsed.length != 2) return MSG("❌️ Not enough arguments");
|
||||
if (getUsrPL(evt.room, evt.sender) < 50) return MSG("❌️ Unauthorized");
|
||||
db.exec("create table if not exists nctl (room string, user string, nc string, type string, unt integer)");
|
||||
|
||||
bool wd, err;
|
||||
string cntnt, type;
|
||||
|
||||
int dur;
|
||||
auto durStr = arg.getArg("D");
|
||||
if (durStr) dur = parseTime(durStr);
|
||||
|
||||
if (dur < 0) {
|
||||
static foreach(Terr; __traits(allMembers, TimeErr)) {
|
||||
if (dur == __traits(getMember, TimeErr, Terr)) {
|
||||
return MSG("💥 " ~ __traits(getAttributes, __traits(getMember, TimeErr, Terr))[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mrq(string ep) {
|
||||
short rq = mkhsrq(
|
||||
"/_matrix/client/v3/rooms/"~evt.room~'/'~ep,
|
||||
"POST",
|
||||
Moderate(arg.parsed[1], "Moderated by "~evt.sender).serializeToJson
|
||||
).status;
|
||||
if (rq != 200) err = true;
|
||||
}
|
||||
|
||||
void setpl(short pl) {
|
||||
auto pls = State.PowerLevels(getUsrsPLs(evt.room));
|
||||
if (dur) cntnt = pls.serializeToJson;
|
||||
pls.users[arg.parsed[1]] = pl;
|
||||
state(evt.room, "m.room.power_levels", pls);
|
||||
}
|
||||
|
||||
bool c() {
|
||||
if (db.query("select type from nctl where room = ? and user = ?",evt.room, arg.parsed[1]).step)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (arg.parsed[0]) {
|
||||
case "ban":
|
||||
wd = true;
|
||||
mrq("ban");
|
||||
break;
|
||||
case "kick", "unban":
|
||||
mrq(arg.parsed[0]);
|
||||
break;
|
||||
case "mute":
|
||||
if(c) goto e;
|
||||
type = "m.room.power_levels";
|
||||
wd = true;
|
||||
setpl(-100);
|
||||
break;
|
||||
case "unmute": setpl(0); break;
|
||||
case "acl", "delete-acl":
|
||||
State.ACL acls = getState!(State.ACL)(evt.room, "m.room.server_acl");
|
||||
if (dur) cntnt = acls.serializeToJson;
|
||||
|
||||
if (arg.parsed[0] == "acl") {
|
||||
if(c) goto e;
|
||||
type = "m.room.server_acl";
|
||||
wd = true;
|
||||
acls.deny ~= arg.parsed[1];
|
||||
} else {
|
||||
foreach (n, srv; acls.deny) {
|
||||
if (srv == arg.parsed[1])
|
||||
acls.deny = acls.deny[0..n] ~ acls.deny[n+1..$];
|
||||
}
|
||||
}
|
||||
|
||||
state(evt.room, "m.room.server_acl", acls);
|
||||
break;
|
||||
default: return MSG("❓️ Invalid argument");
|
||||
}
|
||||
|
||||
if (err) return MSG("💥 Something went wrong");
|
||||
|
||||
if (dur && wd) {
|
||||
import std.datetime.systime: SysTime;
|
||||
auto untill = time(null) + dur;
|
||||
|
||||
db.exec(
|
||||
"insert into nctl (room, user, nc, type, unt) values (?,?,?,?,?)",
|
||||
evt.room,
|
||||
arg.parsed[1],
|
||||
cntnt,
|
||||
type,
|
||||
untill
|
||||
);
|
||||
|
||||
return MSG("✅️ Blocked untill " ~ SysTime.fromUnixTime(untill).toSimpleString);
|
||||
}
|
||||
|
||||
return MSG("✅️");
|
||||
e: return MSG("💥 Already moderated!");
|
||||
}
|
54
source/commands/mozhi.d
Normal file
54
source/commands/mozhi.d
Normal file
|
@ -0,0 +1,54 @@
|
|||
module commands.mozhi;
|
||||
|
||||
// import api;
|
||||
// import util;
|
||||
// import commands.util;
|
||||
// import api_data;
|
||||
|
||||
// import asdf;
|
||||
|
||||
// @Command("Translates text via Mozhi")
|
||||
// auto tr(Arguments argz, EventWithoutRoomID* evt) {
|
||||
// struct RqRsp {
|
||||
// string engine;
|
||||
// string detected;
|
||||
// @serdeKeys("translated-text") string translatedText;
|
||||
// string source_language;
|
||||
// string target_language;
|
||||
// }
|
||||
|
||||
// MSG msg;
|
||||
// string text;
|
||||
// auto ngn = argz.getArg("E");
|
||||
// auto instance = argz.getArg("I");
|
||||
// MSG origin = evt.content.raw.deserialize!MSG;
|
||||
|
||||
// if (argz.parsed.length == 2) {
|
||||
// auto reply = event(origin.relates.reply.event_id, evt.room).body;
|
||||
// foreach (chr; reply) {
|
||||
// if (chr == ' ') text ~= '+';
|
||||
// else text ~= chr;
|
||||
// }
|
||||
// } else for (short i = 2; i < argz.parsed.length; ++i)
|
||||
// text ~= argz.parsed[i] ~ '+';
|
||||
|
||||
// auto rq = mkrqst (
|
||||
// "https://" ~ (instance ? instance : "mozhi.gitro.xyz") ~ "/api/translate", "POST",
|
||||
// "engine=" ~ (ngn ? ngn : "google")
|
||||
// ~ "&from=" ~ argz.parsed[0]
|
||||
// ~ "&to=" ~ argz.parsed[1]
|
||||
// ~ "&text=" ~ text,
|
||||
// false
|
||||
// );
|
||||
|
||||
// if (rq.status != 200) return MSG(intToStr(rq.status));
|
||||
// auto content = rq.body.deserialize!RqRsp;
|
||||
|
||||
// msg = MSG("ЙАЗЫКНЙЭВЫ|БРАН", content.translatedText);
|
||||
// return msg;
|
||||
// }
|
||||
|
||||
// @Command("Creates audio with text, using Mozhi")
|
||||
// auto tts(Arguments argz, EventWithoutRoomID* evt) {
|
||||
|
||||
// }
|
81
source/commands/slaves.d
Normal file
81
source/commands/slaves.d
Normal file
|
@ -0,0 +1,81 @@
|
|||
module commands.slaves;
|
||||
|
||||
enum Parallel;
|
||||
|
||||
import util;
|
||||
import api;
|
||||
import api_data;
|
||||
import main: db;
|
||||
|
||||
void apod_slave() @Parallel {
|
||||
import core.thread;
|
||||
import commands.apod;
|
||||
import core.stdc.time: time;
|
||||
|
||||
db.exec("create table if not exists apod (
|
||||
subscribed_room string,
|
||||
mxc string unique,
|
||||
body string,
|
||||
title string,
|
||||
mimetype string,
|
||||
size integer,
|
||||
width integer,
|
||||
height integer,
|
||||
untill integer
|
||||
)");
|
||||
|
||||
for (;;) {
|
||||
int v;
|
||||
auto q = db.query("select untill from apod where subscribed_room = 'CACHE'");
|
||||
if (q.step) v = q.get!int;
|
||||
for (q = db.query("select subscribed_room from apod where subscribed_room != 'CACHE'"); q.step;) {
|
||||
if (v == 0 || v < time(null)) {
|
||||
send(cached_apod, q.get!string);
|
||||
db.exec("delete from apod where subscribed_room = 'CACHE'");
|
||||
}
|
||||
}
|
||||
Thread.sleep(30.seconds);
|
||||
}
|
||||
}
|
||||
|
||||
void nctl_slave() @Parallel {
|
||||
import core.thread: Thread;
|
||||
import core.time: Duration, dur;
|
||||
import core.stdc.time: time;
|
||||
|
||||
import asdf: serializeToJson;
|
||||
|
||||
static Duration tms = dur!"msecs"(10);
|
||||
|
||||
struct udr {
|
||||
string room;
|
||||
string user;
|
||||
string type;
|
||||
string nc;
|
||||
int unt;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
auto q = db.query("select * from nctl");
|
||||
while (q.step) {
|
||||
try {
|
||||
udr z = q.get!udr;
|
||||
if (time(null) >= z.unt) {
|
||||
if (z.type == null) {
|
||||
mkhsrq(
|
||||
"/_matrix/client/v3/rooms/"~z.room~"/unban",
|
||||
"POST",
|
||||
Moderate(z.user, "Its time to unban!").serializeToJson
|
||||
);
|
||||
}
|
||||
else rawState(z.room, z.type, z.nc);
|
||||
db.exec("delete from nctl where user = ? and room = ?", z.user, z.room);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
import core.stdc.stdio;
|
||||
printf("[nctl_slave] ERROR: %s\n", cast(char*)e.msg);
|
||||
}
|
||||
}
|
||||
Thread.sleep(tms);
|
||||
}
|
||||
}
|
92
source/commands/util.d
Normal file
92
source/commands/util.d
Normal file
|
@ -0,0 +1,92 @@
|
|||
module commands.util;
|
||||
|
||||
struct Command {
|
||||
string description = "No description provided";
|
||||
string name;
|
||||
}
|
||||
|
||||
static enum Time: int {
|
||||
@('s') second = 1,
|
||||
@('m') minute = 60 * second,
|
||||
@('h') hour = 60 * minute,
|
||||
@('d') day = 24 * hour,
|
||||
@('w') week = 7 * day,
|
||||
@('M') month = 30 * day,
|
||||
@('y') year = 12 * month
|
||||
}
|
||||
|
||||
struct Arguments {
|
||||
string raw;
|
||||
string command;
|
||||
string[] parsed;
|
||||
char[] options;
|
||||
string getArg(string arg) @nogc {
|
||||
int prev, splt;
|
||||
for (int i; i < options.length; ++i) {
|
||||
if (options[i] == '\0') splt = i;
|
||||
else if (options[i] == '\1') {
|
||||
if (arg == options[prev..splt])
|
||||
return cast(string)options[splt+1..i];
|
||||
prev = i + 1;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
auto parseMsg(string cmd) {
|
||||
import std.stdio;
|
||||
Arguments argz = Arguments(cmd);
|
||||
if (argz.raw[0] == '#') {
|
||||
string buf;
|
||||
for (ulong i = 1; i < argz.raw.length; ++i)
|
||||
if (argz.raw[i] != ' ' && argz.raw[i] != '=') {
|
||||
buf ~= argz.raw[i];
|
||||
if (i+1 == argz.raw.length || (argz.raw[i+1] == ' ' || argz.raw[i+1] == '=')) {
|
||||
argz.parsed ~= buf;
|
||||
buf = null;
|
||||
}
|
||||
}
|
||||
argz.command = argz.parsed[0]; argz.parsed = argz.parsed[1..$];
|
||||
|
||||
for (ulong i; i < argz.parsed.length; ++i)
|
||||
if (argz.parsed[i][0] == '-') {
|
||||
string key = argz.parsed[i];
|
||||
auto val = (i+1 < argz.parsed.length && argz.parsed[i+1][0] != '-')
|
||||
? argz.parsed[i+1] : null;
|
||||
if (key[1] == '-')
|
||||
argz.options ~= key[2..$] ~ '\0' ~ val ~ '\1';
|
||||
else for (ulong x = 1; x < key.length; ++x)
|
||||
argz.options ~= key[x..x+1] ~ '\0' ~ val ~ '\1';
|
||||
|
||||
auto x = (val) ? i + 2 : i + 1;
|
||||
argz.parsed = argz.parsed[0..i] ~ argz.parsed[x..$];
|
||||
i = i - (x - i);
|
||||
}
|
||||
}
|
||||
return argz;
|
||||
}
|
||||
|
||||
int getUsrPL(string room, string user) {
|
||||
import main: db;
|
||||
auto q = db.query("select pl from room_pls where room = ? and user = ?", room, user);
|
||||
if (q.step) return q.get!int;
|
||||
return 0;
|
||||
}
|
||||
|
||||
short[string] getUsrsPLs(string room) {
|
||||
struct hz {
|
||||
string user;
|
||||
short pl;
|
||||
}
|
||||
|
||||
import main: db;
|
||||
short[string] buf;
|
||||
auto q = db.query("select user, pl from room_pls where room = ?", room);
|
||||
while (q.step) {
|
||||
auto x = q.get!hz;
|
||||
buf[x.user] = x.pl;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue