Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • protocols/twitter/twitter.c

    r7549d00 rce402b2  
    3131
    3232GSList *twitter_connections = NULL;
     33
     34static int twitter_filter_cmp(struct twitter_filter *tf1,
     35                              struct twitter_filter *tf2)
     36{
     37        int i1 = 0;
     38        int i2 = 0;
     39        int i;
     40
     41        static const twitter_filter_type_t types[] = {
     42                /* Order of the types */
     43                TWITTER_FILTER_TYPE_FOLLOW,
     44                TWITTER_FILTER_TYPE_TRACK
     45        };
     46
     47        for (i = 0; i < G_N_ELEMENTS(types); i++) {
     48                if (types[i] == tf1->type) {
     49                        i1 = i + 1;
     50                        break;
     51                }
     52        }
     53
     54        for (i = 0; i < G_N_ELEMENTS(types); i++) {
     55                if (types[i] == tf2->type) {
     56                        i2 = i + 1;
     57                        break;
     58                }
     59        }
     60
     61        if (i1 != i2) {
     62                /* With different types, return their difference */
     63                return i1 - i2;
     64        }
     65
     66        /* With the same type, return the text comparison */
     67        return g_strcasecmp(tf1->text, tf2->text);
     68}
     69
     70static gboolean twitter_filter_update(gpointer data, gint fd,
     71                                      b_input_condition cond)
     72{
     73        struct im_connection *ic = data;
     74        struct twitter_data *td = ic->proto_data;
     75
     76        if (td->filters) {
     77                twitter_open_filter_stream(ic);
     78        } else if (td->filter_stream) {
     79                http_close(td->filter_stream);
     80                td->filter_stream = NULL;
     81        }
     82
     83        td->filter_update_id = 0;
     84        return FALSE;
     85}
     86
     87static struct twitter_filter *twitter_filter_get(struct groupchat *c,
     88                                                 twitter_filter_type_t type,
     89                                                 const char *text)
     90{
     91        struct twitter_data *td = c->ic->proto_data;
     92        struct twitter_filter *tf = NULL;
     93        struct twitter_filter tfc = {type, (char*) text};
     94        GSList *l;
     95
     96        for (l = td->filters; l; l = g_slist_next(l)) {
     97                tf = l->data;
     98
     99                if (twitter_filter_cmp(tf, &tfc) == 0)
     100                        break;
     101
     102                tf = NULL;
     103        }
     104
     105        if (!tf) {
     106                tf = g_new0(struct twitter_filter, 1);
     107                tf->type = type;
     108                tf->text = g_strdup(text);
     109                td->filters = g_slist_prepend(td->filters, tf);
     110        }
     111
     112        if (!g_slist_find(tf->groupchats, c))
     113                tf->groupchats = g_slist_prepend(tf->groupchats, c);
     114
     115        if (td->filter_update_id > 0)
     116                b_event_remove(td->filter_update_id);
     117
     118        /* Wait for other possible filter changes to avoid request spam */
     119        td->filter_update_id = b_timeout_add(TWITTER_FILTER_UPDATE_WAIT,
     120                                             twitter_filter_update, c->ic);
     121        return tf;
     122}
     123
     124static void twitter_filter_free(struct twitter_filter *tf)
     125{
     126        g_slist_free(tf->groupchats);
     127        g_free(tf->text);
     128        g_free(tf);
     129}
     130
     131static void twitter_filter_remove(struct groupchat *c)
     132{
     133        struct twitter_data *td = c->ic->proto_data;
     134        struct twitter_filter *tf;
     135        GSList *l = td->filters;
     136        GSList *p;
     137
     138        while (l != NULL) {
     139                tf = l->data;
     140                tf->groupchats = g_slist_remove(tf->groupchats, c);
     141
     142                p = l;
     143                l = g_slist_next(l);
     144
     145                if (!tf->groupchats) {
     146                        twitter_filter_free(tf);
     147                        td->filters = g_slist_delete_link(td->filters, p);
     148                }
     149        }
     150
     151        if (td->filter_update_id > 0)
     152                b_event_remove(td->filter_update_id);
     153
     154        /* Wait for other possible filter changes to avoid request spam */
     155        td->filter_update_id = b_timeout_add(TWITTER_FILTER_UPDATE_WAIT,
     156                                             twitter_filter_update, c->ic);}
     157
     158static void twitter_filter_remove_all(struct im_connection *ic)
     159{
     160        struct twitter_data *td = ic->proto_data;
     161        GSList *chats = NULL;
     162        struct twitter_filter *tf;
     163        GSList *l = td->filters;
     164        GSList *p;
     165
     166        while (l != NULL) {
     167                tf = l->data;
     168
     169                /* Build up a list of groupchats to be freed */
     170                for (p = tf->groupchats; p; p = g_slist_next(p)) {
     171                        if (!g_slist_find(chats, p->data))
     172                                chats = g_slist_prepend(chats, p->data);
     173                }
     174
     175                p = l;
     176                l = g_slist_next(l);
     177                twitter_filter_free(p->data);
     178                td->filters = g_slist_delete_link(td->filters, p);
     179        }
     180
     181        l = chats;
     182
     183        while (l != NULL) {
     184                p = l;
     185                l = g_slist_next(l);
     186
     187                /* Freed each remaining groupchat */
     188                imcb_chat_free(p->data);
     189                chats = g_slist_delete_link(chats, p);
     190        }
     191
     192        if (td->filter_stream) {
     193                http_close(td->filter_stream);
     194                td->filter_stream = NULL;
     195        }
     196}
     197
     198static GSList *twitter_filter_parse(struct groupchat *c, const char *text)
     199{
     200        char **fs = g_strsplit(text, ";", 0);
     201        GSList *ret = NULL;
     202        struct twitter_filter *tf;
     203        char **f;
     204        char *v;
     205        int i;
     206        int t;
     207
     208        static const twitter_filter_type_t types[] = {
     209                TWITTER_FILTER_TYPE_FOLLOW,
     210                TWITTER_FILTER_TYPE_TRACK
     211        };
     212
     213        static const char *typestrs[] = {
     214                "follow",
     215                "track"
     216        };
     217
     218        for (f = fs; *f; f++) {
     219                if ((v = strchr(*f, ':')) == NULL)
     220                        continue;
     221
     222                *(v++) = 0;
     223
     224                for (t = -1, i = 0; i < G_N_ELEMENTS(types); i++) {
     225                        if (g_strcasecmp(typestrs[i], *f) == 0) {
     226                                t = i;
     227                                break;
     228                        }
     229                }
     230
     231                if (t < 0 || strlen(v) == 0)
     232                        continue;
     233
     234                tf = twitter_filter_get(c, types[t], v);
     235                ret = g_slist_prepend(ret, tf);
     236        }
     237
     238        g_strfreev(fs);
     239        return ret;
     240}
     241
    33242/**
    34243 * Main loop function
     
    51260        struct twitter_data *td = ic->proto_data;
    52261
    53         char *last_tweet = set_getstr(&ic->acc->set, "last_tweet");
     262        char *last_tweet = set_getstr(&ic->acc->set, "_last_tweet");
    54263        if (last_tweet)
    55264                td->timeline_id = g_ascii_strtoull(last_tweet, NULL, 0);
     
    330539
    331540        s = set_add(&acc->set, "strip_newlines", "false", set_eval_bool, acc);
    332        
    333         s = set_add(&acc->set, "last_tweet", "0", NULL, acc);
    334         s->flags |= SET_HIDDEN;
     541
     542        s = set_add(&acc->set, "format_string", "\002[\002%i\002]\002 %c", NULL, acc);
     543        s = set_add(&acc->set, "retweet_format_string", "\002[\002%i\002]\002 RT @%a: %c", NULL, acc);
     544        s = set_add(&acc->set, "reply_format_string", "\002[\002%i->%r\002]\002 %c", NULL, acc);
     545       
     546        s = set_add(&acc->set, "_last_tweet", "0", NULL, acc);
     547        s->flags |= SET_HIDDEN | SET_NOSAVE;
    335548
    336549        if (strcmp(acc->prpl->name, "twitter") == 0) {
     
    436649
    437650        if (td) {
     651                if (td->filter_update_id > 0)
     652                        b_event_remove(td->filter_update_id);
     653
    438654                http_close(td->stream);
     655                twitter_filter_remove_all(ic);
    439656                oauth_info_free(td->oauth_info);
    440657                g_free(td->user);
     
    509726}
    510727
     728static struct groupchat *twitter_chat_join(struct im_connection *ic,
     729                                           const char *room, const char *nick,
     730                                           const char *password, set_t **sets)
     731{
     732        struct groupchat *c = imcb_chat_new(ic, room);
     733        GSList *fs = twitter_filter_parse(c, room);
     734        GString *topic = g_string_new("");
     735        struct twitter_filter *tf;
     736        GSList *l;
     737
     738        fs = g_slist_sort(fs, (GCompareFunc) twitter_filter_cmp);
     739
     740        for (l = fs; l; l = g_slist_next(l)) {
     741                tf = l->data;
     742
     743                if (topic->len > 0)
     744                        g_string_append(topic, ", ");
     745
     746                if (tf->type == TWITTER_FILTER_TYPE_FOLLOW)
     747                        g_string_append_c(topic, '@');
     748
     749                g_string_append(topic, tf->text);
     750        }
     751
     752        if (topic->len > 0)
     753                g_string_prepend(topic, "Twitter Filter: ");
     754
     755        imcb_chat_topic(c, NULL, topic->str, 0);
     756        imcb_chat_add_buddy(c, ic->acc->user);
     757
     758        if (topic->len == 0) {
     759                imcb_error(ic, "Failed to handle any filters");
     760                imcb_chat_free(c);
     761                c = NULL;
     762        }
     763
     764        g_string_free(topic, TRUE);
     765        g_slist_free(fs);
     766
     767        return c;
     768}
     769
    511770static void twitter_chat_leave(struct groupchat *c)
    512771{
    513772        struct twitter_data *td = c->ic->proto_data;
    514773
    515         if (c != td->timeline_gc)
    516                 return;         /* WTF? */
     774        if (c != td->timeline_gc) {
     775                twitter_filter_remove(c);
     776                imcb_chat_free(c);
     777                return;
     778        }
    517779
    518780        /* If the user leaves the channel: Fine. Rejoin him/her once new
     
    674936                in_reply_to = id;
    675937                allow_post = TRUE;
     938        } else if (g_strcasecmp(cmd[0], "rawreply") == 0 && cmd[1] && cmd[2]) {
     939                id = twitter_message_id_from_command_arg(ic, cmd[1], NULL);
     940                if (!id) {
     941                        twitter_log(ic, "Tweet `%s' does not exist", cmd[1]);
     942                        goto eof;
     943                }
     944                message = cmd[2];
     945                in_reply_to = id;
     946                allow_post = TRUE;
    676947        } else if (g_strcasecmp(cmd[0], "post") == 0) {
    677948                message += 5;
     
    7481019        ret->chat_msg = twitter_chat_msg;
    7491020        ret->chat_invite = twitter_chat_invite;
     1021        ret->chat_join = twitter_chat_join;
    7501022        ret->chat_leave = twitter_chat_leave;
    7511023        ret->keepalive = twitter_keepalive;
Note: See TracChangeset for help on using the changeset viewer.