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!"); }