aboutsummaryrefslogtreecommitdiffstats
path: root/protocols/twitter/twitter.c
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/twitter/twitter.c')
-rw-r--r--protocols/twitter/twitter.c173
1 files changed, 161 insertions, 12 deletions
diff --git a/protocols/twitter/twitter.c b/protocols/twitter/twitter.c
index fca619c3..16b069ee 100644
--- a/protocols/twitter/twitter.c
+++ b/protocols/twitter/twitter.c
@@ -118,7 +118,7 @@ static gboolean twitter_oauth_callback( struct oauth_info *info )
return FALSE;
}
- sprintf( name, "twitter_%s", ic->acc->user );
+ sprintf( name, "%s_%s", td->prefix, ic->acc->user );
msg = g_strdup_printf( "To finish OAuth authentication, please visit "
"%s and respond with the resulting PIN code.",
info->auth_url );
@@ -171,16 +171,33 @@ static gboolean twitter_length_check( struct im_connection *ic, gchar *msg )
static void twitter_init( account_t *acc )
{
set_t *s;
+ char *def_url;
+ char *def_oauth;
- s = set_add( &acc->set, "base_url", TWITTER_API_URL, NULL, acc );
+ if( strcmp( acc->prpl->name, "twitter" ) == 0 )
+ {
+ def_url = TWITTER_API_URL;
+ def_oauth = "true";
+ }
+ else /* if( strcmp( acc->prpl->name, "identica" ) == 0 ) */
+ {
+ def_url = IDENTICA_API_URL;
+ def_oauth = "false";
+ }
+
+ s = set_add( &acc->set, "auto_reply_timeout", "10800", set_eval_int, acc );
+
+ s = set_add( &acc->set, "base_url", def_url, NULL, acc );
s->flags |= ACC_SET_OFFLINE_ONLY;
+ s = set_add( &acc->set, "commands", "true", set_eval_bool, acc );
+
s = set_add( &acc->set, "message_length", "140", set_eval_int, acc );
s = set_add( &acc->set, "mode", "one", set_eval_mode, acc );
s->flags |= ACC_SET_OFFLINE_ONLY;
- s = set_add( &acc->set, "oauth", "true", set_eval_bool, acc );
+ s = set_add( &acc->set, "oauth", def_oauth, set_eval_bool, acc );
}
/**
@@ -213,12 +230,16 @@ static void twitter_login( account_t *acc )
td->url_path = g_strdup( url.file );
else
td->url_path = g_strdup( "" );
+ if( g_str_has_suffix( url.host, ".com" ) )
+ td->prefix = g_strndup( url.host, strlen( url.host ) - 4 );
+ else
+ td->prefix = g_strdup( url.host );
td->user = acc->user;
if( strstr( acc->pass, "oauth_token=" ) )
td->oauth_info = oauth_from_string( acc->pass, &twitter_oauth );
- sprintf( name, "twitter_%s", acc->user );
+ sprintf( name, "%s_%s", td->prefix, acc->user );
imcb_add_buddy( ic, name, NULL );
imcb_buddy_status( ic, name, OPT_LOGGED_IN, NULL, NULL );
@@ -235,7 +256,7 @@ static void twitter_logout( struct im_connection *ic )
struct twitter_data *td = ic->proto_data;
// Set the status to logged out.
- ic->flags = 0;
+ ic->flags &= ~ OPT_LOGGED_IN;
// Remove the main_loop function from the function queue.
b_event_remove(td->main_loop_id);
@@ -246,6 +267,7 @@ static void twitter_logout( struct im_connection *ic )
if( td )
{
oauth_info_free( td->oauth_info );
+ g_free( td->prefix );
g_free( td->url_host );
g_free( td->url_path );
g_free( td->pass );
@@ -255,15 +277,18 @@ static void twitter_logout( struct im_connection *ic )
twitter_connections = g_slist_remove( twitter_connections, ic );
}
+static void twitter_handle_command( struct im_connection *ic, char *message );
+
/**
*
*/
static int twitter_buddy_msg( struct im_connection *ic, char *who, char *message, int away )
{
struct twitter_data *td = ic->proto_data;
+ int plen = strlen( td->prefix );
- if (g_strncasecmp(who, "twitter_", 8) == 0 &&
- g_strcasecmp(who + 8, ic->acc->user) == 0)
+ if (g_strncasecmp(who, td->prefix, plen) == 0 && who[plen] == '_' &&
+ g_strcasecmp(who + plen + 1, ic->acc->user) == 0)
{
if( set_getbool( &ic->acc->set, "oauth" ) &&
td->oauth_info && td->oauth_info->token == NULL )
@@ -282,8 +307,8 @@ static int twitter_buddy_msg( struct im_connection *ic, char *who, char *message
return FALSE;
}
}
- else if( twitter_length_check(ic, message) )
- twitter_post_status(ic, message);
+ else
+ twitter_handle_command(ic, message);
}
else
{
@@ -315,8 +340,8 @@ static void twitter_remove_buddy( struct im_connection *ic, char *who, char *gro
static void twitter_chat_msg( struct groupchat *c, char *message, int flags )
{
- if( c && message && twitter_length_check(c->ic, message))
- twitter_post_status(c->ic, message);
+ if( c && message )
+ twitter_handle_command( c->ic, message );
}
static void twitter_chat_invite( struct groupchat *c, char *who, char *message )
@@ -371,6 +396,124 @@ static int twitter_send_typing( struct im_connection *ic, char *who, int typing
// return value;
//}
+static void twitter_buddy_data_add( struct bee_user *bu )
+{
+ bu->data = g_new0( struct twitter_user_data, 1 );
+}
+
+static void twitter_buddy_data_free( struct bee_user *bu )
+{
+ g_free( bu->data );
+}
+
+static void twitter_handle_command( struct im_connection *ic, char *message )
+{
+ struct twitter_data *td = ic->proto_data;
+ char *cmds, **cmd;
+
+ cmds = g_strdup( message );
+ cmd = split_command_parts( cmds );
+
+ if( cmd[0] == NULL )
+ {
+ g_free( cmds );
+ return;
+ }
+ else if( !set_getbool( &ic->acc->set, "commands" ) )
+ {
+ /* Not supporting commands. */
+ }
+ else if( g_strcasecmp( cmd[0], "undo" ) == 0 )
+ {
+ guint64 id;
+
+ if( cmd[1] )
+ id = g_ascii_strtoull( cmd[1], NULL, 10 );
+ else
+ id = td->last_status_id;
+
+ /* TODO: User feedback. */
+ if( id )
+ twitter_status_destroy( ic, id );
+
+ g_free( cmds );
+ return;
+ }
+ else if( g_strcasecmp( cmd[0], "follow" ) == 0 && cmd[1] )
+ {
+ twitter_add_buddy( ic, cmd[1], NULL );
+ g_free( cmds );
+ return;
+ }
+ else if( g_strcasecmp( cmd[0], "unfollow" ) == 0 && cmd[1] )
+ {
+ twitter_remove_buddy( ic, cmd[1], NULL );
+ g_free( cmds );
+ return;
+ }
+ else if( g_strcasecmp( cmd[0], "rt" ) == 0 && cmd[1] )
+ {
+ struct twitter_user_data *tud;
+ bee_user_t *bu;
+ guint64 id;
+
+ if( ( bu = bee_user_by_handle( ic->bee, ic, cmd[1] ) ) &&
+ ( tud = bu->data ) && tud->last_id )
+ id = tud->last_id;
+ else
+ id = g_ascii_strtoull( cmd[1], NULL, 10 );
+
+ td->last_status_id = 0;
+ if( id )
+ twitter_status_retweet( ic, id );
+
+ g_free( cmds );
+ return;
+ }
+ else if( g_strcasecmp( cmd[0], "post" ) == 0 )
+ {
+ message += 5;
+ }
+
+ {
+ guint64 in_reply_to = 0;
+ char *s, *new = NULL;
+ bee_user_t *bu;
+
+ if( !twitter_length_check( ic, message ) )
+ {
+ g_free( cmds );
+ return;
+ }
+
+ s = cmd[0] + strlen( cmd[0] ) - 1;
+ if( s > cmd[0] && ( *s == ':' || *s == ',' ) )
+ {
+ *s = '\0';
+
+ if( ( bu = bee_user_by_handle( ic->bee, ic, cmd[0] ) ) )
+ {
+ struct twitter_user_data *tud = bu->data;
+
+ new = g_strdup_printf( "@%s %s", bu->handle,
+ message + ( s - cmd[0] ) + 2 );
+ message = new;
+
+ if( time( NULL ) < tud->last_time +
+ set_getint( &ic->acc->set, "auto_reply_timeout" ) )
+ in_reply_to = tud->last_id;
+ }
+ }
+
+ /* If the user runs undo between this request and its response
+ this would delete the second-last Tweet. Prevent that. */
+ td->last_status_id = 0;
+ twitter_post_status( ic, message, in_reply_to );
+ g_free( new );
+ }
+ g_free( cmds );
+}
+
void twitter_initmodule()
{
struct prpl *ret = g_new0(struct prpl, 1);
@@ -395,11 +538,17 @@ void twitter_initmodule()
ret->add_deny = twitter_add_deny;
ret->rem_deny = twitter_rem_deny;
ret->send_typing = twitter_send_typing;
+ ret->buddy_data_add = twitter_buddy_data_add;
+ ret->buddy_data_free = twitter_buddy_data_free;
ret->handle_cmp = g_strcasecmp;
+
+ register_protocol(ret);
+ /* And an identi.ca variant: */
+ ret = g_memdup(ret, sizeof(struct prpl));
+ ret->name = "identica";
register_protocol(ret);
// Initialise the twitter_connections GSList.
twitter_connections = NULL;
}
-