тонна гонвнокода

This commit is contained in:
lost+skunk 2025-03-11 01:01:54 +03:00
parent 5ea0e943fb
commit 6b7bf681ae
25 changed files with 4396 additions and 228 deletions

105
source/commands/apod.d Normal file
View 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
View 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]~`">`);
// }

View 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
View 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
View 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
View 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;
}