diff options
| author | dequis <dx@dxzone.com.ar> | 2016-04-16 14:21:33 -0300 | 
|---|---|---|
| committer | dequis <dx@dxzone.com.ar> | 2016-04-16 14:21:33 -0300 | 
| commit | 991c75fbf4c4bc0ab2ae6f8b983a092080630b14 (patch) | |
| tree | 7932b640301c13b3c0798562740e971c3eb7b80f /protocols | |
| parent | c9603a38774fb118d4aaa96e170674412ed7328a (diff) | |
| parent | 166a571321826a68626eaf10a59901253237f09e (diff) | |
Merge remote-tracking branch 'bitlbee/pr/70'
Diffstat (limited to 'protocols')
| -rw-r--r-- | protocols/twitter/twitter.c | 8 | ||||
| -rw-r--r-- | protocols/twitter/twitter.h | 2 | ||||
| -rw-r--r-- | protocols/twitter/twitter_lib.c | 189 | ||||
| -rw-r--r-- | protocols/twitter/twitter_lib.h | 9 | 
4 files changed, 204 insertions, 4 deletions
| diff --git a/protocols/twitter/twitter.c b/protocols/twitter/twitter.c index 7c96e9c3..e543f86e 100644 --- a/protocols/twitter/twitter.c +++ b/protocols/twitter/twitter.c @@ -344,6 +344,8 @@ void twitter_login_finish(struct im_connection *ic)  	           !(td->flags & TWITTER_HAVE_FRIENDS)) {  		imcb_log(ic, "Getting contact list");  		twitter_get_friends_ids(ic, -1); +		twitter_get_mutes_ids(ic, -1); +		twitter_get_noretweets_ids(ic, -1);  	} else {  		twitter_main_loop_start(ic);  	} @@ -955,6 +957,12 @@ static void twitter_handle_command(struct im_connection *ic, char *message)  	} else if (g_strcasecmp(cmd[0], "unfollow") == 0 && cmd[1]) {  		twitter_remove_buddy(ic, cmd[1], NULL);  		goto eof; +	} else if (g_strcasecmp(cmd[0], "mute") == 0 && cmd[1]) { +		twitter_mute_create_destroy(ic, cmd[1], 1); +		goto eof; +	} else if (g_strcasecmp(cmd[0], "unmute") == 0 && cmd[1]) { +		twitter_mute_create_destroy(ic, cmd[1], 0); +		goto eof;  	} else if ((g_strcasecmp(cmd[0], "report") == 0 ||  	            g_strcasecmp(cmd[0], "spam") == 0) && cmd[1]) {  		char *screen_name; diff --git a/protocols/twitter/twitter.h b/protocols/twitter/twitter.h index 5a1a4f63..86c88262 100644 --- a/protocols/twitter/twitter.h +++ b/protocols/twitter/twitter.h @@ -60,6 +60,8 @@ struct twitter_data {  	guint64 timeline_id;  	GSList *follow_ids; +	GSList *mutes_ids; +	GSList *noretweets_ids;  	GSList *filters;  	guint64 last_status_id; /* For undo */ diff --git a/protocols/twitter/twitter_lib.c b/protocols/twitter/twitter_lib.c index 80747015..82765201 100644 --- a/protocols/twitter/twitter_lib.c +++ b/protocols/twitter/twitter_lib.c @@ -239,6 +239,8 @@ static json_value *twitter_parse_response(struct im_connection *ic, struct http_  }  static void twitter_http_get_friends_ids(struct http_request *req); +static void twitter_http_get_mutes_ids(struct http_request *req); +static void twitter_http_get_noretweets_ids(struct http_request *req);  /**   * Get the friends ids. @@ -256,6 +258,34 @@ void twitter_get_friends_ids(struct im_connection *ic, gint64 next_cursor)  }  /** + * Get the muted users ids. + */ +void twitter_get_mutes_ids(struct im_connection *ic, gint64 next_cursor) +{ +	char *args[2]; + +	args[0] = "cursor"; +	args[1] = g_strdup_printf("%" G_GINT64_FORMAT, next_cursor); +	twitter_http(ic, TWITTER_MUTES_IDS_URL, twitter_http_get_mutes_ids, ic, 0, args, 2); + +	g_free(args[1]); +} + +/** + * Get the ids for users from whom we should ignore retweets. + */ +void twitter_get_noretweets_ids(struct im_connection *ic, gint64 next_cursor) +{ +	char *args[2]; + +	args[0] = "cursor"; +	args[1] = g_strdup_printf("%" G_GINT64_FORMAT, next_cursor); +	twitter_http(ic, TWITTER_NORETWEETS_IDS_URL, twitter_http_get_noretweets_ids, ic, 0, args, 2); + +	g_free(args[1]); +} + +/**   * Fill a list of ids.   */  static gboolean twitter_xt_get_friends_id_list(json_value *node, struct twitter_xml_list *txl) @@ -336,6 +366,92 @@ static void twitter_http_get_friends_ids(struct http_request *req)  	txl_free(txl);  } +/** + * Callback for getting the mutes ids. + */ +static void twitter_http_get_mutes_ids(struct http_request *req) +{ +	struct im_connection *ic = req->data; +	json_value *parsed; +	struct twitter_xml_list *txl; +	struct twitter_data *td; + +	// Check if the connection is stil active +	if (!g_slist_find(twitter_connections, ic)) { +		return; +	} + +	td = ic->proto_data; + +	// Parse the data. +	if (!(parsed = twitter_parse_response(ic, req))) { +		return; +	} + +	txl = g_new0(struct twitter_xml_list, 1); +	txl->list = td->mutes_ids; + +	/* mute ids API response is similar enough to friends response +	   to reuse this method */ +	twitter_xt_get_friends_id_list(parsed, txl); +	json_value_free(parsed); + +	td->mutes_ids = txl->list; +	if (txl->next_cursor) { +		/* Recurse while there are still more pages */ +		twitter_get_mutes_ids(ic, txl->next_cursor); +	} + +	txl->list = NULL; +	txl_free(txl); +} + +/** + * Callback for getting the no-retweets ids. + */ +static void twitter_http_get_noretweets_ids(struct http_request *req) +{ +	struct im_connection *ic = req->data; +	json_value *parsed; +	struct twitter_xml_list *txl; +	struct twitter_data *td; + +	// Check if the connection is stil active +	if (!g_slist_find(twitter_connections, ic)) { +		return; +	} + +	td = ic->proto_data; + +	// Parse the data. +	if (!(parsed = twitter_parse_response(ic, req))) { +		return; +	} + +	txl = g_new0(struct twitter_xml_list, 1); +	txl->list = td->noretweets_ids; +	 +	// Process the retweet ids +	txl->type = TXL_ID; +	if (parsed->type == json_array) { +		unsigned int i; +		for (i = 0; i < parsed->u.array.length; i++) { +			json_value *c = parsed->u.array.values[i]; +			if (c->type != json_integer) { +				continue; +			} +			txl->list = g_slist_prepend(txl->list, +			                            g_strdup_printf("%"PRIu64, c->u.integer)); +		} +	} + +	json_value_free(parsed); +	td->noretweets_ids = txl->list; + +	txl->list = NULL; +	txl_free(txl); +} +  static gboolean twitter_xt_get_users(json_value *node, struct twitter_xml_list *txl);  static void twitter_http_get_users_lookup(struct http_request *req); @@ -830,10 +946,29 @@ static void twitter_status_show(struct im_connection *ic, struct twitter_xml_sta  {  	struct twitter_data *td = ic->proto_data;  	char *last_id_str; +	char *uid_str;  	if (status->user == NULL || status->text == NULL) {  		return;  	} +	 +	/* Check this is not a tweet that should be muted */ +	uid_str = g_strdup_printf("%" PRIu64, status->user->uid); +	if (getenv("BITLBEE_DEBUG")) { +		GSList *item; +		fprintf(stderr, "Checking mutes; this uid=%s\n", uid_str); +		for (item = td->mutes_ids; item != NULL; item = item->next) { +			fprintf(stderr, "  id: %s\n", (char *)item->data); +		} +	} +	if (g_slist_find_custom(td->mutes_ids, uid_str, (GCompareFunc)strcmp)) { +		g_free(uid_str); +		return; +	} +	if (status->id != status->rt_id && g_slist_find_custom(td->noretweets_ids, uid_str, (GCompareFunc)strcmp)) { +		g_free(uid_str); +		return; +	}  	/* Grrrr. Would like to do this during parsing, but can't access  	   settings from there. */ @@ -856,6 +991,7 @@ static void twitter_status_show(struct im_connection *ic, struct twitter_xml_sta  	last_id_str = g_strdup_printf("%" G_GUINT64_FORMAT, td->timeline_id);  	set_setstr(&ic->acc->set, "_last_tweet", last_id_str);  	g_free(last_id_str); +	g_free(uid_str);  }  static gboolean twitter_stream_handle_object(struct im_connection *ic, json_value *o, gboolean from_filter); @@ -992,6 +1128,8 @@ static gboolean twitter_stream_handle_event(struct im_connection *ic, json_value  	json_value *source = json_o_get(o, "source");  	json_value *target = json_o_get(o, "target");  	const char *type = json_o_str(o, "event"); +	struct twitter_xml_user *us = NULL; +	struct twitter_xml_user *ut = NULL;  	if (!type || !source || source->type != json_object  	    || !target || target->type != json_object) { @@ -999,15 +1137,45 @@ static gboolean twitter_stream_handle_event(struct im_connection *ic, json_value  	}  	if (strcmp(type, "follow") == 0) { -		struct twitter_xml_user *us = twitter_xt_get_user(source); -		struct twitter_xml_user *ut = twitter_xt_get_user(target); +		us = twitter_xt_get_user(source); +		ut = twitter_xt_get_user(target);  		if (g_strcasecmp(us->screen_name, td->user) == 0) {  			twitter_add_buddy(ic, ut->screen_name, ut->name);  		} -		txu_free(us); -		txu_free(ut); +	} else if (strcmp(type, "mute") == 0) { +		GSList *found; +		char *uid_str; +		ut = twitter_xt_get_user(target); +		uid_str = g_strdup_printf("%" PRIu64, ut->uid); +		if (!(found = g_slist_find_custom(td->mutes_ids, uid_str, +		                                  (GCompareFunc)strcmp))) { +			td->mutes_ids = g_slist_prepend(td->mutes_ids, uid_str); +		} +		twitter_log(ic, "Muted user %s", ut->screen_name); +		if (getenv("BITLBEE_DEBUG")) { +			fprintf(stderr, "New mute: %s %"PRIu64"\n", +			        ut->screen_name, ut->uid); +		} +	} else if (strcmp(type, "unmute") == 0) { +		GSList *found; +		char *uid_str; +		ut = twitter_xt_get_user(target); +		uid_str = g_strdup_printf("%" PRIu64, ut->uid); +		if ((found = g_slist_find_custom(td->mutes_ids, uid_str, +		                                (GCompareFunc)strcmp))) { +			td->mutes_ids = g_slist_remove(td->mutes_ids, found); +		} +		g_free(uid_str); +		twitter_log(ic, "Unmuted user %s", ut->screen_name); +		if (getenv("BITLBEE_DEBUG")) { +			fprintf(stderr, "New unmute: %s %"PRIu64"\n", +			        ut->screen_name, ut->uid); +		}  	} +	txu_free(us); +	txu_free(ut); +  	return TRUE;  } @@ -1523,6 +1691,19 @@ void twitter_friendships_create_destroy(struct im_connection *ic, char *who, int  	             twitter_http_post, ic, 1, args, 2);  } +/** + * Mute or unmute a user + */ +void twitter_mute_create_destroy(struct im_connection *ic, char *who, int create) +{ +	char *args[2]; + +	args[0] = "screen_name"; +	args[1] = who; +	twitter_http(ic, create ? TWITTER_MUTES_CREATE_URL : TWITTER_MUTES_DESTROY_URL, +		     twitter_http_post, ic, 1, args, 2); +} +  void twitter_status_destroy(struct im_connection *ic, guint64 id)  {  	char *url; diff --git a/protocols/twitter/twitter_lib.h b/protocols/twitter/twitter_lib.h index 002376b1..6833d23d 100644 --- a/protocols/twitter/twitter_lib.h +++ b/protocols/twitter/twitter_lib.h @@ -62,6 +62,8 @@  /* Social graphs URLs */  #define TWITTER_FRIENDS_IDS_URL "/friends/ids.json"  #define TWITTER_FOLLOWERS_IDS_URL "/followers/ids.json" +#define TWITTER_MUTES_IDS_URL "/mutes/users/ids.json" +#define TWITTER_NORETWEETS_IDS_URL "/friendships/no_retweets/ids.json"  /* Account URLs */  #define TWITTER_ACCOUNT_RATE_LIMIT_URL "/account/rate_limit_status.json" @@ -75,6 +77,10 @@  #define TWITTER_BLOCKS_CREATE_URL "/blocks/create/"  #define TWITTER_BLOCKS_DESTROY_URL "/blocks/destroy/" +/* Mute URLs */ +#define TWITTER_MUTES_CREATE_URL "/mutes/users/create.json" +#define TWITTER_MUTES_DESTROY_URL "/mutes/users/destroy.json" +  /* Report spam */  #define TWITTER_REPORT_SPAM_URL "/users/report_spam.json" @@ -86,11 +92,14 @@ gboolean twitter_open_stream(struct im_connection *ic);  gboolean twitter_open_filter_stream(struct im_connection *ic);  gboolean twitter_get_timeline(struct im_connection *ic, gint64 next_cursor);  void twitter_get_friends_ids(struct im_connection *ic, gint64 next_cursor); +void twitter_get_mutes_ids(struct im_connection *ic, gint64 next_cursor); +void twitter_get_noretweets_ids(struct im_connection *ic, gint64 next_cursor);  void twitter_get_statuses_friends(struct im_connection *ic, gint64 next_cursor);  void twitter_post_status(struct im_connection *ic, char *msg, guint64 in_reply_to);  void twitter_direct_messages_new(struct im_connection *ic, char *who, char *message);  void twitter_friendships_create_destroy(struct im_connection *ic, char *who, int create); +void twitter_mute_create_destroy(struct im_connection *ic, char *who, int create);  void twitter_status_destroy(struct im_connection *ic, guint64 id);  void twitter_status_retweet(struct im_connection *ic, guint64 id);  void twitter_report_spam(struct im_connection *ic, char *screen_name); | 
