diff --git a/src/AS.c b/src/AS.c index 8415148..2010d8f 100644 --- a/src/AS.c +++ b/src/AS.c @@ -946,3 +946,45 @@ ASRedact(const ParseeConfig *c, char *room, char *user, char *e_id) return; } +void +ASSetStatus(const ParseeConfig *c, char *user, UserStatus status, char *msg) +{ + HttpClientContext *ctx = NULL; + HashMap *request; + char *path; + char *status_str = NULL; + if (!c || !user || !msg) + { + return; + } + + switch (status) + { + case USER_STATUS_ONLINE: status_str = "online"; break; + case USER_STATUS_OFFLINE: status_str = "offline"; break; + case USER_STATUS_UNAVAILABLE: status_str = "unavailable"; break; + default: return; + } + + user = HttpUrlEncode(user); + path = StrConcat(5, + "/_matrix/client/v3/presence/",user,"/status", + "?user_id=", user + ); + Free(user); + + request = HashMapCreate(); + HashMapSet(request, "presence", JsonValueString(status_str)); + if (msg) + { + HashMapSet(request, "status_msg", JsonValueString(msg)); + } + + ctx = ParseeCreateRequest(c, HTTP_PUT, path); + ASAuthenticateRequest(c, ctx); + ParseeSetRequestJSON(ctx, request); + JsonFree(request); + + HttpClientContextFree(ctx); + Free(path); +} diff --git a/src/XMPPThread.c b/src/XMPPThread.c index d55f8a4..2af4d7d 100644 --- a/src/XMPPThread.c +++ b/src/XMPPThread.c @@ -1091,7 +1091,34 @@ PresenceStanza(ParseeData *args, XMLElement *stanza) #define MUC_USER_NS "http://jabber.org/protocol/muc#user" XMLElement *user_info; XMLElement *vc = XMLookForTKV(stanza, "x", "xmlns", "vcard-temp:x:update"); + XMLElement *status = XMLookForUnique(stanza, "status"); char *oid = HashMapGet(stanza->attrs, "from"); + + if (status) + { + XMLElement *status_data = ArrayGet(status->children, 0); + char *decode_from = ParseeLookupJID(oid); + char *from_matrix = ParseeDecodeMXID(decode_from); + if (!from_matrix || *from_matrix != '@') + { + Free(from_matrix); + from_matrix = ParseeEncodeJID(args->config, decode_from, false); + } + if (status_data) + { + char *status_str = status_data->data; + + /* TODO: Verify whenever this code works as soon as I can get + * my own instance (kappach.at) with presence enabled. */ + ASSetStatus( + args->config, from_matrix, + USER_STATUS_ONLINE, status_str + ); + } + + Free(decode_from); + Free(from_matrix); + } if ((user_info = XMLookForTKV(stanza, "x", "xmlns", MUC_USER_NS))) { XMLElement *item = XMLookForUnique(user_info, "item"); @@ -1180,7 +1207,6 @@ PresenceStanza(ParseeData *args, XMLElement *stanza) { ASLeave(args->config, room, from_matrix); } - } if (jid) diff --git a/src/include/AS.h b/src/include/AS.h index 4000c9a..e59b4b1 100644 --- a/src/include/AS.h +++ b/src/include/AS.h @@ -57,10 +57,32 @@ extern void ASSetPL(const ParseeConfig *conf, char *id, HashMap *m); * returns it's ID if it exists. */ extern char * ASCreateRoom(const ParseeConfig *c, char *by, char *alias); -/* Sets a user's displayname */ +/** Sets the user's global display{name] + * -------- + * Returns: NOTHING + * Modifies: [EXT:User status] + * See-Also: ASGetName, ASSetStatus, ASSetAvatar */ extern void ASSetName(const ParseeConfig *c, char *user, char *name); + +/** Sets the {user}'s global avatar, as an {mxc} URI + * -------- + * Returns: NOTHING + * Modifies: [EXT:User status] + * See-Also: ASGetName, ASSetStatus */ extern void ASSetAvatar(const ParseeConfig *c, char *user, char *mxc); +typedef enum UserStatus { + USER_STATUS_ONLINE, + USER_STATUS_OFFLINE, + USER_STATUS_UNAVAILABLE +} UserStatus; +/** Sets the user's status and message, to be seen by other clients. + * -------- + * Returns: NOTHING + * Modifies: [EXT:User status] + * See-Also: https://spec.matrix.org/v1.11/client-server-api/#put_matrixclientv3presenceuseridstatus, ASSetName, ASSetAvatar */ +extern void ASSetStatus(const ParseeConfig *c, char *user, UserStatus status, char *msg); + /* Returns the user's name in a room, or a copy of the MXID itself, to be * Free'd. */ extern char * ASGetName(const ParseeConfig *c, char *room, char *user);