module listener; import api, api_data; import commands.util; import main: db; import util; import std.stdio: writeln; import core.thread; import asdf: deserialize; __gshared string syncUrl, initialBatch; void listen(Modules...)() { static MSG helpgen() { MSG msg; static foreach (mod; Modules) { static foreach (member; __traits(allMembers, mod)) { static foreach (attr; __traits(getAttributes, __traits(getMember, mod, member))) { static if (is(typeof(attr) == Command)) msg.body ~= member ~ ": " ~ attr.description ~ '\n'; } } } return msg; } auto content = Sync(); content.next_batch = initialBatch; for (;;) { string bthUrl = syncUrl ~ content.next_batch; try { content = mkhsrq(bthUrl).body.deserialize!Sync; db.exec("update client set latest_batch = ?", content.next_batch); } catch (Exception e) { writeln(e.msg); continue; } // https://github.com/trikko/serverino/blob/3e3e6273a5aaa32615ae9d007a1a83877bc23ab4/source/serverino/worker.d#L168 new Thread(delegate { foreach (room, _; content.rooms.invite) { writeln("Joining to room: ", room); mkhsrq("/_matrix/client/v3/rooms/"~room~"/join", "POST", "{}"); send(MSG("Йа криведко"), room); fetchMembers(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.raw); if (!evt.body.length) break; event.room = room; auto argz = parseMsg(evt.body); if (argz.command == "hlp") { auto h = helpgen; h.relates.reply.event_id = event.event_id; send(h, room); break; } static foreach (mod; Modules) { static foreach (member; __traits(allMembers, mod)) { // if (argz.command == member) { foreach (attr; __traits(getAttributes, __traits(getMember, mod, member))) { if (is(typeof(attr) == Command) && (argz.command == member || (argz.command == attr.name && attr.name != null))) { alias command = __traits(getMember, mod, member); static if (is(typeof(command) == function)) auto content = command(argz, &event); else static if (__traits(isStaticArray, command)) auto content = MSG(command[0], command[1]); else auto content = MSG(command); content.relates.reply.event_id = event.event_id; send(content, room); } } // } } } } catch (Exception e) { writeln(e.msg); send(MSG(e.msg), room); } } else if (event.type == "m.room.power_levels") { auto pls = deserialize!(State.PowerLevels)(event.content.raw); foreach (user, pl; pls.users) { auto q = db.query("select pl from room_pls where room = ? and user = ?", room, user); if (q.step) { if (q.get!int != pl) db.exec("update room_pls set pl = ? where room = ? and user = ?", pl, room, user); } else db.exec("insert into room_pls (room, user, pl) values (?, ?, ?)", room, user, pl); } } // else if (event.type == "m.room.encrypted") { // import encryption; // auto e = deserialize!Encrypted(event.content.raw); // decrypt(&e); // } } } }).start; } } void fetchMembers(string room) { auto state = getState!(State.PowerLevels)(room, "m.room.power_levels"); foreach (user, pl; state.users) { db.exec("insert into room_pls (room, user, pl) values (?, ?, ?)", room, user, pl); } }