From f6c67a1a337278b5b1a7238c2e194680e4b65f49 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Thu, 1 Jul 2021 21:37:43 +0100 Subject: [PATCH] merry MUCmas --- Makefile | 2 +- README.org | 20 ++++++-- channel.c | 17 ++++--- command.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++ connection.c | 9 ++++ 5 files changed, 174 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index 9a19fb7..b452cdd 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,7 @@ xmpp.so: $(OBJS) test: xmpp.so env LD_PRELOAD=$(DEBUG) \ - weechat -a -P 'buflist,irc' -r '/plugin load ./xmpp.so' + weechat -a -P 'alias,buflist,irc' -r '/plugin load ./xmpp.so' debug: xmpp.so gdb -ex "handle SIGPIPE nostop noprint pass" --args \ diff --git a/README.org b/README.org index 4e9bd15..d93dc88 100644 --- a/README.org +++ b/README.org @@ -74,18 +74,28 @@ * Tasks ** DONE [#A] Implement basic functionality (milestone v0.1) - * [x] Connecting - * [x] Pretty-printing stanzas - * [x] Receiveing and formatting PMs to a dedicated buffer - * [x] Responding to PMs and formatting responses + * [X] Connecting + * [X] Pretty-printing stanzas + * [X] Receiveing and formatting PMs to a dedicated buffer + * [X] Responding to PMs and formatting responses + * [X] Opening PMs (/chat) ** TODO [#A] Implement essential functionality (milestone v0.2) + * [X] Opening PMs with initial message + * [ ] Handle wide errors gracefully * [ ] MUCs + * [X] Opening (/enter) + * [X] Receiving + * [X] Sending + * [ ] [#B] Handle errors gracefully + * [ ] [#B] Presence/nicklist + * [ ] [#B] Show topic + * [ ] [#B] Edits * [ ] OMEMO presence * [ ] OMEMO messages * [ ] MUC PMs * [ ] Send typing notifications * [ ] Recv typing notifications -** TODO [#B] Implement completion engine (milestone v0.3) +** TODO [#C] Implement completion engine (milestone v0.3) ** TODO [#D] Close all issues (milestone v1.0) * Contributing diff --git a/channel.c b/channel.c index 8b3fed8..09e56b1 100644 --- a/channel.c +++ b/channel.c @@ -117,11 +117,12 @@ struct t_gui_buffer *channel__create_buffer(struct t_account *account, if (!short_name || (localvar_channel && (strcmp(localvar_channel, short_name) == 0))) { - weechat_buffer_set (ptr_buffer, "short_name", name); + weechat_buffer_set (ptr_buffer, "short_name", xmpp_jid_node(account->context, + name)); } } - weechat_buffer_set(ptr_buffer, "name", buffer_name); + weechat_buffer_set(ptr_buffer, "name", name); weechat_buffer_set(ptr_buffer, "localvar_set_type", (type == CHANNEL_TYPE_PM) ? "private" : "channel"); weechat_buffer_set(ptr_buffer, "localvar_set_nick", account->nickname); @@ -601,11 +602,15 @@ struct t_channel_member *channel__add_member(struct t_account *account, void channel__send_message(struct t_account *account, struct t_channel *channel, const char *to, const char *body) { - struct xmpp_stanza_t *message = xmpp_message_new(account->context, "chat", to, NULL); + struct xmpp_stanza_t *message = xmpp_message_new(account->context, + channel->type == CHANNEL_TYPE_MUC + ? "groupchat" : "chat", + to, NULL); xmpp_message_set_body(message, body); xmpp_send(account->connection, message); xmpp_stanza_release(message); - weechat_printf(channel->buffer, "%s: %s", - weechat_config_string(account->options[ACCOUNT_OPTION_JID]), - body); + if (channel->type != CHANNEL_TYPE_MUC) + weechat_printf(channel->buffer, "%s: %s", + weechat_config_string(account->options[ACCOUNT_OPTION_JID]), + body); } diff --git a/command.c b/command.c index 25a75d7..a5c5799 100644 --- a/command.c +++ b/command.c @@ -327,6 +327,126 @@ int command__account(const void *pointer, void *data, return WEECHAT_RC_OK; } +int command__enter(const void *pointer, void *data, + struct t_gui_buffer *buffer, int argc, + char **argv, char **argv_eol) +{ + struct t_account *ptr_account = NULL; + struct t_channel *ptr_channel = NULL; + struct xmpp_stanza_t *pres; + char *jid, *pres_jid, *text; + + (void) pointer; + (void) data; + (void) argv; + + buffer__get_account_and_channel(buffer, &ptr_account, &ptr_channel); + + if (!ptr_account) + return WEECHAT_RC_ERROR; + + if (!ptr_account->is_connected) + { + weechat_printf(buffer, + _("%s%s: you are not connected to server"), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME); + return WEECHAT_RC_OK; + } + + if (argc > 1) + { + jid = argv[1]; + pres_jid = argv[1]; + + if(!xmpp_jid_resource(ptr_account->context, pres_jid)) + pres_jid = xmpp_jid_new( + ptr_account->context, + xmpp_jid_node(ptr_account->context, jid), + xmpp_jid_domain(ptr_account->context, jid), + weechat_config_string(ptr_account->options[ACCOUNT_OPTION_NICKNAME]) + && strlen(weechat_config_string(ptr_account->options[ACCOUNT_OPTION_NICKNAME])) + ? weechat_config_string(ptr_account->options[ACCOUNT_OPTION_NICKNAME]) + : xmpp_jid_node(ptr_account->context, + weechat_config_string(ptr_account->options[ACCOUNT_OPTION_JID]))); + + ptr_channel = channel__search(ptr_account, jid); + if (!ptr_channel) + ptr_channel = channel__new(ptr_account, CHANNEL_TYPE_MUC, jid, jid); + + pres = xmpp_presence_new(ptr_account->context); + xmpp_stanza_set_to(pres, pres_jid); + xmpp_stanza_set_from(pres, weechat_config_string(ptr_account->options[ACCOUNT_OPTION_JID])); + + struct xmpp_stanza_t *pres__x = xmpp_stanza_new(ptr_account->context); + xmpp_stanza_set_name(pres__x, "x"); + xmpp_stanza_set_ns(pres__x, "http://jabber.org/protocol/muc"); + xmpp_stanza_add_child(pres, pres__x); + + xmpp_send(ptr_account->connection, pres); + xmpp_stanza_release(pres__x); + xmpp_stanza_release(pres); + + if (argc > 2) + { + text = argv_eol[2]; + + channel__send_message(ptr_account, ptr_channel, jid, text); + } + } + + return WEECHAT_RC_OK; +} + +int command__open(const void *pointer, void *data, + struct t_gui_buffer *buffer, int argc, + char **argv, char **argv_eol) +{ + struct t_account *ptr_account = NULL; + struct t_channel *ptr_channel = NULL; + struct xmpp_stanza_t *pres; + char *jid, *text; + + (void) pointer; + (void) data; + (void) argv; + + buffer__get_account_and_channel(buffer, &ptr_account, &ptr_channel); + + if (!ptr_account) + return WEECHAT_RC_ERROR; + + if (!ptr_account->is_connected) + { + weechat_printf(buffer, + _("%s%s: you are not connected to server"), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME); + return WEECHAT_RC_OK; + } + + if (argc > 1) + { + jid = argv[1]; + + pres = xmpp_presence_new(ptr_account->context); + xmpp_stanza_set_to(pres, jid); + xmpp_send(ptr_account->connection, pres); + xmpp_stanza_release(pres); + + ptr_channel = channel__search(ptr_account, jid); + if (!ptr_channel) + ptr_channel = channel__new(ptr_account, CHANNEL_TYPE_PM, jid, jid); + + if (argc > 2) + { + text = argv_eol[2]; + + channel__send_message(ptr_account, ptr_channel, jid, text); + } + } + + return WEECHAT_RC_OK; +} + int command__me(const void *pointer, void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) @@ -401,6 +521,24 @@ void command__init() if (!hook) weechat_printf(NULL, "Failed to setup command /account"); + hook = weechat_hook_command( + "enter", + N_("enter an xmpp multi-user-chat (muc)"), + N_(""), + N_("jid: muc to enter"), + NULL, &command__enter, NULL, NULL); + if (!hook) + weechat_printf(NULL, "Failed to setup command /enter"); + + hook = weechat_hook_command( + "open", + N_("open a direct xmpp chat"), + N_(""), + N_("jid: jid to target"), + NULL, &command__open, NULL, NULL); + if (!hook) + weechat_printf(NULL, "Failed to setup command /chat"); + hook = weechat_hook_command( "me", N_("send a xmpp action to the current channel"), diff --git a/connection.c b/connection.c index c8adde4..49aaf61 100644 --- a/connection.c +++ b/connection.c @@ -92,6 +92,15 @@ int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) if (!channel) channel = channel__new(account, CHANNEL_TYPE_PM, from_bare, from_bare); + if (weechat_strcasecmp(type, "groupchat") == 0) + { + from = weechat_strcasecmp(channel->name, + xmpp_jid_bare(account->context, + from)) == 0 + ? xmpp_jid_resource(account->context, from) + : from; + } + if (strcmp(to, channel->id) == 0) weechat_printf(channel->buffer, "%s [to %s]: %s", from, to, intext); else if (strncmp(intext, "/me ", 4) == 0)