Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • protocols/twitter/twitter_lib.c

    rce402b2 r85c3004  
    5151
    5252struct twitter_xml_user {
    53         guint64 uid;
    5453        char *name;
    5554        char *screen_name;
     
    6261        guint64 id, rt_id; /* Usually equal, with RTs id == *original* id */
    6362        guint64 reply_to;
    64         gboolean from_filter;
    65         struct twitter_xml_status *rt;
    6663};
    6764
     
    8986        g_free(txs->text);
    9087        txu_free(txs->user);
    91         txs_free(txs->rt);
    9288        g_free(txs);
    9389}
     
    396392{
    397393        struct twitter_xml_user *txu;
    398         json_value *jv;
    399394       
    400395        txu = g_new0(struct twitter_xml_user, 1);
    401396        txu->name = g_strdup(json_o_str(node, "name"));
    402397        txu->screen_name = g_strdup(json_o_str(node, "screen_name"));
    403        
    404         jv = json_o_get(node, "id");
    405         txu->uid = jv->u.integer;
    406398       
    407399        return txu;
     
    491483                if (rtxs) {
    492484                        g_free(txs->text);
    493                         txs->text = g_strdup(rtxs->text);
     485                        txs->text = g_strdup_printf("RT @%s: %s", rtxs->user->screen_name, rtxs->text);
    494486                        txs->id = rtxs->id;
    495                         txs->rt = rtxs;
     487                        txs_free(rtxs);
    496488                }
    497489        } else if (entities) {
     
    611603}
    612604
    613 /**
    614  * Function to properly format a tweet as per the users configuration.
    615  */
    616 static char *twitter_msg_get_text(struct im_connection *ic, int log_id, int reply_to,
    617                                 struct twitter_xml_status *txs, const char *prefix) {
    618         gchar * format = set_getstr(&ic->acc->set, "format_string");
    619         GString * text = g_string_new(NULL);
    620 
    621         gchar *c;
    622         if (reply_to != -1)
    623                 format = set_getstr(&ic->acc->set, "reply_format_string");
    624         if (txs->rt)
    625                 format = set_getstr(&ic->acc->set, "retweet_format_string");
    626 
    627         for (c = format; *c ; c++) {
    628                 if (!(*c == '%' && *(c+1))) {
    629                         text = g_string_append_c(text, *c);
    630                         continue;
    631                 }
    632                 c++; // Move past the %
    633                 switch (*c) {
    634                         case 'i':
    635                                 g_string_append_printf(text, "%02x", log_id);
    636                                 break;
    637                         case 'r':
    638                                 if (reply_to != -1) // In case someone does put %r in the wrong format_string
    639                                 g_string_append_printf(text, "%02x", reply_to);
    640                                 break;
    641                         case 'a':
    642                                 if (txs->rt) // In case someone does put %a in the wrong format_string
    643                                         text = g_string_append(text, txs->rt->user->screen_name);
    644                                 break;
    645                         case 'c':
    646                                 text = g_string_append(text, txs->text);
    647                                 break;
    648                         default:
    649                                 text = g_string_append_c(text, *c);
    650                 }
    651         }
    652         text = g_string_prepend(text, prefix);
    653         return g_string_free(text, FALSE);
    654 }
    655 
    656605/* Will log messages either way. Need to keep track of IDs for stream deduping.
    657606   Plus, show_ids is on by default and I don't see why anyone would disable it. */
     
    692641                td->log[td->log_id].id = txs->rt_id;
    693642       
    694         return twitter_msg_get_text(ic, td->log_id, reply_to, txs, prefix);
    695 }
    696 
    697 /**
    698  * Function that is called to see the filter statuses in groupchat windows.
    699  */
    700 static void twitter_status_show_filter(struct im_connection *ic, struct twitter_xml_status *status)
    701 {
    702         struct twitter_data *td = ic->proto_data;
    703         char *msg = twitter_msg_add_id(ic, status, "");
    704         struct twitter_filter *tf;
    705         GSList *f;
    706         GSList *l;
    707 
    708         for (f = td->filters; f; f = g_slist_next(f)) {
    709                 tf = f->data;
    710 
    711                 switch (tf->type) {
    712                 case TWITTER_FILTER_TYPE_FOLLOW:
    713                         if (status->user->uid != tf->uid)
    714                                 continue;
    715                         break;
    716 
    717                 case TWITTER_FILTER_TYPE_TRACK:
    718                         if (strcasestr(status->text, tf->text) == NULL)
    719                                 continue;
    720                         break;
    721 
    722                 default:
    723                         continue;
    724                 }
    725 
    726                 for (l = tf->groupchats; l; l = g_slist_next(l)) {
    727                         imcb_chat_msg(l->data, status->user->screen_name,
    728                                       msg ? msg : status->text, 0, 0);
    729                 }
    730         }
    731 
    732         g_free(msg);
     643        if (set_getbool(&ic->acc->set, "show_ids")) {
     644                if (reply_to != -1)
     645                        return g_strdup_printf("\002[\002%02x->%02x\002]\002 %s%s",
     646                                               td->log_id, reply_to, prefix, txs->text);
     647                else
     648                        return g_strdup_printf("\002[\002%02x\002]\002 %s%s",
     649                                               td->log_id, prefix, txs->text);
     650        } else {
     651                if (*prefix)
     652                        return g_strconcat(prefix, txs->text, NULL);
     653                else
     654                        return NULL;
     655        }
    733656}
    734657
     
    808731                strip_newlines(status->text);
    809732       
    810         if (status->from_filter)
    811                 twitter_status_show_filter(ic, status);
    812         else if (td->flags & TWITTER_MODE_CHAT)
     733        if (td->flags & TWITTER_MODE_CHAT)
    813734                twitter_status_show_chat(ic, status);
    814735        else
     
    824745}
    825746
    826 static gboolean twitter_stream_handle_object(struct im_connection *ic, json_value *o, gboolean from_filter);
     747static gboolean twitter_stream_handle_object(struct im_connection *ic, json_value *o);
    827748
    828749static void twitter_http_stream(struct http_request *req)
     
    833754        int len = 0;
    834755        char c, *nl;
    835         gboolean from_filter;
    836756       
    837757        if (!g_slist_find(twitter_connections, ic))
     
    842762       
    843763        if ((req->flags & HTTPC_EOF) || !req->reply_body) {
    844                 if (req == td->stream)
    845                         td->stream = NULL;
    846                 else if (req == td->filter_stream)
    847                         td->filter_stream = NULL;
    848 
     764                td->stream = NULL;
    849765                imcb_error(ic, "Stream closed (%s)", req->status_string);
    850766                imc_logout(ic, TRUE);
     
    863779               
    864780                if ((parsed = json_parse(req->reply_body, req->body_size))) {
    865                         from_filter = (req == td->filter_stream);
    866                         twitter_stream_handle_object(ic, parsed, from_filter);
     781                        twitter_stream_handle_object(ic, parsed);
    867782                }
    868783                json_value_free(parsed);
     
    880795static gboolean twitter_stream_handle_status(struct im_connection *ic, struct twitter_xml_status *txs);
    881796
    882 static gboolean twitter_stream_handle_object(struct im_connection *ic, json_value *o, gboolean from_filter)
     797static gboolean twitter_stream_handle_object(struct im_connection *ic, json_value *o)
    883798{
    884799        struct twitter_data *td = ic->proto_data;
     
    887802       
    888803        if ((txs = twitter_xt_get_status(o))) {
    889                 txs->from_filter = from_filter;
    890804                gboolean ret = twitter_stream_handle_status(ic, txs);
    891805                txs_free(txs);
     
    985899}
    986900
    987 static gboolean twitter_filter_stream(struct im_connection *ic)
    988 {
    989         struct twitter_data *td = ic->proto_data;
    990         char *args[4] = {"follow", NULL, "track", NULL};
    991         GString *followstr = g_string_new("");
    992         GString *trackstr = g_string_new("");
    993         gboolean ret = FALSE;
    994         struct twitter_filter *tf;
    995         GSList *l;
    996 
    997         for (l = td->filters; l; l = g_slist_next(l)) {
    998                 tf = l->data;
    999 
    1000                 switch (tf->type) {
    1001                 case TWITTER_FILTER_TYPE_FOLLOW:
    1002                         if (followstr->len > 0)
    1003                                 g_string_append_c(followstr, ',');
    1004 
    1005                         g_string_append_printf(followstr, "%" G_GUINT64_FORMAT,
    1006                                                tf->uid);
    1007                         break;
    1008 
    1009                 case TWITTER_FILTER_TYPE_TRACK:
    1010                         if (trackstr->len > 0)
    1011                                 g_string_append_c(trackstr, ',');
    1012 
    1013                         g_string_append(trackstr, tf->text);
    1014                         break;
    1015 
    1016                 default:
    1017                         continue;
    1018                 }
    1019         }
    1020 
    1021         args[1] = followstr->str;
    1022         args[3] = trackstr->str;
    1023 
    1024         if (td->filter_stream)
    1025                 http_close(td->filter_stream);
    1026 
    1027         if ((td->filter_stream = twitter_http(ic, TWITTER_FILTER_STREAM_URL,
    1028                                               twitter_http_stream, ic, 0,
    1029                                               args, 4))) {
    1030                 /* This flag must be enabled or we'll get no data until EOF
    1031                    (which err, kind of, defeats the purpose of a streaming API). */
    1032                 td->filter_stream->flags |= HTTPC_STREAMING;
    1033                 ret = TRUE;
    1034         }
    1035 
    1036         g_string_free(followstr, TRUE);
    1037         g_string_free(trackstr, TRUE);
    1038 
    1039         return ret;
    1040 }
    1041 
    1042 static void twitter_filter_users_post(struct http_request *req)
    1043 {
    1044         struct im_connection *ic = req->data;
    1045         struct twitter_data *td;
    1046         struct twitter_filter *tf;
    1047         GList *users = NULL;
    1048         json_value *parsed;
    1049         json_value *id;
    1050         const char *name;
    1051         GString *fstr;
    1052         GSList *l;
    1053         GList *u;
    1054         int i;
    1055 
    1056         // Check if the connection is still active.
    1057         if (!g_slist_find(twitter_connections, ic))
    1058                 return;
    1059 
    1060         td = ic->proto_data;
    1061 
    1062         if (!(parsed = twitter_parse_response(ic, req)))
    1063                 return;
    1064 
    1065         for (l = td->filters; l; l = g_slist_next(l)) {
    1066                 tf = l->data;
    1067 
    1068                 if (tf->type == TWITTER_FILTER_TYPE_FOLLOW)
    1069                         users = g_list_prepend(users, tf);
    1070         }
    1071 
    1072         if (parsed->type != json_array)
    1073                 goto finish;
    1074 
    1075         for (i = 0; i < parsed->u.array.length; i++) {
    1076                 id = json_o_get(parsed->u.array.values[i], "id");
    1077                 name = json_o_str(parsed->u.array.values[i], "screen_name");
    1078 
    1079                 if (!name || !id || id->type != json_integer)
    1080                         continue;
    1081 
    1082                 for (u = users; u; u = g_list_next(u)) {
    1083                         tf = u->data;
    1084 
    1085                         if (g_strcasecmp(tf->text, name) == 0) {
    1086                                 tf->uid = id->u.integer;
    1087                                 users = g_list_delete_link(users, u);
    1088                                 break;
    1089                         }
    1090                 }
    1091         }
    1092 
    1093 finish:
    1094         json_value_free(parsed);
    1095         twitter_filter_stream(ic);
    1096 
    1097         if (!users)
    1098                 return;
    1099 
    1100         fstr = g_string_new("");
    1101 
    1102         for (u = users; u; u = g_list_next(u)) {
    1103                 if (fstr->len > 0)
    1104                         g_string_append(fstr, ", ");
    1105 
    1106                 g_string_append(fstr, tf->text);
    1107         }
    1108 
    1109         imcb_error(ic, "Failed UID acquisitions: %s", fstr->str);
    1110 
    1111         g_string_free(fstr, TRUE);
    1112         g_list_free(users);
    1113 }
    1114 
    1115 gboolean twitter_open_filter_stream(struct im_connection *ic)
    1116 {
    1117         struct twitter_data *td = ic->proto_data;
    1118         char *args[2] = {"screen_name", NULL};
    1119         GString *ustr = g_string_new("");
    1120         struct twitter_filter *tf;
    1121         struct http_request *req;
    1122         GSList *l;
    1123 
    1124         for (l = td->filters; l; l = g_slist_next(l)) {
    1125                 tf = l->data;
    1126 
    1127                 if (tf->type != TWITTER_FILTER_TYPE_FOLLOW || tf->uid != 0)
    1128                         continue;
    1129 
    1130                 if (ustr->len > 0)
    1131                         g_string_append_c(ustr, ',');
    1132 
    1133                 g_string_append(ustr, tf->text);
    1134         }
    1135 
    1136         if (ustr->len == 0) {
    1137                 g_string_free(ustr, TRUE);
    1138                 return twitter_filter_stream(ic);
    1139         }
    1140 
    1141         args[1] = ustr->str;
    1142         req = twitter_http(ic, TWITTER_USERS_LOOKUP_URL,
    1143                            twitter_filter_users_post,
    1144                            ic, 0, args, 2);
    1145 
    1146         g_string_free(ustr, TRUE);
    1147         return req != NULL;
    1148 }
    1149 
    1150901static void twitter_get_home_timeline(struct im_connection *ic, gint64 next_cursor);
    1151902static void twitter_get_mentions(struct im_connection *ic, gint64 next_cursor);
Note: See TracChangeset for help on using the changeset viewer.