mirror of
https://github.com/profanity-im/profanity.git
synced 2024-11-03 19:37:16 -05:00
add subscription support
This commit is contained in:
parent
7958a450bd
commit
c3b0e80432
@ -199,12 +199,18 @@ static struct cmd_t main_commands[] =
|
|||||||
|
|
||||||
{ "/sub",
|
{ "/sub",
|
||||||
_cmd_sub,
|
_cmd_sub,
|
||||||
{ "/sub user@host", "Subscribe to presence notifications of user.",
|
{ "/sub <add|del|request|show> [jid]", "Manage subscriptions.",
|
||||||
{ "/sub user@host",
|
{ "/sub <add|del|request|show> [jid]",
|
||||||
"------------------",
|
"------------------",
|
||||||
"Send a subscription request to the user to be informed of their presence.",
|
"add : Approve subscription to a contact.",
|
||||||
|
"del : Remove subscription for a contact.",
|
||||||
|
"request : Send a subscription request to the user to be informed of their",
|
||||||
|
" : presence.",
|
||||||
|
"show : Show subscriprion status for a contact.",
|
||||||
"",
|
"",
|
||||||
"Example: /sub myfriend@jabber.org",
|
"If optional parameter 'jid' isn't set command belongs to the current window.",
|
||||||
|
"",
|
||||||
|
"Example: /sub add myfriend@jabber.org",
|
||||||
NULL } } },
|
NULL } } },
|
||||||
|
|
||||||
{ "/tiny",
|
{ "/tiny",
|
||||||
@ -710,6 +716,8 @@ _cmd_complete_parameters(char *input, int *size)
|
|||||||
contact_list_find_contact);
|
contact_list_find_contact);
|
||||||
_parameter_autocomplete(input, size, "/connect",
|
_parameter_autocomplete(input, size, "/connect",
|
||||||
prefs_find_login);
|
prefs_find_login);
|
||||||
|
_parameter_autocomplete(input, size, "/sub",
|
||||||
|
prefs_autocomplete_sub_cmd);
|
||||||
_parameter_autocomplete(input, size, "/help",
|
_parameter_autocomplete(input, size, "/help",
|
||||||
_cmd_help_complete);
|
_cmd_help_complete);
|
||||||
_parameter_autocomplete(input, size, "/who",
|
_parameter_autocomplete(input, size, "/who",
|
||||||
@ -775,13 +783,40 @@ _cmd_sub(const char * const inp, struct cmd_help_t help)
|
|||||||
cons_show("Usage: %s", help.usage);
|
cons_show("Usage: %s", help.usage);
|
||||||
result = TRUE;
|
result = TRUE;
|
||||||
} else {
|
} else {
|
||||||
char *user, *lower;
|
char *inp_cpy, *subcmd;
|
||||||
user = strndup(inp+5, strlen(inp)-5);
|
char *jid, *bare_jid;
|
||||||
lower = g_utf8_strdown(user, -1);
|
|
||||||
|
|
||||||
jabber_subscribe(lower);
|
inp_cpy = strndup(inp+5, strlen(inp)-5);
|
||||||
cons_show("Sent subscription request to %s.", user);
|
/* using strtok is bad idea */
|
||||||
|
subcmd = strtok(inp_cpy, " ");
|
||||||
|
jid = strtok(NULL, " ");
|
||||||
|
|
||||||
|
if (jid != NULL) {
|
||||||
|
jid = strdup(jid);
|
||||||
|
} else {
|
||||||
|
jid = win_get_recipient();
|
||||||
|
}
|
||||||
|
|
||||||
|
bare_jid = strtok(jid, "/");
|
||||||
|
|
||||||
|
if (strcmp(subcmd, "add") == 0) {
|
||||||
|
jabber_subscription(bare_jid, PRESENCE_SUBSCRIBED);
|
||||||
|
cons_show("Accepted subscription for %s", bare_jid);
|
||||||
|
log_info("Accepted subscription for %s", bare_jid);
|
||||||
|
} else if (strcmp(subcmd, "del") == 0) {
|
||||||
|
jabber_subscription(bare_jid, PRESENCE_UNSUBSCRIBED);
|
||||||
|
cons_show("Deleted subscription for %s", bare_jid);
|
||||||
|
log_info("Deleted subscription for %s", bare_jid);
|
||||||
|
} else if (strcmp(subcmd, "request") == 0) {
|
||||||
|
jabber_subscription(bare_jid, PRESENCE_SUBSCRIBE);
|
||||||
|
cons_show("Sent subscription request to %s.", bare_jid);
|
||||||
|
log_info("Sent subscription request to %s.", bare_jid);
|
||||||
|
} else if (strcmp(subcmd, "show") == 0) {
|
||||||
|
/* TODO: not implemented yet */
|
||||||
|
}
|
||||||
|
|
||||||
|
free(jid);
|
||||||
|
free(inp_cpy);
|
||||||
result = TRUE;
|
result = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
40
src/jabber.c
40
src/jabber.c
@ -219,16 +219,31 @@ jabber_send_gone(const char * const recipient)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
jabber_subscribe(const char * const recipient)
|
jabber_subscription(const char * const jid, jabber_subscr_t action)
|
||||||
{
|
{
|
||||||
xmpp_stanza_t *presence;
|
xmpp_stanza_t *presence;
|
||||||
|
char *type, *jid_cpy, *bare_jid;
|
||||||
|
|
||||||
|
// jid must be a bare JID
|
||||||
|
jid_cpy = strdup(jid);
|
||||||
|
bare_jid = strtok(jid_cpy, "/");
|
||||||
|
|
||||||
|
if (action == PRESENCE_SUBSCRIBE)
|
||||||
|
type = STANZA_TYPE_SUBSCRIBE;
|
||||||
|
else if (action == PRESENCE_SUBSCRIBED)
|
||||||
|
type = STANZA_TYPE_SUBSCRIBED;
|
||||||
|
else if (action == PRESENCE_UNSUBSCRIBED)
|
||||||
|
type = STANZA_TYPE_UNSUBSCRIBED;
|
||||||
|
else // unknown action
|
||||||
|
return;
|
||||||
|
|
||||||
presence = xmpp_stanza_new(jabber_conn.ctx);
|
presence = xmpp_stanza_new(jabber_conn.ctx);
|
||||||
xmpp_stanza_set_name(presence, STANZA_NAME_PRESENCE);
|
xmpp_stanza_set_name(presence, STANZA_NAME_PRESENCE);
|
||||||
xmpp_stanza_set_type(presence, STANZA_TYPE_SUBSCRIBE);
|
xmpp_stanza_set_type(presence, type);
|
||||||
xmpp_stanza_set_attribute(presence, STANZA_ATTR_TO, recipient);
|
xmpp_stanza_set_attribute(presence, STANZA_ATTR_TO, bare_jid);
|
||||||
xmpp_send(jabber_conn.conn, presence);
|
xmpp_send(jabber_conn.conn, presence);
|
||||||
xmpp_stanza_release(presence);
|
xmpp_stanza_release(presence);
|
||||||
|
free(jid_cpy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -698,12 +713,7 @@ _presence_handler(xmpp_conn_t * const conn,
|
|||||||
else
|
else
|
||||||
status_str = NULL;
|
status_str = NULL;
|
||||||
|
|
||||||
if ((type != NULL) && (strcmp(type, STANZA_TYPE_UNAVAILABLE) == 0)) {
|
if (type == NULL) { // available
|
||||||
if (strcmp(short_jid, short_from) !=0) {
|
|
||||||
prof_handle_contact_offline(short_from, "offline", status_str);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
xmpp_stanza_t *show = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_SHOW);
|
xmpp_stanza_t *show = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_SHOW);
|
||||||
if (show != NULL)
|
if (show != NULL)
|
||||||
show_str = xmpp_stanza_get_text(show);
|
show_str = xmpp_stanza_get_text(show);
|
||||||
@ -713,6 +723,18 @@ _presence_handler(xmpp_conn_t * const conn,
|
|||||||
if (strcmp(short_jid, short_from) !=0) {
|
if (strcmp(short_jid, short_from) !=0) {
|
||||||
prof_handle_contact_online(short_from, show_str, status_str);
|
prof_handle_contact_online(short_from, show_str, status_str);
|
||||||
}
|
}
|
||||||
|
} else if (strcmp(type, STANZA_TYPE_UNAVAILABLE) == 0) {
|
||||||
|
if (strcmp(short_jid, short_from) !=0) {
|
||||||
|
prof_handle_contact_offline(short_from, "offline", status_str);
|
||||||
|
}
|
||||||
|
} else if (strcmp(type, STANZA_TYPE_SUBSCRIBE) == 0) {
|
||||||
|
prof_handle_subscription(short_from, PRESENCE_SUBSCRIBE);
|
||||||
|
} else if (strcmp(type, STANZA_TYPE_SUBSCRIBED) == 0) {
|
||||||
|
prof_handle_subscription(short_from, PRESENCE_SUBSCRIBED);
|
||||||
|
} else if (strcmp(type, STANZA_TYPE_UNSUBSCRIBED) == 0) {
|
||||||
|
prof_handle_subscription(short_from, PRESENCE_UNSUBSCRIBED);
|
||||||
|
} else { /* unknown type */
|
||||||
|
log_debug("Received presence with unknown type '%s'", type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,14 +40,20 @@ typedef enum {
|
|||||||
PRESENCE_XA
|
PRESENCE_XA
|
||||||
} jabber_presence_t;
|
} jabber_presence_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PRESENCE_SUBSCRIBE,
|
||||||
|
PRESENCE_SUBSCRIBED,
|
||||||
|
PRESENCE_UNSUBSCRIBED
|
||||||
|
} jabber_subscr_t;
|
||||||
|
|
||||||
void jabber_init(const int disable_tls);
|
void jabber_init(const int disable_tls);
|
||||||
jabber_conn_status_t jabber_connect(const char * const user,
|
jabber_conn_status_t jabber_connect(const char * const user,
|
||||||
const char * const passwd);
|
const char * const passwd);
|
||||||
void jabber_disconnect(void);
|
void jabber_disconnect(void);
|
||||||
void jabber_process_events(void);
|
void jabber_process_events(void);
|
||||||
void jabber_subscribe(const char * const recipient);
|
|
||||||
void jabber_join(const char * const room, const char * const nick);
|
void jabber_join(const char * const room, const char * const nick);
|
||||||
void jabber_leave_chat_room(const char * const room_jid);
|
void jabber_leave_chat_room(const char * const room_jid);
|
||||||
|
void jabber_subscription(const char * const jid, jabber_subscr_t action);
|
||||||
void jabber_send(const char * const msg, const char * const recipient);
|
void jabber_send(const char * const msg, const char * const recipient);
|
||||||
void jabber_send_groupchat(const char * const msg, const char * const recipient);
|
void jabber_send_groupchat(const char * const msg, const char * const recipient);
|
||||||
void jabber_send_inactive(const char * const recipient);
|
void jabber_send_inactive(const char * const recipient);
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "preferences.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -41,6 +42,7 @@ static GKeyFile *prefs;
|
|||||||
|
|
||||||
static PAutocomplete login_ac;
|
static PAutocomplete login_ac;
|
||||||
static PAutocomplete boolean_choice_ac;
|
static PAutocomplete boolean_choice_ac;
|
||||||
|
static PAutocomplete sub_cmd_ac;
|
||||||
|
|
||||||
struct colour_string_t {
|
struct colour_string_t {
|
||||||
char *str;
|
char *str;
|
||||||
@ -116,6 +118,11 @@ prefs_load(void)
|
|||||||
p_autocomplete_add(boolean_choice_ac, strdup("on"));
|
p_autocomplete_add(boolean_choice_ac, strdup("on"));
|
||||||
p_autocomplete_add(boolean_choice_ac, strdup("off"));
|
p_autocomplete_add(boolean_choice_ac, strdup("off"));
|
||||||
|
|
||||||
|
sub_cmd_ac = p_autocomplete_new();
|
||||||
|
p_autocomplete_add(sub_cmd_ac, strdup("add"));
|
||||||
|
p_autocomplete_add(sub_cmd_ac, strdup("del"));
|
||||||
|
p_autocomplete_add(sub_cmd_ac, strdup("request"));
|
||||||
|
p_autocomplete_add(sub_cmd_ac, strdup("show"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -123,6 +130,7 @@ prefs_close(void)
|
|||||||
{
|
{
|
||||||
p_autocomplete_clear(login_ac);
|
p_autocomplete_clear(login_ac);
|
||||||
p_autocomplete_clear(boolean_choice_ac);
|
p_autocomplete_clear(boolean_choice_ac);
|
||||||
|
p_autocomplete_clear(sub_cmd_ac);
|
||||||
g_key_file_free(prefs);
|
g_key_file_free(prefs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,6 +230,22 @@ prefs_reset_boolean_choice(void)
|
|||||||
p_autocomplete_reset(boolean_choice_ac);
|
p_autocomplete_reset(boolean_choice_ac);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
prefs_autocomplete_sub_cmd(char *prefix)
|
||||||
|
{
|
||||||
|
char *result;
|
||||||
|
result = p_autocomplete_complete(sub_cmd_ac, prefix);
|
||||||
|
/* TODO: fix the problem with ac->last_found instead of this hack */
|
||||||
|
prefs_reset_sub_cmd();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
prefs_reset_sub_cmd(void)
|
||||||
|
{
|
||||||
|
p_autocomplete_reset(sub_cmd_ac);
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
prefs_get_beep(void)
|
prefs_get_beep(void)
|
||||||
{
|
{
|
||||||
|
@ -41,6 +41,8 @@ char * prefs_find_login(char *prefix);
|
|||||||
void prefs_reset_login_search(void);
|
void prefs_reset_login_search(void);
|
||||||
char * prefs_autocomplete_boolean_choice(char *prefix);
|
char * prefs_autocomplete_boolean_choice(char *prefix);
|
||||||
void prefs_reset_boolean_choice(void);
|
void prefs_reset_boolean_choice(void);
|
||||||
|
char * prefs_autocomplete_sub_cmd(char *prefix);
|
||||||
|
void prefs_reset_sub_cmd(void);
|
||||||
|
|
||||||
gboolean prefs_get_beep(void);
|
gboolean prefs_get_beep(void);
|
||||||
void prefs_set_beep(gboolean value);
|
void prefs_set_beep(gboolean value);
|
||||||
|
@ -144,6 +144,32 @@ prof_handle_error_message(const char *from, const char *err_msg)
|
|||||||
win_show_error_msg(from, err_msg);
|
win_show_error_msg(from, err_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
prof_handle_subscription(const char *from, jabber_subscr_t type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case PRESENCE_SUBSCRIBE:
|
||||||
|
/* TODO: auto-subscribe if needed */
|
||||||
|
cons_show("Received authorization request from %s", from);
|
||||||
|
log_info("Received authorization request from %s", from);
|
||||||
|
win_show_system_msg(from, "Authorization request, type '/sub add' to accept or '/sub del' to reject");
|
||||||
|
break;
|
||||||
|
case PRESENCE_SUBSCRIBED:
|
||||||
|
cons_show("Subscription received from %s", from);
|
||||||
|
log_info("Subscription received from %s", from);
|
||||||
|
win_show_system_msg(from, "Subscribed");
|
||||||
|
break;
|
||||||
|
case PRESENCE_UNSUBSCRIBED:
|
||||||
|
cons_show("%s deleted subscription", from);
|
||||||
|
log_info("%s deleted subscription", from);
|
||||||
|
win_show_system_msg(from, "Unsubscribed");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* unknown type */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
prof_handle_login_success(const char *jid)
|
prof_handle_login_success(const char *jid)
|
||||||
{
|
{
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
#ifndef PROFANITY_H
|
#ifndef PROFANITY_H
|
||||||
#define PROFANITY_H
|
#define PROFANITY_H
|
||||||
|
|
||||||
|
#include "jabber.h"
|
||||||
|
|
||||||
void prof_run(const int disable_tls, char *log_level);
|
void prof_run(const int disable_tls, char *log_level);
|
||||||
|
|
||||||
void prof_handle_login_success(const char *jid);
|
void prof_handle_login_success(const char *jid);
|
||||||
@ -34,6 +36,7 @@ void prof_handle_contact_offline(char *contact, char *show, char *status);
|
|||||||
void prof_handle_incoming_message(char *from, char *message);
|
void prof_handle_incoming_message(char *from, char *message);
|
||||||
void prof_handle_delayed_message(char *from, char *message, GTimeVal tv_stamp);
|
void prof_handle_delayed_message(char *from, char *message, GTimeVal tv_stamp);
|
||||||
void prof_handle_error_message(const char *from, const char *err_msg);
|
void prof_handle_error_message(const char *from, const char *err_msg);
|
||||||
|
void prof_handle_subscription(const char *from, jabber_subscr_t type);
|
||||||
void prof_handle_roster(GSList *roster);
|
void prof_handle_roster(GSList *roster);
|
||||||
void prof_handle_gone(const char * const from);
|
void prof_handle_gone(const char * const from);
|
||||||
void prof_handle_room_history(const char * const room_jid,
|
void prof_handle_room_history(const char * const room_jid,
|
||||||
|
@ -49,6 +49,8 @@
|
|||||||
#define STANZA_TYPE_GROUPCHAT "groupchat"
|
#define STANZA_TYPE_GROUPCHAT "groupchat"
|
||||||
#define STANZA_TYPE_UNAVAILABLE "unavailable"
|
#define STANZA_TYPE_UNAVAILABLE "unavailable"
|
||||||
#define STANZA_TYPE_SUBSCRIBE "subscribe"
|
#define STANZA_TYPE_SUBSCRIBE "subscribe"
|
||||||
|
#define STANZA_TYPE_SUBSCRIBED "subscribed"
|
||||||
|
#define STANZA_TYPE_UNSUBSCRIBED "unsubscribed"
|
||||||
#define STANZA_TYPE_GET "get"
|
#define STANZA_TYPE_GET "get"
|
||||||
#define STANZA_TYPE_ERROR "error"
|
#define STANZA_TYPE_ERROR "error"
|
||||||
|
|
||||||
|
1
src/ui.h
1
src/ui.h
@ -91,6 +91,7 @@ void win_show_gone(const char * const from);
|
|||||||
void win_show_incomming_msg(const char * const from, const char * const message,
|
void win_show_incomming_msg(const char * const from, const char * const message,
|
||||||
GTimeVal *tv_stamp);
|
GTimeVal *tv_stamp);
|
||||||
void win_show_error_msg(const char * const from, const char *err_msg);
|
void win_show_error_msg(const char * const from, const char *err_msg);
|
||||||
|
void win_show_system_msg(const char * const from, const char *message);
|
||||||
void win_show_outgoing_msg(const char * const from, const char * const to,
|
void win_show_outgoing_msg(const char * const from, const char * const to,
|
||||||
const char * const message);
|
const char * const message);
|
||||||
void win_handle_special_keys(const int * const ch);
|
void win_handle_special_keys(const int * const ch);
|
||||||
|
@ -433,6 +433,39 @@ win_show_gone(const char * const from)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
win_show_system_msg(const char * const from, const char *message)
|
||||||
|
{
|
||||||
|
int win_index;
|
||||||
|
WINDOW *win;
|
||||||
|
char from_cpy[strlen(from) + 1];
|
||||||
|
char *bare_jid;
|
||||||
|
|
||||||
|
if (from == NULL || message == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
strcpy(from_cpy, from);
|
||||||
|
bare_jid = strtok(from_cpy, "/");
|
||||||
|
|
||||||
|
win_index = _find_prof_win_index(bare_jid);
|
||||||
|
if (win_index == NUM_WINS) {
|
||||||
|
win_index = _new_prof_win(bare_jid);
|
||||||
|
status_bar_active(win_index);
|
||||||
|
dirty = TRUE;
|
||||||
|
}
|
||||||
|
win = _wins[win_index].win;
|
||||||
|
|
||||||
|
_win_show_time(win);
|
||||||
|
wattron(win, COLOUR_ONLINE);
|
||||||
|
wprintw(win, "*%s %s\n", bare_jid, message);
|
||||||
|
wattroff(win, COLOUR_ONLINE);
|
||||||
|
|
||||||
|
// this is the current window
|
||||||
|
if (win_index == _curr_prof_win) {
|
||||||
|
dirty = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_LIBNOTIFY
|
#ifdef HAVE_LIBNOTIFY
|
||||||
static void
|
static void
|
||||||
_win_notify(const char * const message, int timeout,
|
_win_notify(const char * const message, int timeout,
|
||||||
|
Loading…
Reference in New Issue
Block a user