1
0
mirror of https://github.com/profanity-im/profanity.git synced 2024-07-07 18:04:15 -04:00

Merge pull request #63 from pasis/subscription

add subscription support
This commit is contained in:
James Booth 2012-11-11 10:41:28 -08:00
commit a5983cacb0
9 changed files with 173 additions and 23 deletions

View File

@ -65,11 +65,13 @@ static gboolean _cmd_set_boolean_preference(const char * const inp,
static char *_cmd_complete(char *inp);
static void _cmd_reset_command_completer(void);
static char *_cmd_who_complete(char *inp);
static void _cmd_reset_who_completer(void);
static void _cmd_who_reset_completer(void);
static char *_cmd_help_complete(char *inp);
static void _cmd_help_reset_completer(void);
static char *_cmd_notify_complete(char *inp);
static void _cmd_notify_reset_completer(void);
static char *_cmd_sub_complete(char *inp);
static void _cmd_sub_reset_completer(void);
static void _cmd_complete_parameters(char *input, int *size);
static void _notify_autocomplete(char *input, int *size);
static void _parameter_autocomplete(char *input, int *size, char *command,
@ -199,12 +201,18 @@ static struct cmd_t main_commands[] =
{ "/sub",
_cmd_sub,
{ "/sub user@host", "Subscribe to presence notifications of user.",
{ "/sub user@host",
{ "/sub <add|del|request|show> [jid]", "Manage subscriptions.",
{ "/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 } } },
{ "/tiny",
@ -462,6 +470,7 @@ static PAutocomplete commands_ac;
static PAutocomplete who_ac;
static PAutocomplete help_ac;
static PAutocomplete notify_ac;
static PAutocomplete sub_ac;
/*
* Initialise command autocompleter and history
@ -485,6 +494,12 @@ cmd_init(void)
p_autocomplete_add(notify_ac, strdup("typing"));
p_autocomplete_add(notify_ac, strdup("remind"));
sub_ac = p_autocomplete_new();
p_autocomplete_add(sub_ac, strdup("add"));
p_autocomplete_add(sub_ac, strdup("del"));
p_autocomplete_add(sub_ac, strdup("request"));
p_autocomplete_add(sub_ac, strdup("show"));
unsigned int i;
for (i = 0; i < ARRAY_SIZE(main_commands); i++) {
struct cmd_t *pcmd = main_commands+i;
@ -554,8 +569,9 @@ cmd_reset_autocomplete()
prefs_reset_boolean_choice();
_cmd_help_reset_completer();
_cmd_notify_reset_completer();
_cmd_sub_reset_completer();
_cmd_who_reset_completer();
_cmd_reset_command_completer();
_cmd_reset_who_completer();
}
GSList *
@ -655,7 +671,7 @@ _cmd_who_complete(char *inp)
}
static void
_cmd_reset_who_completer(void)
_cmd_who_reset_completer(void)
{
p_autocomplete_reset(who_ac);
}
@ -684,6 +700,18 @@ _cmd_notify_reset_completer(void)
p_autocomplete_reset(notify_ac);
}
static char *
_cmd_sub_complete(char *inp)
{
return p_autocomplete_complete(sub_ac, inp);
}
static void
_cmd_sub_reset_completer(void)
{
p_autocomplete_reset(sub_ac);
}
static void
_cmd_complete_parameters(char *input, int *size)
{
@ -710,6 +738,8 @@ _cmd_complete_parameters(char *input, int *size)
contact_list_find_contact);
_parameter_autocomplete(input, size, "/connect",
prefs_find_login);
_parameter_autocomplete(input, size, "/sub",
_cmd_sub_complete);
_parameter_autocomplete(input, size, "/help",
_cmd_help_complete);
_parameter_autocomplete(input, size, "/who",
@ -775,13 +805,40 @@ _cmd_sub(const char * const inp, struct cmd_help_t help)
cons_show("Usage: %s", help.usage);
result = TRUE;
} else {
char *user, *lower;
user = strndup(inp+5, strlen(inp)-5);
lower = g_utf8_strdown(user, -1);
char *inp_cpy, *subcmd;
char *jid, *bare_jid;
jabber_subscribe(lower);
cons_show("Sent subscription request to %s.", user);
inp_cpy = strndup(inp+5, strlen(inp)-5);
/* 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;
}

View File

@ -219,16 +219,31 @@ jabber_send_gone(const char * const recipient)
}
void
jabber_subscribe(const char * const recipient)
jabber_subscription(const char * const jid, jabber_subscr_t action)
{
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);
xmpp_stanza_set_name(presence, STANZA_NAME_PRESENCE);
xmpp_stanza_set_type(presence, STANZA_TYPE_SUBSCRIBE);
xmpp_stanza_set_attribute(presence, STANZA_ATTR_TO, recipient);
xmpp_stanza_set_type(presence, type);
xmpp_stanza_set_attribute(presence, STANZA_ATTR_TO, bare_jid);
xmpp_send(jabber_conn.conn, presence);
xmpp_stanza_release(presence);
free(jid_cpy);
}
void
@ -698,12 +713,7 @@ _presence_handler(xmpp_conn_t * const conn,
else
status_str = NULL;
if ((type != NULL) && (strcmp(type, STANZA_TYPE_UNAVAILABLE) == 0)) {
if (strcmp(short_jid, short_from) !=0) {
prof_handle_contact_offline(short_from, "offline", status_str);
}
} else {
if (type == NULL) { // available
xmpp_stanza_t *show = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_SHOW);
if (show != NULL)
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) {
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);
}
}

View File

@ -40,14 +40,20 @@ typedef enum {
PRESENCE_XA
} jabber_presence_t;
typedef enum {
PRESENCE_SUBSCRIBE,
PRESENCE_SUBSCRIBED,
PRESENCE_UNSUBSCRIBED
} jabber_subscr_t;
void jabber_init(const int disable_tls);
jabber_conn_status_t jabber_connect(const char * const user,
const char * const passwd);
void jabber_disconnect(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_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_groupchat(const char * const msg, const char * const recipient);
void jabber_send_inactive(const char * const recipient);

View File

@ -21,6 +21,7 @@
*/
#include "config.h"
#include "preferences.h"
#include <stdlib.h>
#include <string.h>
@ -115,7 +116,6 @@ prefs_load(void)
boolean_choice_ac = p_autocomplete_new();
p_autocomplete_add(boolean_choice_ac, strdup("on"));
p_autocomplete_add(boolean_choice_ac, strdup("off"));
}
void

View File

@ -144,6 +144,32 @@ prof_handle_error_message(const char *from, const char *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
prof_handle_login_success(const char *jid)
{

View File

@ -23,6 +23,8 @@
#ifndef PROFANITY_H
#define PROFANITY_H
#include "jabber.h"
void prof_run(const int disable_tls, char *log_level);
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_delayed_message(char *from, char *message, GTimeVal tv_stamp);
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_gone(const char * const from);
void prof_handle_room_history(const char * const room_jid,

View File

@ -49,6 +49,8 @@
#define STANZA_TYPE_GROUPCHAT "groupchat"
#define STANZA_TYPE_UNAVAILABLE "unavailable"
#define STANZA_TYPE_SUBSCRIBE "subscribe"
#define STANZA_TYPE_SUBSCRIBED "subscribed"
#define STANZA_TYPE_UNSUBSCRIBED "unsubscribed"
#define STANZA_TYPE_GET "get"
#define STANZA_TYPE_ERROR "error"

View File

@ -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,
GTimeVal *tv_stamp);
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,
const char * const message);
void win_handle_special_keys(const int * const ch);

View File

@ -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
static void
_win_notify(const char * const message, int timeout,