Changeset 537d9b9 for protocols/twitter


Ignore:
Timestamp:
2016-11-20T08:40:36Z (8 years ago)
Author:
dequis <dx@…>
Children:
3f44e43
Parents:
ba52ac5 (diff), 9f03c47 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge master up to commit '9f03c47' into parson

Location:
protocols/twitter
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • protocols/twitter/twitter.c

    rba52ac5 r537d9b9  
    345345                imcb_log(ic, "Getting contact list");
    346346                twitter_get_friends_ids(ic, -1);
     347                twitter_get_mutes_ids(ic, -1);
     348                twitter_get_noretweets_ids(ic, -1);
    347349        } else {
    348350                twitter_main_loop_start(ic);
     
    469471        g_regex_match(regex, msg, 0, &match_info);
    470472        while (g_match_info_matches(match_info)) {
    471                 gchar *s, *url;
     473                gchar *url;
    472474
    473475                url = g_match_info_fetch(match_info, 2);
    474476                url_len_diff += target_len - g_utf8_strlen(url, -1);
    475477
    476                 /* Add another character for https://t.co/... URLs */
    477                 if ((s = g_match_info_fetch(match_info, 3))) {
    478                         url_len_diff += 1;
    479                         g_free(s);
    480                 }
    481478                g_free(url);
    482479                g_match_info_next(match_info, NULL);
     
    541538        if (strcmp(acc->prpl->name, "twitter") == 0) {
    542539                def_url = TWITTER_API_URL;
    543                 def_tul = "22";
     540                def_tul = "23";
    544541                def_mentions = "true";
    545542        } else {                /* if( strcmp( acc->prpl->name, "identica" ) == 0 ) */
     
    690687                }
    691688
     689                g_slist_foreach(td->mutes_ids, (GFunc) g_free, NULL);
     690                g_slist_free(td->mutes_ids);
     691
     692                g_slist_foreach(td->noretweets_ids, (GFunc) g_free, NULL);
     693                g_slist_free(td->noretweets_ids);
     694
    692695                http_close(td->stream);
    693696                twitter_filter_remove_all(ic);
     
    948951        } else if ((g_strcasecmp(cmd[0], "favourite") == 0 ||
    949952                    g_strcasecmp(cmd[0], "favorite") == 0 ||
    950                     g_strcasecmp(cmd[0], "fav") == 0) && cmd[1]) {
     953                    g_strcasecmp(cmd[0], "fav") == 0 ||
     954                    g_strcasecmp(cmd[0], "like") == 0) && cmd[1]) {
    951955                if ((id = twitter_message_id_from_command_arg(ic, cmd[1], NULL))) {
    952956                        twitter_favourite_tweet(ic, id);
     
    960964        } else if (g_strcasecmp(cmd[0], "unfollow") == 0 && cmd[1]) {
    961965                twitter_remove_buddy(ic, cmd[1], NULL);
     966                goto eof;
     967        } else if (g_strcasecmp(cmd[0], "mute") == 0 && cmd[1]) {
     968                twitter_mute_create_destroy(ic, cmd[1], 1);
     969                goto eof;
     970        } else if (g_strcasecmp(cmd[0], "unmute") == 0 && cmd[1]) {
     971                twitter_mute_create_destroy(ic, cmd[1], 0);
    962972                goto eof;
    963973        } else if ((g_strcasecmp(cmd[0], "report") == 0 ||
     
    10821092        struct prpl *ret = g_new0(struct prpl, 1);
    10831093
    1084         ret->options = OPT_NOOTR;
     1094        ret->options = PRPL_OPT_NOOTR | PRPL_OPT_NO_PASSWORD;
    10851095        ret->name = "twitter";
    10861096        ret->login = twitter_login;
     
    11091119        ret = g_memdup(ret, sizeof(struct prpl));
    11101120        ret->name = "identica";
     1121        ret->options =  PRPL_OPT_NOOTR;
    11111122        register_protocol(ret);
    11121123}
  • protocols/twitter/twitter.h

    rba52ac5 r537d9b9  
    6161
    6262        GSList *follow_ids;
     63        GSList *mutes_ids;
     64        GSList *noretweets_ids;
    6365        GSList *filters;
    6466
  • protocols/twitter/twitter_http.c

    rba52ac5 r537d9b9  
    7979        g_string_printf(request, "%s %s%s%s%s HTTP/1.1\r\n"
    8080                        "Host: %s\r\n"
    81                         "User-Agent: BitlBee " BITLBEE_VERSION " " ARCH "/" CPU "\r\n",
     81                        "User-Agent: BitlBee " BITLBEE_VERSION "\r\n",
    8282                        is_post ? "POST" : "GET",
    8383                        base_url ? base_url->file : td->url_path,
  • protocols/twitter/twitter_lib.c

    rba52ac5 r537d9b9  
    245245
    246246static void twitter_http_get_friends_ids(struct http_request *req);
     247static void twitter_http_get_mutes_ids(struct http_request *req);
     248static void twitter_http_get_noretweets_ids(struct http_request *req);
    247249
    248250/**
     
    257259        args[1] = g_strdup_printf("%" G_GINT64_FORMAT, next_cursor);
    258260        twitter_http(ic, TWITTER_FRIENDS_IDS_URL, twitter_http_get_friends_ids, ic, 0, args, 2);
     261
     262        g_free(args[1]);
     263}
     264
     265/**
     266 * Get the muted users ids.
     267 */
     268void twitter_get_mutes_ids(struct im_connection *ic, gint64 next_cursor)
     269{
     270        char *args[2];
     271
     272        args[0] = "cursor";
     273        args[1] = g_strdup_printf("%" G_GINT64_FORMAT, next_cursor);
     274        twitter_http(ic, TWITTER_MUTES_IDS_URL, twitter_http_get_mutes_ids, ic, 0, args, 2);
     275
     276        g_free(args[1]);
     277}
     278
     279/**
     280 * Get the ids for users from whom we should ignore retweets.
     281 */
     282void twitter_get_noretweets_ids(struct im_connection *ic, gint64 next_cursor)
     283{
     284        char *args[2];
     285
     286        args[0] = "cursor";
     287        args[1] = g_strdup_printf("%" G_GINT64_FORMAT, next_cursor);
     288        twitter_http(ic, TWITTER_NORETWEETS_IDS_URL, twitter_http_get_noretweets_ids, ic, 0, args, 2);
    259289
    260290        g_free(args[1]);
     
    334364                twitter_get_users_lookup(ic);
    335365        }
     366
     367        txl->list = NULL;
     368        txl_free(txl);
     369}
     370
     371/**
     372 * Callback for getting the mutes ids.
     373 */
     374static void twitter_http_get_mutes_ids(struct http_request *req)
     375{
     376        struct im_connection *ic = req->data;
     377        JSON_Value *parsed;
     378        struct twitter_xml_list *txl;
     379        struct twitter_data *td;
     380
     381        // Check if the connection is stil active
     382        if (!g_slist_find(twitter_connections, ic)) {
     383                return;
     384        }
     385
     386        td = ic->proto_data;
     387
     388        if (req->status_code != 200) {
     389                /* Fail silently */
     390                return;
     391        }
     392
     393        // Parse the data.
     394        if (!(parsed = twitter_parse_response(ic, req))) {
     395                return;
     396        }
     397
     398        txl = g_new0(struct twitter_xml_list, 1);
     399        txl->list = td->mutes_ids;
     400
     401        /* mute ids API response is similar enough to friends response
     402           to reuse this method */
     403        twitter_xt_get_friends_id_list(parsed, txl);
     404        json_value_free(parsed);
     405
     406        td->mutes_ids = txl->list;
     407        if (txl->next_cursor) {
     408                /* Recurse while there are still more pages */
     409                twitter_get_mutes_ids(ic, txl->next_cursor);
     410        }
     411
     412        txl->list = NULL;
     413        txl_free(txl);
     414}
     415
     416/**
     417 * Callback for getting the no-retweets ids.
     418 */
     419static void twitter_http_get_noretweets_ids(struct http_request *req)
     420{
     421        struct im_connection *ic = req->data;
     422        JSON_Value *parsed;
     423        struct twitter_xml_list *txl;
     424        struct twitter_data *td;
     425
     426        // Check if the connection is stil active
     427        if (!g_slist_find(twitter_connections, ic)) {
     428                return;
     429        }
     430
     431        if (req->status_code != 200) {
     432                /* Fail silently */
     433                return;
     434        }
     435
     436        td = ic->proto_data;
     437
     438        // Parse the data.
     439        if (!(parsed = twitter_parse_response(ic, req))) {
     440                return;
     441        }
     442
     443        txl = g_new0(struct twitter_xml_list, 1);
     444        txl->list = td->noretweets_ids;
     445       
     446        // Process the retweet ids
     447        txl->type = TXL_ID;
     448        if (json_type(parsed) == JSONArray) {
     449                JSON_Array *arr = json_array(parsed);
     450                unsigned int i;
     451                for (i = 0; i < json_array_get_count(arr); i++) {
     452                        jint id = json_array_get_integer(arr, i);
     453                        txl->list = g_slist_prepend(txl->list,
     454                                                    g_strdup_printf("%lld", id));
     455                }
     456        }
     457
     458        json_value_free(parsed);
     459        td->noretweets_ids = txl->list;
    336460
    337461        txl->list = NULL;
     
    467591#endif
    468592
    469 static void expand_entities(char **text, const JSON_Object *node);
     593static void expand_entities(char **text, const JSON_Object *node, const JSON_Object *extended_node);
    470594
    471595/**
     
    479603static struct twitter_xml_status *twitter_xt_get_status(const JSON_Object *node)
    480604{
    481         struct twitter_xml_status *txs;
     605        struct twitter_xml_status *txs = {0};
    482606        const JSON_Object *rt = NULL;
     607        const JSON_Value *text_value = NULL;
     608        const JSON_Object *extended_node = NULL;
    483609
    484610        if (!node) {
     
    488614
    489615        JSON_O_FOREACH(node, k, v) {
    490                 if (strcmp("text", k) == 0 && (txs->text = g_strdup(json_string(v)))) {
    491                         // TODO: Huh strip html? In json? Not sure whether I have to..
    492                         strip_html(txs->text);
     616                if (strcmp("text", k) == 0 && json_type(v) == JSONString && text_value == NULL) {
     617                        text_value = v;
     618                } else if (strcmp("full_text", k) == 0 && json_type(v) == JSONString) {
     619                        text_value = v;
     620                } else if (strcmp("extended_tweet", k) == 0 && json_type(v) == JSONObject) {
     621                        text_value = json_object_get_value(json_object(v), "full_text");
     622                        extended_node = json_object(v);
    493623                } else if (strcmp("retweeted_status", k) == 0 && (rt = json_object(v))) {
    494624                        // Handling below.
     
    516646                struct twitter_xml_status *rtxs = twitter_xt_get_status(rt);
    517647                if (rtxs) {
    518                         g_free(txs->text);
    519648                        txs->text = g_strdup_printf("RT @%s: %s", rtxs->user->screen_name, rtxs->text);
    520649                        txs->id = rtxs->id;
    521650                        txs_free(rtxs);
    522651                }
    523         } else {
    524                 expand_entities(&txs->text, node);
     652        } else if (text_value && json_type(text_value) == JSONString) {
     653                txs->text = g_strdup(json_string(text_value));
     654                strip_html(txs->text);
     655                expand_entities(&txs->text, node, extended_node);
    525656        }
    526657
     
    564695        }
    565696
    566         expand_entities(&txs->text, node);
     697        expand_entities(&txs->text, node, NULL);
    567698
    568699        if (txs->text && txs->user && txs->id) {
     
    574705}
    575706
    576 static void expand_entities(char **text, const JSON_Object *node)
    577 {
    578         JSON_Object *entities, *quoted;
     707static void expand_entities(char **text, const JSON_Object *node, const JSON_Object *extended_node)
     708{
     709        JSON_Object *entities, *extended_entities, *quoted;
    579710        char *quote_url = NULL, *quote_text = NULL;
    580711
     
    594725        }
    595726
     727        if (extended_node) {
     728                extended_entities = json_object_get_object(extended_node, "entities");
     729                if (extended_entities) {
     730                        entities = extended_entities;
     731                }
     732        }
     733
    596734        JSON_O_FOREACH(entities, k, v) {
    597735                int i;
     
    837975        struct twitter_data *td = ic->proto_data;
    838976        char *last_id_str;
     977        char *uid_str;
    839978
    840979        if (status->user == NULL || status->text == NULL) {
     980                return;
     981        }
     982       
     983        /* Check this is not a tweet that should be muted */
     984        uid_str = g_strdup_printf("%" G_GUINT64_FORMAT, status->user->uid);
     985
     986        if (g_slist_find_custom(td->mutes_ids, uid_str, (GCompareFunc)strcmp)) {
     987                g_free(uid_str);
     988                return;
     989        }
     990        if (status->id != status->rt_id && g_slist_find_custom(td->noretweets_ids, uid_str, (GCompareFunc)strcmp)) {
     991                g_free(uid_str);
    841992                return;
    842993        }
     
    8631014        set_setstr(&ic->acc->set, "_last_tweet", last_id_str);
    8641015        g_free(last_id_str);
     1016        g_free(uid_str);
    8651017}
    8661018
     
    8801032        }
    8811033
    882         ic->flags |= OPT_PONGED;
    8831034        td = ic->proto_data;
    8841035
     
    8961047                imc_logout(ic, TRUE);
    8971048                return;
     1049        }
     1050
     1051        if (req == td->stream) {
     1052                ic->flags |= OPT_PONGED;
    8981053        }
    8991054
     
    9991154        JSON_Object *target = json_object_get_object(o, "target");
    10001155        const char *type = json_object_get_string(o, "event");
     1156        struct twitter_xml_user *us = NULL;
     1157        struct twitter_xml_user *ut = NULL;
    10011158
    10021159        if (!type || !source || !target) {
     
    10051162
    10061163        if (strcmp(type, "follow") == 0) {
    1007                 struct twitter_xml_user *us = twitter_xt_get_user(source);
    1008                 struct twitter_xml_user *ut = twitter_xt_get_user(target);
     1164                us = twitter_xt_get_user(source);
     1165                ut = twitter_xt_get_user(target);
    10091166                if (g_strcasecmp(us->screen_name, td->user) == 0) {
    10101167                        twitter_add_buddy(ic, ut->screen_name, ut->name);
    10111168                }
    1012                 txu_free(us);
    1013                 txu_free(ut);
    1014         }
     1169        } else if (strcmp(type, "mute") == 0) {
     1170                GSList *found;
     1171                char *uid_str;
     1172                ut = twitter_xt_get_user(target);
     1173                uid_str = g_strdup_printf("%" G_GUINT64_FORMAT, ut->uid);
     1174                if (!(found = g_slist_find_custom(td->mutes_ids, uid_str,
     1175                                                  (GCompareFunc)strcmp))) {
     1176                        td->mutes_ids = g_slist_prepend(td->mutes_ids, uid_str);
     1177                }
     1178                twitter_log(ic, "Muted user %s", ut->screen_name);
     1179                if (getenv("BITLBEE_DEBUG")) {
     1180                        fprintf(stderr, "New mute: %s %"G_GUINT64_FORMAT"\n",
     1181                                ut->screen_name, ut->uid);
     1182                }
     1183        } else if (strcmp(type, "unmute") == 0) {
     1184                GSList *found;
     1185                char *uid_str;
     1186                ut = twitter_xt_get_user(target);
     1187                uid_str = g_strdup_printf("%" G_GUINT64_FORMAT, ut->uid);
     1188                if ((found = g_slist_find_custom(td->mutes_ids, uid_str,
     1189                                                (GCompareFunc)strcmp))) {
     1190                        char *found_str = found->data;
     1191                        td->mutes_ids = g_slist_delete_link(td->mutes_ids, found);
     1192                        g_free(found_str);
     1193                }
     1194                g_free(uid_str);
     1195                twitter_log(ic, "Unmuted user %s", ut->screen_name);
     1196                if (getenv("BITLBEE_DEBUG")) {
     1197                        fprintf(stderr, "New unmute: %s %"G_GUINT64_FORMAT"\n",
     1198                                ut->screen_name, ut->uid);
     1199                }
     1200        }
     1201
     1202        txu_free(us);
     1203        txu_free(ut);
    10151204
    10161205        return TRUE;
     
    13091498        td->flags &= ~TWITTER_GOT_TIMELINE;
    13101499
    1311         char *args[6];
     1500        char *args[8];
    13121501        args[0] = "cursor";
    13131502        args[1] = g_strdup_printf("%" G_GINT64_FORMAT, next_cursor);
    13141503        args[2] = "include_entities";
    13151504        args[3] = "true";
     1505        args[4] = "tweet_mode";
     1506        args[5] = "extended";
    13161507        if (td->timeline_id) {
    1317                 args[4] = "since_id";
    1318                 args[5] = g_strdup_printf("%" G_GUINT64_FORMAT, td->timeline_id);
     1508                args[6] = "since_id";
     1509                args[7] = g_strdup_printf("%" G_GUINT64_FORMAT, td->timeline_id);
    13191510        }
    13201511
    13211512        if (twitter_http(ic, TWITTER_HOME_TIMELINE_URL, twitter_http_get_home_timeline, ic, 0, args,
    1322                          td->timeline_id ? 6 : 4) == NULL) {
     1513                         td->timeline_id ? 8 : 6) == NULL) {
    13231514                if (++td->http_fails >= 5) {
    13241515                        imcb_error(ic, "Could not retrieve %s: %s",
     
    13311522        g_free(args[1]);
    13321523        if (td->timeline_id) {
    1333                 g_free(args[5]);
     1524                g_free(args[7]);
    13341525        }
    13351526}
     
    13461537        td->flags &= ~TWITTER_GOT_MENTIONS;
    13471538
    1348         char *args[6];
     1539        char *args[8];
    13491540        args[0] = "cursor";
    13501541        args[1] = g_strdup_printf("%" G_GINT64_FORMAT, next_cursor);
     
    13581549                args[5] = g_strdup_printf("%d", set_getint(&ic->acc->set, "show_old_mentions"));
    13591550        }
     1551        args[6] = "tweet_mode";
     1552        args[7] = "extended";
    13601553
    13611554        if (twitter_http(ic, TWITTER_MENTIONS_URL, twitter_http_get_mentions,
    1362                          ic, 0, args, 6) == NULL) {
     1555                         ic, 0, args, 8) == NULL) {
    13631556                if (++td->http_fails >= 5) {
    13641557                        imcb_error(ic, "Could not retrieve %s: %s",
     
    15291722}
    15301723
     1724/**
     1725 * Mute or unmute a user
     1726 */
     1727void twitter_mute_create_destroy(struct im_connection *ic, char *who, int create)
     1728{
     1729        char *args[2];
     1730
     1731        args[0] = "screen_name";
     1732        args[1] = who;
     1733        twitter_http(ic, create ? TWITTER_MUTES_CREATE_URL : TWITTER_MUTES_DESTROY_URL,
     1734                     twitter_http_post, ic, 1, args, 2);
     1735}
     1736
    15311737void twitter_status_destroy(struct im_connection *ic, guint64 id)
    15321738{
  • protocols/twitter/twitter_lib.h

    rba52ac5 r537d9b9  
    6363#define TWITTER_FRIENDS_IDS_URL "/friends/ids.json"
    6464#define TWITTER_FOLLOWERS_IDS_URL "/followers/ids.json"
     65#define TWITTER_MUTES_IDS_URL "/mutes/users/ids.json"
     66#define TWITTER_NORETWEETS_IDS_URL "/friendships/no_retweets/ids.json"
    6567
    6668/* Account URLs */
     
    7678#define TWITTER_BLOCKS_DESTROY_URL "/blocks/destroy/"
    7779
     80/* Mute URLs */
     81#define TWITTER_MUTES_CREATE_URL "/mutes/users/create.json"
     82#define TWITTER_MUTES_DESTROY_URL "/mutes/users/destroy.json"
     83
    7884/* Report spam */
    7985#define TWITTER_REPORT_SPAM_URL "/users/report_spam.json"
     
    8793gboolean twitter_get_timeline(struct im_connection *ic, gint64 next_cursor);
    8894void twitter_get_friends_ids(struct im_connection *ic, gint64 next_cursor);
     95void twitter_get_mutes_ids(struct im_connection *ic, gint64 next_cursor);
     96void twitter_get_noretweets_ids(struct im_connection *ic, gint64 next_cursor);
    8997void twitter_get_statuses_friends(struct im_connection *ic, gint64 next_cursor);
    9098
     
    92100void twitter_direct_messages_new(struct im_connection *ic, char *who, char *message);
    93101void twitter_friendships_create_destroy(struct im_connection *ic, char *who, int create);
     102void twitter_mute_create_destroy(struct im_connection *ic, char *who, int create);
    94103void twitter_status_destroy(struct im_connection *ic, guint64 id);
    95104void twitter_status_retweet(struct im_connection *ic, guint64 id);
Note: See TracChangeset for help on using the changeset viewer.