anfjtjsdrhgu

This commit is contained in:
lost+skunk 2025-01-08 17:24:48 +03:00
commit 8277809e4d
6 changed files with 197 additions and 0 deletions

16
.gitignore vendored Normal file
View File

@ -0,0 +1,16 @@
.dub
docs.json
__dummy.html
docs/
/skunkybot-d
skunkybot-d.so
skunkybot-d.dylib
skunkybot-d.dll
skunkybot-d.a
skunkybot-d.lib
skunkybot-d-test-*
*.exe
*.pdb
*.o
*.obj
*.lst

7
README.md Normal file
View File

@ -0,0 +1,7 @@
# TODO
- [ ] get rid of indian code
- [ ] implement shared-library modules
- [ ] implement config
- [ ] implement forgejo/gitea webhooks
# INFO
говнобот

6
dub.sdl Normal file
View File

@ -0,0 +1,6 @@
name "skunkybot-d"
description "Matrix bot"
authors "skunk"
copyright "Copyright © 2025, skunk"
license "AGPL-3.0-only"
dependency "asdf" version="~>0.7.17"

9
dub.selections.json Normal file
View File

@ -0,0 +1,9 @@
{
"fileVersion": 1,
"versions": {
"asdf": "0.7.17",
"mir-algorithm": "3.22.3",
"mir-core": "1.7.1",
"silly": "1.1.1"
}
}

86
source/app.d Normal file
View File

@ -0,0 +1,86 @@
import std.stdio: writeln;
import std.net.curl;
import asdf: deserialize, serializeToJson;
import util;
void main() {
init("syt_c29mdHBpZ2VvbmVz_QqNnkNjuuAffMKfGfUEO_0SqrAx", "hot-chilli.im");
sync();
}
HTTP http;
string homeserver;
void init(string token, string hs) {
http = HTTP();
http.addRequestHeader("Authorization", "Bearer " ~ token);
homeserver = "https://" ~ hs;
get(homeserver~"/_matrix/federation/v1/version");
}
void send(T)(T content, string roomid, string type = "m.room.message") {
import std.random: uniform;
put(homeserver~"/_matrix/client/v3/rooms/" ~ roomid ~ "/send/" ~ type ~
"/skunky-" ~ intToStr(uniform(1111_1111, 9999_9999)), content.serializeToJson, http);
}
// void join(string roomid) {
// post(homeserver~"/_matrix/client/v3/rooms/"~roomid~"/join", http);
// }
void sync() {
import core.memory;
import object: destroy;
string str = homeserver ~ "/_matrix/client/v3/sync?set_presence=online";
Sync content = get(str, http).deserialize!Sync; str ~= "&since=";
for (;;) {
string bthUrl = str ~ content.next_batch;
writeln(content.next_batch);
destroy(content);
GC.free(&content);
content = get(bthUrl, http).deserialize!Sync;
// 🇮🇳🇮🇳🇮🇳
foreach (room, _; content.rooms.invite) {
writeln("Joining to room: ", room);
post(homeserver~"/_matrix/client/v3/rooms/"~room~"/join", null, http);
send(MSG("Yasno << Ponyatno"), room);
}
foreach (room, roomContent; content.rooms.join) {
foreach(event; roomContent.timeline.events) {
if (event.type == "m.room.message") {
try {
auto evt = deserialize!MSG(event.content.data);
writeln(room, ": ", evt.body);
switch (evt.body) {
case "!huy":
send(MSG(":orehussmile:",
`<img data-mx-emoticon height="32" src="mxc://4d2.org/XvWYAuhASYRHtYvtspsrWvtU" alt=":orehussmile:" title=":orehussmile:">`), room);
break;
case "!версия": send(MSG("Compiler version: "~intToStr(__VERSION__)), room); break;
case "скунс": send(MSG("еблан"), room); break;
case "!avatar":
string url = cast(string)get(homeserver~"/_matrix/client/v3/profile/"~event.sender~"/avatar_url");
if (url == "{}") {send(MSG("Avatar is empty"), room); break;}
send(MSG(event.sender, `<img src="`~url[15..$-2]~`">`), room);
break;
default: break;
}
} catch (Exception e) {
writeln(e.msg);
send(MSG(e.msg), room);
}
}
}
}
}
}
string intToStr(T)(T num) {
char[] buf;
for(short i; num > 0; ++i) {
buf = (num % 10 + '0')~buf;
num /= 10;
} return cast(string)buf;
}

73
source/util.d Normal file
View File

@ -0,0 +1,73 @@
module util;
import asdf;
struct JsonObject {
import std.conv: to;
string data;
SerdeException deserializeFromAsdf(Asdf data) {
this.data = data.to!string;
return null;
}
void serialize(S)(ref S serializer) {
try serializer.sink.putSmallEscaped(data.parseJson.to!string);
catch (Exception) serializer.sink.putSmallEscaped("{}");
}
}
struct Sync {
struct StrippedStateEvent {
JsonObject content;
string sender, state_key, type;
}
struct Unsigned {
int age;
string membership, transaction_id;
}
struct Rooms {
struct Invited {
struct IS { StrippedStateEvent[] events; }
IS invite_state;
}
struct Joined {
struct Timeline {
struct EventWithoutRoomID {
JsonObject content;
string event_id;
ulong origin_server_ts;
@serdeOptional string sender, state_key, type;
// Unsigned unsigned;
}
EventWithoutRoomID[] events;
bool limited;
string prev_batch;
}
struct UNC {
int highlight_count;
int notification_count;
}
Timeline timeline;
UNC unread_notifications;
}
@serdeOptional Invited[string] invite;
@serdeOptional Joined[string] join;
}
@serdeOptional Rooms rooms;
string next_batch;
}
// EVENTS
struct MSG {
string body;
@serdeOptional @serdeIgnoreDefault string formatted_body;
string msgtype = "m.notice";
@serdeOptional string format = "org.matrix.custom.html";
}