diff options
Diffstat (limited to 'protocols/twitter/twitter.c')
| -rw-r--r-- | protocols/twitter/twitter.c | 173 | 
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;  } - | 
