show enters and leaves

v1
Tony Olagbaiye 4 years ago
parent 020da2710e
commit 09ce7489b7
No known key found for this signature in database
GPG Key ID: 9E2FF3BDEBDFC910

@ -47,7 +47,7 @@
- glib (dynamic, dependency of libomemo)
- sqlite (dynamic, dependency of libomemo/axc)
- libsignal-protocol-c (dynamic, dependency of axc)
- weechat (>= v2.5)
- weechat (>= v3.0)
.. or just use the guix spec in .envrc
@ -101,13 +101,15 @@
* [X] Sending
* [ ] [#B] Edits
* [ ] [#B] Handle errors gracefully
* [ ] [#B] Presence/nicklist
* [X] [#B] Presence/nicklist
* [X] [#B] Enters
* [ ] [#B] Leaves
* [X] [#B] Leaves
* [X] [#B] Tracking
* [X] [#B] Set/show topic
* [ ] OMEMO (libsignal-protocol-c / axc)
* [ ] Presence
* [X] Disco
* [ ] Disco response
* [ ] Messages
* [ ] MUC PMs
* [ ] Send typing notifications
@ -117,6 +119,7 @@
* [ ] PGP (libgpgme)
** TODO [#C] Implement completion engine (milestone v0.3)
** TODO [#D] Close all issues (milestone v1.0)
* [ ] Absorb libomemo / axc, and drop glib
* Contributing

@ -601,6 +601,68 @@ struct t_channel_member *channel__add_member(struct t_account *account,
if (user)
user__nicklist_add(account, channel, user);
char *jid_bare = xmpp_jid_bare(account->context, user->id);
char *jid_resource = xmpp_jid_resource(account->context, user->id);
if (weechat_strcasecmp(jid_bare, channel->id) == 0
&& channel->type == CHANNEL_TYPE_MUC)
weechat_printf(channel->buffer, "%s%s entered",
weechat_prefix("join"),
jid_resource);
else
weechat_printf(channel->buffer, "%s%s (%s) entered",
weechat_prefix("join"),
xmpp_jid_bare(account->context, user->id),
xmpp_jid_resource(account->context, user->id));
return member;
}
struct t_channel_member *channel__member_search(struct t_channel *channel,
const char *id)
{
struct t_channel_member *ptr_member;
if (!channel || !id)
return NULL;
for (ptr_member = channel->members; ptr_member;
ptr_member = ptr_member->next_member)
{
if (weechat_strcasecmp(ptr_member->id, id) == 0)
return ptr_member;
}
return NULL;
}
struct t_channel_member *channel__remove_member(struct t_account *account,
struct t_channel *channel,
const char *id)
{
struct t_channel_member *member;
struct t_user *user;
user = user__search(account, id);
if (user)
user__nicklist_remove(account, channel, user);
member = channel__member_search(channel, id);
if (member)
channel__member_free(channel, member);
char *jid_bare = xmpp_jid_bare(account->context, user->id);
char *jid_resource = xmpp_jid_resource(account->context, user->id);
if (weechat_strcasecmp(jid_bare, channel->id) == 0
&& channel->type == CHANNEL_TYPE_MUC)
weechat_printf(channel->buffer, "%s%s left",
weechat_prefix("quit"),
jid_resource);
else
weechat_printf(channel->buffer, "%s%s (%s) left",
weechat_prefix("quit"),
xmpp_jid_bare(account->context, user->id),
xmpp_jid_resource(account->context, user->id));
return member;
}

@ -120,6 +120,10 @@ struct t_channel_member *channel__add_member(struct t_account *account,
struct t_channel *channel,
const char *id);
struct t_channel_member *channel__remove_member(struct t_account *account,
struct t_channel *channel,
const char *id);
void channel__send_message(struct t_account *account, struct t_channel *channel,
const char *to, const char *body);

@ -21,7 +21,7 @@ void connection__init()
xmpp_initialize();
}
int version_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
int connection__version_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
{
xmpp_stanza_t *reply, *query, *name, *version, *text;
const char *ns;
@ -72,37 +72,51 @@ int version_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
return 1;
}
int presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
{
(void) conn;
struct t_account *account = (struct t_account *)userdata;
struct t_user *user;
struct t_channel *channel;
const char *from, *from_bare;
xmpp_stanza_t *iq__x, *iq__x__item;
const char *from, *from_bare, *role = NULL, *affiliation = NULL;
from = xmpp_stanza_get_from(stanza);
if (from == NULL)
return 1;
from_bare = xmpp_jid_bare(account->context, from);
iq__x = xmpp_stanza_get_child_by_name_and_ns(
stanza, "x", "http://jabber.org/protocol/muc#user");
if (iq__x)
{
iq__x__item = xmpp_stanza_get_child_by_name(iq__x, "item");
role = xmpp_stanza_get_attribute(iq__x__item, "role");
affiliation = xmpp_stanza_get_attribute(iq__x__item, "affiliation");
}
user = user__search(account, from);
if (!user)
user = user__new(account, from, from);
channel = channel__search(account, from_bare);
if (!iq__x)
{
if (!channel)
channel = channel__new(account, CHANNEL_TYPE_PM, from_bare, from_bare);
channel__add_member(account, channel, from);
weechat_printf(account->buffer, "%s%s (%s) presence",
weechat_prefix("action"),
user->name, user->profile.display_name);
}
else if (channel)
{
if (weechat_strcasecmp(role, "none") == 0)
channel__remove_member(account, channel, from);
channel__add_member(account, channel, from);
}
return 1;
}
int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
{
(void) conn;
@ -184,6 +198,203 @@ int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
return 1;
}
#include <sys/utsname.h>
int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
{
(void) conn;
struct t_account *account = (struct t_account *)userdata;
xmpp_stanza_t *reply, *query, *identity, *feature, *x, *field, *value, *text;
char client_name[64], *node;
static struct utsname osinfo;
reply = xmpp_stanza_reply(stanza);
xmpp_stanza_set_type(reply, "result");
query = xmpp_stanza_get_child_by_name_and_ns(
stanza, "query", "http://jabber.org/protocol/disco#info");
node = xmpp_stanza_get_attribute(query, "node");
xmpp_stanza_set_attribute(reply, "id", node);
identity = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(identity, "identity");
xmpp_stanza_set_attribute(identity, "category", "client");
snprintf(client_name, sizeof(client_name),
"weechat %s", weechat_info_get("version", NULL));
xmpp_stanza_set_attribute(identity, "name", client_name);
xmpp_stanza_set_attribute(identity, "type", "pc");
xmpp_stanza_add_child(query, identity);
xmpp_stanza_release(identity);
#define FEATURE(ns) \
feature = xmpp_stanza_new(account->context); \
xmpp_stanza_set_name(feature, "feature"); \
xmpp_stanza_set_attribute(feature, "var", ns); \
xmpp_stanza_add_child(query, feature); \
xmpp_stanza_release(feature);
FEATURE("http://jabber.org/protocol/caps");
FEATURE("http://jabber.org/protocol/disco#info");
FEATURE("http://jabber.org/protocol/disco#items");
FEATURE("http://jabber.org/protocol/muc");
FEATURE("eu.siacs.conversations.axolotl.devicelist");
FEATURE("eu.siacs.conversations.axolotl.devicelist+notify");
#undef FEATURE
x = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(x, "x");
xmpp_stanza_set_ns(x, "jabber:x:data");
xmpp_stanza_set_attribute(x, "type", "result");
if (uname(&osinfo) >= 0)
{
osinfo.machine;
}
{
field = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(field, "field");
xmpp_stanza_set_attribute(field, "var", "FORM_TYPE");
xmpp_stanza_set_attribute(field, "type", "hidden");
value = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(value, "value");
text = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(text, "urn:xmpp:dataforms:softwareinfo");
xmpp_stanza_add_child(value, text);
xmpp_stanza_release(text);
xmpp_stanza_add_child(field, value);
xmpp_stanza_release(value);
xmpp_stanza_add_child(x, field);
xmpp_stanza_release(field);
}
{
field = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(field, "field");
xmpp_stanza_set_attribute(field, "var", "ip_version");
xmpp_stanza_set_attribute(field, "type", "text-multi");
value = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(value, "value");
text = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(text, "ipv4");
xmpp_stanza_add_child(value, text);
xmpp_stanza_release(text);
xmpp_stanza_add_child(field, value);
xmpp_stanza_release(value);
value = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(value, "value");
text = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(text, "ipv6");
xmpp_stanza_add_child(value, text);
xmpp_stanza_release(text);
xmpp_stanza_add_child(field, value);
xmpp_stanza_release(value);
xmpp_stanza_add_child(x, field);
xmpp_stanza_release(field);
}
{
field = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(field, "field");
xmpp_stanza_set_attribute(field, "var", "os");
value = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(value, "value");
text = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(text, osinfo.sysname);
xmpp_stanza_add_child(value, text);
xmpp_stanza_release(text);
xmpp_stanza_add_child(field, value);
xmpp_stanza_release(value);
xmpp_stanza_add_child(x, field);
xmpp_stanza_release(field);
}
{
field = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(field, "field");
xmpp_stanza_set_attribute(field, "var", "os_version");
value = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(value, "value");
text = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(text, osinfo.release);
xmpp_stanza_add_child(value, text);
xmpp_stanza_release(text);
xmpp_stanza_add_child(field, value);
xmpp_stanza_release(value);
xmpp_stanza_add_child(x, field);
xmpp_stanza_release(field);
}
{
field = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(field, "field");
xmpp_stanza_set_attribute(field, "var", "software");
value = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(value, "value");
text = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(text, "weechat");
xmpp_stanza_add_child(value, text);
xmpp_stanza_release(text);
xmpp_stanza_add_child(field, value);
xmpp_stanza_release(value);
xmpp_stanza_add_child(x, field);
xmpp_stanza_release(field);
}
{
field = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(field, "field");
xmpp_stanza_set_attribute(field, "var", "software_version");
value = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(value, "value");
text = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(text, weechat_info_get("version", NULL));
xmpp_stanza_add_child(value, text);
xmpp_stanza_release(text);
xmpp_stanza_add_child(field, value);
xmpp_stanza_release(value);
xmpp_stanza_add_child(x, field);
xmpp_stanza_release(field);
}
xmpp_stanza_add_child(query, x);
xmpp_stanza_release(x);
xmpp_stanza_add_child(reply, query);
xmpp_send(conn, reply);
xmpp_stanza_release(reply);
return 1;
}
void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status,
int error, xmpp_stream_error_t *stream_error,
void *userdata)
@ -197,9 +408,14 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status,
xmpp_stanza_t *pres, *pres__c, *pres__status, *pres__status__text;
char cap_hash[28+1] = {0};
xmpp_handler_add(conn, version_handler, "jabber:iq:version", "iq", NULL, account);
xmpp_handler_add(conn, presence_handler, NULL, "presence", NULL, account);
xmpp_handler_add(conn, message_handler, NULL, "message", /*type*/ NULL, account);
xmpp_handler_add(conn, connection__version_handler,
"jabber:iq:version", "iq", NULL, account);
xmpp_handler_add(conn, connection__presence_handler,
NULL, "presence", NULL, account);
xmpp_handler_add(conn, connection__message_handler,
NULL, "message", /*type*/ NULL, account);
xmpp_handler_add(conn, connection__iq_handler,
NULL, "iq", "get", account);
/* Send initial <presence/> so that we appear online to contacts */
pres = xmpp_presence_new(account->context);
@ -240,7 +456,7 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status,
}
}
char* rand_string(int length)
char* connection__rand_string(int length)
{
char *string = malloc(length);
srand(time(NULL));
@ -262,7 +478,7 @@ int connection__connect(struct t_account *account, xmpp_conn_t **connection,
const char *resource = account_resource(account);
if (!(resource && strlen(resource)))
{
char *const rand = rand_string(8);
char *const rand = connection__rand_string(8);
char ident[64] = {0};
snprintf(ident, sizeof(ident), "weechat.%s", rand);
free(rand);

@ -115,6 +115,26 @@ void user__nicklist_add(struct t_account *account,
1);
}
void user__nicklist_remove(struct t_account *account,
struct t_channel *channel,
struct t_user *user)
{
struct t_gui_nick_group *ptr_group;
struct t_gui_buffer *ptr_buffer;
char *name = user->profile.display_name;
if (channel && weechat_strcasecmp(xmpp_jid_bare(account->context, name),
channel->id) == 0)
name = xmpp_jid_resource(account->context, name);
ptr_buffer = channel ? channel->buffer : account->buffer;
ptr_group = weechat_nicklist_search_group(ptr_buffer, NULL,
user->is_away ?
"+" : "...");
weechat_nicklist_remove_nick(ptr_buffer,
weechat_nicklist_search_nick(ptr_buffer, ptr_group, name));
}
struct t_user *user__new(struct t_account *account,
const char *id, const char *display_name)
{

@ -75,4 +75,8 @@ void user__nicklist_add(struct t_account *account,
struct t_channel *channel,
struct t_user *user);
void user__nicklist_remove(struct t_account *account,
struct t_channel *channel,
struct t_user *user);
#endif /*WEECHAT_XMPP_USER_H*/

Loading…
Cancel
Save