Changeset f924563 for protocols/twitter


Ignore:
Timestamp:
2010-05-03T00:52:08Z (14 years ago)
Author:
Wilmer van der Gaast <wilmer@…>
Branches:
master
Children:
1a3ba05
Parents:
6a9d068 (diff), 6824fb3 (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:

Mainline merge.

Location:
protocols/twitter
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • protocols/twitter/twitter.c

    r6a9d068 rf924563  
    2323
    2424#include "nogaim.h"
     25#include "oauth.h"
    2526#include "twitter.h"
    2627#include "twitter_http.h"
    2728#include "twitter_lib.h"
    2829
    29 
    3030/**
    3131 * Main loop function
     
    4141        // If the user uses multiple private message windows we need to get the
    4242        // users buddies.
    43         if (!set_getbool( &ic->acc->set, "use_groupchat" ))
     43        if (g_strcasecmp(set_getstr(&ic->acc->set, "mode"), "many") == 0)
    4444                twitter_get_statuses_friends(ic, -1);
    4545
     
    5151}
    5252
    53 
    54 static void twitter_init( account_t *acc )
    55 {
    56         set_t *s;
    57         s = set_add( &acc->set, "use_groupchat", "false", set_eval_bool, acc );
    58         s->flags |= ACC_SET_OFFLINE_ONLY;
    59 }
    60 
    61 /**
    62  * Login method. Since the twitter API works with seperate HTTP request we
    63  * only save the user and pass to the twitter_data object.
    64  */
    65 static void twitter_login( account_t *acc )
    66 {
    67         struct im_connection *ic = imcb_new( acc );
    68         struct twitter_data *td = g_new0( struct twitter_data, 1 );
    69 
    70         twitter_connections = g_slist_append( twitter_connections, ic );
    71 
    72         td->user = acc->user;
    73         td->pass = acc->pass;
    74         td->home_timeline_id = 0;
    75 
    76         ic->proto_data = td;
    77 
     53static void twitter_main_loop_start( struct im_connection *ic )
     54{
     55        struct twitter_data *td = ic->proto_data;
     56       
    7857        imcb_log( ic, "Connecting to Twitter" );
    7958
     
    8665}
    8766
     67
     68static const struct oauth_service twitter_oauth =
     69{
     70        "http://api.twitter.com/oauth/request_token",
     71        "http://api.twitter.com/oauth/access_token",
     72        "http://api.twitter.com/oauth/authorize",
     73        .consumer_key = "xsDNKJuNZYkZyMcu914uEA",
     74        .consumer_secret = "FCxqcr0pXKzsF9ajmP57S3VQ8V6Drk4o2QYtqMcOszo",
     75};
     76
     77static gboolean twitter_oauth_callback( struct oauth_info *info );
     78
     79static void twitter_oauth_start( struct im_connection *ic )
     80{
     81        struct twitter_data *td = ic->proto_data;
     82       
     83        imcb_log( ic, "Requesting OAuth request token" );
     84
     85        td->oauth_info = oauth_request_token( &twitter_oauth, twitter_oauth_callback, ic );
     86}
     87
     88static gboolean twitter_oauth_callback( struct oauth_info *info )
     89{
     90        struct im_connection *ic = info->data;
     91        struct twitter_data *td;
     92       
     93        if( !g_slist_find( twitter_connections, ic ) )
     94                return FALSE;
     95       
     96        td = ic->proto_data;
     97        if( info->stage == OAUTH_REQUEST_TOKEN )
     98        {
     99                char name[strlen(ic->acc->user)+9], *msg;
     100               
     101                if( info->request_token == NULL )
     102                {
     103                        imcb_error( ic, "OAuth error: %s", info->http->status_string );
     104                        imc_logout( ic, TRUE );
     105                        return FALSE;
     106                }
     107               
     108                sprintf( name, "twitter_%s", ic->acc->user );
     109                msg = g_strdup_printf( "To finish OAuth authentication, please visit "
     110                                       "%s and respond with the resulting PIN code.",
     111                                       info->auth_url );
     112                imcb_buddy_msg( ic, name, msg, 0, 0 );
     113                g_free( msg );
     114        }
     115        else if( info->stage == OAUTH_ACCESS_TOKEN )
     116        {
     117                if( info->token == NULL || info->token_secret == NULL )
     118                {
     119                        imcb_error( ic, "OAuth error: %s", info->http->status_string );
     120                        imc_logout( ic, TRUE );
     121                        return FALSE;
     122                }
     123               
     124                /* IM mods didn't do this so far and it's ugly but I should
     125                   be able to get away with it... */
     126                g_free( ic->acc->pass );
     127                ic->acc->pass = oauth_to_string( info );
     128               
     129                twitter_main_loop_start( ic );
     130        }
     131       
     132        return TRUE;
     133}
     134
     135
     136static char *set_eval_mode( set_t *set, char *value )
     137{
     138        if( g_strcasecmp( value, "one" ) == 0 ||
     139            g_strcasecmp( value, "many" ) == 0 ||
     140            g_strcasecmp( value, "chat" ) == 0 )
     141                return value;
     142        else
     143                return NULL;
     144}
     145
     146static void twitter_init( account_t *acc )
     147{
     148        set_t *s;
     149       
     150        s = set_add( &acc->set, "mode", "one", set_eval_mode, acc );
     151        s->flags |= ACC_SET_OFFLINE_ONLY;
     152       
     153        s = set_add( &acc->set, "oauth", "true", set_eval_bool, acc );
     154}
     155
     156/**
     157 * Login method. Since the twitter API works with seperate HTTP request we
     158 * only save the user and pass to the twitter_data object.
     159 */
     160static void twitter_login( account_t *acc )
     161{
     162        struct im_connection *ic = imcb_new( acc );
     163        struct twitter_data *td = g_new0( struct twitter_data, 1 );
     164        char name[strlen(acc->user)+9];
     165
     166        twitter_connections = g_slist_append( twitter_connections, ic );
     167        ic->proto_data = td;
     168        ic->flags |= OPT_DOES_HTML;
     169       
     170        td->user = acc->user;
     171        if( !set_getbool( &acc->set, "oauth" ) )
     172                td->pass = g_strdup( acc->pass );
     173        else if( strstr( acc->pass, "oauth_token=" ) )
     174                td->oauth_info = oauth_from_string( acc->pass, &twitter_oauth );
     175        td->home_timeline_id = 0;
     176       
     177        sprintf( name, "twitter_%s", acc->user );
     178        imcb_add_buddy( ic, name, NULL );
     179        imcb_buddy_status( ic, name, OPT_LOGGED_IN, NULL, NULL );
     180       
     181        if( td->pass || td->oauth_info )
     182                twitter_main_loop_start( ic );
     183        else
     184                twitter_oauth_start( ic );
     185}
     186
    88187/**
    89188 * Logout method. Just free the twitter_data.
     
    104203        if( td )
    105204        {
     205                oauth_info_free( td->oauth_info );
     206                g_free( td->pass );
    106207                g_free( td );
    107208        }
     
    115216static int twitter_buddy_msg( struct im_connection *ic, char *who, char *message, int away )
    116217{
    117         // Let's just update the status.
    118 //      if ( g_strcasecmp(who, ic->acc->user) == 0 )
    119                 twitter_post_status(ic, message);
    120 //      else
    121 //              twitter_direct_messages_new(ic, who, message);
     218        struct twitter_data *td = ic->proto_data;
     219       
     220        if (g_strncasecmp(who, "twitter_", 8) == 0 &&
     221            g_strcasecmp(who + 8, ic->acc->user) == 0)
     222        {
     223                if( set_getbool( &ic->acc->set, "oauth" ) &&
     224                    td->oauth_info && td->oauth_info->token == NULL )
     225                {
     226                        if( !oauth_access_token( message, td->oauth_info ) )
     227                        {
     228                                imcb_error( ic, "OAuth error: %s", "Failed to send access token request" );
     229                                imc_logout( ic, TRUE );
     230                                return FALSE;
     231                        }
     232                }
     233                else
     234                        twitter_post_status(ic, message);
     235        }
     236        else
     237        {
     238                twitter_direct_messages_new(ic, who, message);
     239        }
    122240        return( 0 );
    123241}
  • protocols/twitter/twitter.h

    r6a9d068 rf924563  
    3737        char* user;
    3838        char* pass;
     39        struct oauth_info *oauth_info;
    3940        guint64 home_timeline_id;
    4041        gint main_loop_id;
  • protocols/twitter/twitter_http.c

    r6a9d068 rf924563  
    2929****************************************************************************/
    3030
    31 #include "twitter_http.h"
    3231#include "twitter.h"
    3332#include "bitlbee.h"
     
    3534#include "misc.h"
    3635#include "base64.h"
     36#include "oauth.h"
    3737#include <ctype.h>
    3838#include <errno.h>
     39
     40#include "twitter_http.h"
    3941
    4042
     
    4547 * This is actually pretty generic function... Perhaps it should move to the lib/http_client.c
    4648 */
    47 void *twitter_http(char *url_string, http_input_function func, gpointer data, int is_post, char* user, char* pass, char** arguments, int arguments_len)
     49void *twitter_http(char *url_string, http_input_function func, gpointer data, int is_post, char* user, char* pass, struct oauth_info* oi, char** arguments, int arguments_len)
    4850{
    4951        url_t *url = g_new0( url_t, 1 );
     
    110112
    111113        // If a pass and user are given we append them to the request.
    112         if (userpass_base64)
     114        if (oi)
     115        {
     116                char *full_header;
     117               
     118                full_header = oauth_http_header(oi, is_post ? "POST" : "GET",
     119                                                url_string, url_arguments);
     120               
     121                tmp = g_strdup_printf("%sAuthorization: %s\r\n", request, full_header);
     122                g_free(request);
     123                g_free(full_header);
     124                request = tmp;
     125        }
     126        else if (userpass_base64)
    113127        {
    114128                tmp = g_strdup_printf("%sAuthorization: Basic %s\r\n", request, userpass_base64);
  • protocols/twitter/twitter_http.h

    r6a9d068 rf924563  
    2828#include "http_client.h"
    2929
     30struct oauth_info;
     31
    3032void *twitter_http(char *url_string, http_input_function func, gpointer data, int is_post,
    31                                         char* user, char* pass, char** arguments, int arguments_len);
     33                   char* user, char* pass, struct oauth_info *oi, char** arguments, int arguments_len);
    3234
    3335#endif //_TWITTER_HTTP_H
  • protocols/twitter/twitter_lib.c

    r6a9d068 rf924563  
    105105        if (!bee_user_by_handle( ic->bee, ic, name ))
    106106        {
     107                char *mode = set_getstr(&ic->acc->set, "mode");
     108               
    107109                // The buddy is not in the list, add the buddy and set the status to logged in.
    108110                imcb_add_buddy( ic, name, NULL );
    109111                imcb_rename_buddy( ic, name, fullname );
    110                 if (set_getbool( &ic->acc->set, "use_groupchat" ))
     112                if (g_strcasecmp(mode, "chat") == 0)
    111113                        imcb_chat_add_buddy( td->home_timeline_gc, name );
    112                 else
     114                else if (g_strcasecmp(mode, "many") == 0)
    113115                        imcb_buddy_status( ic, name, OPT_LOGGED_IN, NULL, NULL );
    114116        }
     
    128130        args[0] = "cursor";
    129131        args[1] = g_strdup_printf ("%d", next_cursor);
    130         twitter_http(TWITTER_FRIENDS_IDS_URL, twitter_http_get_friends_ids, ic, 0, td->user, td->pass, args, 2);
     132        twitter_http(TWITTER_FRIENDS_IDS_URL, twitter_http_get_friends_ids, ic, 0, td->user, td->pass, td->oauth_info, args, 2);
    131133
    132134        g_free(args[1]);
     
    394396        }
    395397
    396         twitter_http(TWITTER_HOME_TIMELINE_URL, twitter_http_get_home_timeline, ic, 0, td->user, td->pass, args, td->home_timeline_id ? 4 : 2);
     398        twitter_http(TWITTER_HOME_TIMELINE_URL, twitter_http_get_home_timeline, ic, 0, td->user, td->pass, td->oauth_info, args, td->home_timeline_id ? 4 : 2);
    397399
    398400        g_free(args[1]);
     
    452454        GSList *l = NULL;
    453455        struct twitter_xml_status *status;
    454 
     456        char from[MAX_STRING];
     457        gboolean mode_one;
     458       
     459        mode_one = g_strcasecmp( set_getstr( &ic->acc->set, "mode" ), "one" ) == 0;
     460
     461        if( mode_one )
     462        {
     463                g_snprintf( from, sizeof( from ) - 1, "twitter_%s", ic->acc->user );
     464                from[MAX_STRING-1] = '\0';
     465        }
     466       
    455467        for ( l = list; l ; l = g_slist_next(l) )
    456468        {
     469                char *text = NULL;
     470               
    457471                status = l->data;
    458                 imcb_buddy_msg( ic, status->user->screen_name, status->text, 0, status->created_at );
     472               
     473                if( mode_one )
     474                        text = g_strdup_printf( "\002<\002%s\002>\002 %s",
     475                                                status->user->screen_name, status->text );
     476                else
     477                        twitter_add_buddy(ic, status->user->screen_name, status->user->name);
     478               
     479                imcb_buddy_msg( ic,
     480                                mode_one ? from : status->user->screen_name,
     481                                mode_one ? text : status->text,
     482                                0, status->created_at );
     483               
    459484                // Update the home_timeline_id to hold the highest id, so that by the next request
    460485                // we won't pick up the updates allready in the list.
    461486                td->home_timeline_id = td->home_timeline_id < status->id ? status->id : td->home_timeline_id;
     487               
     488                g_free( text );
    462489        }
    463490}
     
    483510        {
    484511                td->http_fails = 0;
    485                 if (!ic->flags & OPT_LOGGED_IN)
     512                if (!(ic->flags & OPT_LOGGED_IN))
    486513                        imcb_connected(ic);
    487514        }
     
    512539
    513540        // See if the user wants to see the messages in a groupchat window or as private messages.
    514         if (set_getbool( &ic->acc->set, "use_groupchat" ))
     541        if (g_strcasecmp(set_getstr(&ic->acc->set, "mode"), "chat") == 0)
    515542                twitter_groupchat(ic, txl->list);
    516543        else
     
    593620        args[1] = g_strdup_printf ("%d", next_cursor);
    594621
    595         twitter_http(TWITTER_SHOW_FRIENDS_URL, twitter_http_get_statuses_friends, ic, 0, td->user, td->pass, args, 2);
     622        twitter_http(TWITTER_SHOW_FRIENDS_URL, twitter_http_get_statuses_friends, ic, 0, td->user, td->pass, td->oauth_info, args, 2);
    596623
    597624        g_free(args[1]);
     
    612639        if (req->status_code != 200) {
    613640                // It didn't go well, output the error and return.
    614                 imcb_error(ic, "Could not post tweet... HTTP STATUS: %d", req->status_code);
     641                imcb_error(ic, "Could not post message... HTTP STATUS: %d", req->status_code);
    615642                return;
    616643        }
     
    627654        args[0] = "status";
    628655        args[1] = msg;
    629         twitter_http(TWITTER_STATUS_UPDATE_URL, twitter_http_post_status, ic, 1, td->user, td->pass, args, 2);
     656        twitter_http(TWITTER_STATUS_UPDATE_URL, twitter_http_post_status, ic, 1, td->user, td->pass, td->oauth_info, args, 2);
    630657//      g_free(args[1]);
    631658}
     
    645672        args[3] = msg;
    646673        // Use the same callback as for twitter_post_status, since it does basically the same.
    647         twitter_http(TWITTER_DIRECT_MESSAGES_NEW_URL, twitter_http_post_status, ic, 1, td->user, td->pass, args, 4);
     674        twitter_http(TWITTER_DIRECT_MESSAGES_NEW_URL, twitter_http_post_status, ic, 1, td->user, td->pass, td->oauth_info, args, 4);
    648675//      g_free(args[1]);
    649676//      g_free(args[3]);
Note: See TracChangeset for help on using the changeset viewer.