source: protocols/twitter/twitter.c @ 288b215

Last change on this file since 288b215 was 288b215, checked in by Wilmer van der Gaast <wilmer@…>, at 2010-04-26T22:50:25Z

Save the OAuth token in the acct structs so it doesn't have to be rerequested
every time.

  • Property mode set to 100644
File size: 8.9 KB
RevLine 
[1b221e0]1/***************************************************************************\
2*                                                                           *
3*  BitlBee - An IRC to IM gateway                                           *
4*  Simple module to facilitate twitter functionality.                       *
5*                                                                           *
6*  Copyright 2009 Geert Mulders <g.c.w.m.mulders@gmail.com>                 *
7*                                                                           *
8*  This library is free software; you can redistribute it and/or            *
9*  modify it under the terms of the GNU Lesser General Public               *
10*  License as published by the Free Software Foundation, version            *
11*  2.1.                                                                     *
12*                                                                           *
13*  This library is distributed in the hope that it will be useful,          *
14*  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
15*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU        *
16*  Lesser General Public License for more details.                          *
17*                                                                           *
18*  You should have received a copy of the GNU Lesser General Public License *
19*  along with this library; if not, write to the Free Software Foundation,  *
20*  Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA           *
21*                                                                           *
22****************************************************************************/
23
24#include "nogaim.h"
[713d611]25#include "oauth.h"
[1b221e0]26#include "twitter.h"
27#include "twitter_http.h"
28#include "twitter_lib.h"
29
30
31/**
[62d2cfb]32 * Main loop function
33 */
[1b221e0]34gboolean twitter_main_loop(gpointer data, gint fd, b_input_condition cond)
35{
36        struct im_connection *ic = data;
[3e69802]37       
[1b221e0]38        // Check if we are still logged in...
[3bd4a93]39        if (!g_slist_find( twitter_connections, ic ))
[1b221e0]40                return 0;
41
[62d2cfb]42        // If the user uses multiple private message windows we need to get the
43        // users buddies.
[e88fbe27]44        if (g_strcasecmp(set_getstr(&ic->acc->set, "mode"), "many") == 0)
[62d2cfb]45                twitter_get_statuses_friends(ic, -1);
46
[1b221e0]47        // Do stuff..
48        twitter_get_home_timeline(ic, -1);
49
50        // If we are still logged in run this function again after timeout.
51        return (ic->flags & OPT_LOGGED_IN) == OPT_LOGGED_IN;
52}
53
[713d611]54static void twitter_main_loop_start( struct im_connection *ic )
55{
56        struct twitter_data *td = ic->proto_data;
57       
58        imcb_log( ic, "Connecting to Twitter" );
59
60        // Run this once. After this queue the main loop function.
61        twitter_main_loop(ic, -1, 0);
62
63        // Queue the main_loop
64        // Save the return value, so we can remove the timeout on logout.
65        td->main_loop_id = b_timeout_add(60000, twitter_main_loop, ic);
66}
67
68static void twitter_oauth_callback( struct oauth_info *info );
69
70static void twitter_oauth_start( struct im_connection *ic )
71{
[c42e8b9]72        imcb_log( ic, "Requesting OAuth request token" );
73
[713d611]74        oauth_request_token( TWITTER_OAUTH_REQUEST_TOKEN, twitter_oauth_callback, ic );
75}
76
77static void twitter_oauth_callback( struct oauth_info *info )
78{
79        struct im_connection *ic = info->data;
[c42e8b9]80        struct twitter_data *td = ic->proto_data;
[713d611]81       
[c42e8b9]82        if( info->stage == OAUTH_REQUEST_TOKEN )
[713d611]83        {
84                char name[strlen(ic->acc->user)+9], *msg;
85               
[c42e8b9]86                if( info->request_token == NULL )
87                {
88                        imcb_error( ic, "OAuth error: %s", info->http->status_string );
89                        imc_logout( ic, TRUE );
90                        return;
91                }
92               
93                td->oauth_info = info;
94               
[713d611]95                sprintf( name, "twitter_%s", ic->acc->user );
96                msg = g_strdup_printf( "To finish OAuth authentication, please visit "
97                                       "%s?%s and respond with the resulting PIN code.",
98                                       TWITTER_OAUTH_AUTHORIZE, info->auth_params );
99                imcb_buddy_msg( ic, name, msg, 0, 0 );
100                g_free( msg );
101        }
[c42e8b9]102        else if( info->stage == OAUTH_ACCESS_TOKEN )
103        {
104                if( info->access_token == NULL )
105                {
106                        imcb_error( ic, "OAuth error: %s", info->http->status_string );
107                        imc_logout( ic, TRUE );
108                        return;
109                }
110               
111                td->oauth = g_strdup( info->access_token );
112               
[288b215]113                /* IM mods didn't do this so far and it's ugly but I should
114                   be able to get away with it... */
115                g_free( ic->acc->pass );
116                ic->acc->pass = g_strdup( info->access_token );
117               
[c42e8b9]118                twitter_main_loop_start( ic );
119        }
[713d611]120}
121
[e88fbe27]122static char *set_eval_mode( set_t *set, char *value )
123{
124        if( g_strcasecmp( value, "one" ) == 0 ||
125            g_strcasecmp( value, "many" ) == 0 ||
[db57e7c]126            g_strcasecmp( value, "chat" ) == 0 )
[e88fbe27]127                return value;
128        else
129                return NULL;
130}
[1b221e0]131
132static void twitter_init( account_t *acc )
133{
[62d2cfb]134        set_t *s;
[e88fbe27]135       
136        s = set_add( &acc->set, "mode", "one", set_eval_mode, acc );
[2abceca]137        s->flags |= ACC_SET_OFFLINE_ONLY;
[713d611]138       
139        s = set_add( &acc->set, "oauth", "true", set_eval_bool, acc );
[1b221e0]140}
141
142/**
143 * Login method. Since the twitter API works with seperate HTTP request we
144 * only save the user and pass to the twitter_data object.
145 */
146static void twitter_login( account_t *acc )
147{
148        struct im_connection *ic = imcb_new( acc );
149        struct twitter_data *td = g_new0( struct twitter_data, 1 );
[e88fbe27]150        char name[strlen(acc->user)+9];
[62d2cfb]151
[d569019]152        twitter_connections = g_slist_append( twitter_connections, ic );
[713d611]153        ic->proto_data = td;
154       
[1b221e0]155        td->user = acc->user;
[713d611]156        if( !set_getbool( &acc->set, "oauth" ) )
[508c340]157                td->pass = g_strdup( acc->pass );
[713d611]158        else if( strstr( acc->pass, "oauth_token=" ) )
[508c340]159                td->oauth = g_strdup( acc->pass );
[1b221e0]160        td->home_timeline_id = 0;
[e88fbe27]161       
162        sprintf( name, "twitter_%s", acc->user );
163        imcb_add_buddy( ic, name, NULL );
164        imcb_buddy_status( ic, name, OPT_LOGGED_IN, NULL, NULL );
[713d611]165       
166        if( td->pass || td->oauth )
167                twitter_main_loop_start( ic );
168        else
169                twitter_oauth_start( ic );
[1b221e0]170}
171
172/**
173 * Logout method. Just free the twitter_data.
174 */
175static void twitter_logout( struct im_connection *ic )
176{
177        struct twitter_data *td = ic->proto_data;
178       
179        // Set the status to logged out.
180        ic->flags = 0;
181
[2abceca]182        // Remove the main_loop function from the function queue.
183        b_event_remove(td->main_loop_id);
184
[37d84b3]185        if(td->home_timeline_gc)
186                imcb_chat_free(td->home_timeline_gc);
[1014cab]187
[1b221e0]188        if( td )
189        {
[508c340]190                g_free( td->pass );
191                g_free( td->oauth );
[1b221e0]192                g_free( td );
193        }
[62d2cfb]194
195        twitter_connections = g_slist_remove( twitter_connections, ic );
[1b221e0]196}
197
198/**
199 *
200 */
201static int twitter_buddy_msg( struct im_connection *ic, char *who, char *message, int away )
202{
[c42e8b9]203        struct twitter_data *td = ic->proto_data;
204       
[e88fbe27]205        if (g_strncasecmp(who, "twitter_", 8) == 0 &&
206            g_strcasecmp(who + 8, ic->acc->user) == 0)
[c42e8b9]207        {
208                if( set_getbool( &ic->acc->set, "oauth" ) && td->oauth == NULL )
209                        oauth_access_token( TWITTER_OAUTH_ACCESS_TOKEN, message, td->oauth_info );
210                else
211                        twitter_post_status(ic, message);
212        }
[e88fbe27]213        else
[c42e8b9]214        {
[e88fbe27]215                twitter_direct_messages_new(ic, who, message);
[c42e8b9]216        }
[1b221e0]217        return( 0 );
218}
219
220/**
221 *
222 */
223static void twitter_set_my_name( struct im_connection *ic, char *info )
224{
225}
226
227static void twitter_get_info(struct im_connection *ic, char *who) 
228{
229}
230
231static void twitter_add_buddy( struct im_connection *ic, char *who, char *group )
232{
233}
234
235static void twitter_remove_buddy( struct im_connection *ic, char *who, char *group )
236{
237}
238
239static void twitter_chat_msg( struct groupchat *c, char *message, int flags )
240{
[2abceca]241        if( c && message )
242                twitter_post_status(c->ic, message);
[1b221e0]243}
244
245static void twitter_chat_invite( struct groupchat *c, char *who, char *message )
246{
247}
248
249static void twitter_chat_leave( struct groupchat *c )
250{
[16592d8]251        struct twitter_data *td = c->ic->proto_data;
252       
253        if( c != td->home_timeline_gc )
254                return; /* WTF? */
255       
256        /* If the user leaves the channel: Fine. Rejoin him/her once new
257           tweets come in. */
258        imcb_chat_free(td->home_timeline_gc);
259        td->home_timeline_gc = NULL;
[1b221e0]260}
261
262static struct groupchat *twitter_chat_with( struct im_connection *ic, char *who )
263{
264        return NULL;
265}
266
267static void twitter_keepalive( struct im_connection *ic )
268{
269}
270
271static void twitter_add_permit( struct im_connection *ic, char *who )
272{
273}
274
275static void twitter_rem_permit( struct im_connection *ic, char *who )
276{
277}
278
279static void twitter_add_deny( struct im_connection *ic, char *who )
280{
281}
282
283static void twitter_rem_deny( struct im_connection *ic, char *who )
284{
285}
286
287static int twitter_send_typing( struct im_connection *ic, char *who, int typing )
288{
289        return( 1 );
290}
291
292//static char *twitter_set_display_name( set_t *set, char *value )
293//{
294//      return value;
295//}
296
297void twitter_initmodule()
298{
299        struct prpl *ret = g_new0(struct prpl, 1);
300       
301        ret->name = "twitter";
302        ret->login = twitter_login;
303        ret->init = twitter_init;
304        ret->logout = twitter_logout;
305        ret->buddy_msg = twitter_buddy_msg;
306        ret->get_info = twitter_get_info;
307        ret->set_my_name = twitter_set_my_name;
308        ret->add_buddy = twitter_add_buddy;
309        ret->remove_buddy = twitter_remove_buddy;
310        ret->chat_msg = twitter_chat_msg;
311        ret->chat_invite = twitter_chat_invite;
312        ret->chat_leave = twitter_chat_leave;
313        ret->chat_with = twitter_chat_with;
314        ret->keepalive = twitter_keepalive;
315        ret->add_permit = twitter_add_permit;
316        ret->rem_permit = twitter_rem_permit;
317        ret->add_deny = twitter_add_deny;
318        ret->rem_deny = twitter_rem_deny;
319        ret->send_typing = twitter_send_typing;
320        ret->handle_cmp = g_strcasecmp;
321
322        register_protocol(ret);
[62d2cfb]323
324        // Initialise the twitter_connections GSList.
325        twitter_connections = NULL;
[1b221e0]326}
327
Note: See TracBrowser for help on using the repository browser.