source: protocols/purple/purple.c @ 0f7ee7e5

Last change on this file since 0f7ee7e5 was 0f7ee7e5, checked in by Wilmer van der Gaast <wilmer@…>, at 2009-10-11T12:57:29Z

Copy all the string/bool/int account settings with their defaults to
"account set". They can be changed, but changes don't yet have any effect.

  • Property mode set to 100644
File size: 11.3 KB
Line 
1/***************************************************************************\
2*                                                                           *
3*  BitlBee - An IRC to IM gateway                                           *
4*  libpurple module - Main file                                             *
5*                                                                           *
6*  Copyright 2009 Wilmer van der Gaast <wilmer@gaast.net>                   *
7*                                                                           *
8*  This program is free software; you can redistribute it and/or modify     *
9*  it under the terms of the GNU General Public License as published by     *
10*  the Free Software Foundation; either version 2 of the License, or        *
11*  (at your option) any later version.                                      *
12*                                                                           *
13*  This program 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            *
16*  GNU General Public License for more details.                             *
17*                                                                           *
18*  You should have received a copy of the GNU General Public License along  *
19*  with this program; if not, write to the Free Software Foundation, Inc.,  *
20*  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.              *
21*                                                                           *
22\***************************************************************************/
23
24#include <glib.h>
25#include <purple.h>
26
27#include "bitlbee.h"
28
29GSList *purple_connections;
30
31static struct im_connection *purple_ic_by_pa( PurpleAccount *pa )
32{
33        GSList *i;
34       
35        for( i = purple_connections; i; i = i->next )
36                if( ((struct im_connection *)i->data)->proto_data == pa )
37                        return i->data;
38       
39        return NULL;
40}
41
42static struct im_connection *purple_ic_by_gc( PurpleConnection *gc )
43{
44        return purple_ic_by_pa( purple_connection_get_account( gc ) );
45}
46
47static void purple_init( account_t *acc )
48{
49        PurplePlugin *prpl = purple_plugins_find_with_id( acc->prpl->name );
50        PurplePluginProtocolInfo *pi = prpl->info->extra_info;
51        GList *i;
52       
53        for( i = pi->protocol_options; i; i = i->next )
54        {
55                PurpleAccountOption *o = i->data;
56                const char *name;
57                char *def = NULL;
58                set_eval eval = NULL;
59                set_t *s;
60               
61                name = purple_account_option_get_setting( o );
62               
63                switch( purple_account_option_get_type( o ) )
64                {
65                case PURPLE_PREF_STRING:
66                        def = g_strdup( purple_account_option_get_default_string( o ) );
67                        break;
68               
69                case PURPLE_PREF_INT:
70                        def = g_strdup_printf( "%d", purple_account_option_get_default_int( o ) );
71                        eval = set_eval_int;
72                        break;
73               
74                case PURPLE_PREF_BOOLEAN:
75                        if( purple_account_option_get_default_bool( o ) )
76                                def = g_strdup( "true" );
77                        else
78                                def = g_strdup( "false" );
79                        eval = set_eval_bool;
80                        break;
81               
82                default:
83                        fprintf( stderr, "Setting with unknown type: %s (%d)\n", name, purple_account_option_get_type( o ) );
84                }
85               
86                if( def != NULL )
87                {
88                        s = set_add( &acc->set, name, def, eval, acc );
89                        s->flags |= ACC_SET_OFFLINE_ONLY;
90                        g_free( def );
91                }
92        }
93}
94
95static void purple_login( account_t *acc )
96{
97        struct im_connection *ic = imcb_new( acc );
98        PurpleAccount *pa;
99       
100        /* For now this is needed in the _connected() handlers if using
101           GLib event handling, to make sure we're not handling events
102           on dead connections. */
103        purple_connections = g_slist_prepend( purple_connections, ic );
104       
105        pa = purple_account_new( acc->user, acc->prpl->name );
106        purple_account_set_password( pa, acc->pass );
107       
108        ic->proto_data = pa;
109       
110        purple_account_set_enabled( pa, "BitlBee", TRUE );
111}
112
113static void purple_logout( struct im_connection *ic )
114{
115        PurpleAccount *pa = ic->proto_data;
116       
117        purple_account_set_enabled( pa, "BitlBee", FALSE );
118        purple_connections = g_slist_remove( purple_connections, ic );
119        purple_account_destroy( pa );
120}
121
122static int purple_buddy_msg( struct im_connection *ic, char *who, char *message, int flags )
123{
124        PurpleConversation *conv;
125       
126        if( ( conv = purple_find_conversation_with_account( PURPLE_CONV_TYPE_IM,
127                                                            who, ic->proto_data ) ) == NULL )
128        {
129                conv = purple_conversation_new( PURPLE_CONV_TYPE_IM,
130                                                ic->proto_data, who );
131        }
132       
133        purple_conv_im_send( purple_conversation_get_im_data( conv ), message );
134       
135        return 1;
136}
137
138static GList *purple_away_states( struct im_connection *ic )
139{
140        return NULL;
141}
142
143static void purple_set_away( struct im_connection *ic, char *state_txt, char *message )
144{
145}
146
147static void purple_add_buddy( struct im_connection *ic, char *who, char *group )
148{
149}
150
151static void purple_remove_buddy( struct im_connection *ic, char *who, char *group )
152{
153}
154
155static void purple_keepalive( struct im_connection *ic )
156{
157}
158
159static int purple_send_typing( struct im_connection *ic, char *who, int typing )
160{
161        return 1;
162}
163
164static void purple_ui_init();
165
166static PurpleCoreUiOps bee_core_uiops = 
167{
168        NULL,
169        NULL,
170        purple_ui_init,
171        NULL,
172};
173
174static void prplcb_conn_progress( PurpleConnection *gc, const char *text, size_t step, size_t step_count )
175{
176        struct im_connection *ic = purple_ic_by_gc( gc );
177       
178        imcb_log( ic, "%s", text );
179}
180
181static void prplcb_conn_connected( PurpleConnection *gc )
182{
183        struct im_connection *ic = purple_ic_by_gc( gc );
184       
185        imcb_connected( ic );
186       
187        if( gc->flags & PURPLE_CONNECTION_HTML )
188                ic->flags |= OPT_DOES_HTML;
189}
190
191static void prplcb_conn_disconnected( PurpleConnection *gc )
192{
193        struct im_connection *ic = purple_ic_by_gc( gc );
194       
195        if( ic != NULL )
196                imc_logout( ic, TRUE );
197}
198
199static void prplcb_conn_notice( PurpleConnection *gc, const char *text )
200{
201        struct im_connection *ic = purple_ic_by_gc( gc );
202       
203        if( ic != NULL )
204                imcb_log( ic, "%s", text );
205}
206
207static void prplcb_conn_report_disconnect_reason( PurpleConnection *gc, PurpleConnectionError reason, const char *text )
208{
209        struct im_connection *ic = purple_ic_by_gc( gc );
210       
211        /* PURPLE_CONNECTION_ERROR_NAME_IN_USE means concurrent login,
212           should probably handle that. */
213        if( ic != NULL )
214                imcb_error( ic, "%s", text );
215}
216
217static PurpleConnectionUiOps bee_conn_uiops =
218{
219        prplcb_conn_progress,
220        prplcb_conn_connected,
221        prplcb_conn_disconnected,
222        prplcb_conn_notice,
223        NULL,
224        NULL,
225        NULL,
226        prplcb_conn_report_disconnect_reason,
227};
228
229static void prplcb_blist_new( PurpleBlistNode *node )
230{
231        PurpleBuddy *bud = (PurpleBuddy*) node;
232       
233        if( node->type == PURPLE_BLIST_BUDDY_NODE )
234        {
235                struct im_connection *ic = purple_ic_by_pa( bud->account );
236               
237                if( ic == NULL )
238                        return;
239               
240                imcb_add_buddy( ic, bud->name, NULL );
241                if( bud->server_alias )
242                        imcb_buddy_nick_hint( ic, bud->name, bud->server_alias );
243        }
244}
245
246static void prplcb_blist_update( PurpleBuddyList *list, PurpleBlistNode *node )
247{
248        PurpleBuddy *bud = (PurpleBuddy*) node;
249       
250        if( node->type == PURPLE_BLIST_BUDDY_NODE )
251        {
252                struct im_connection *ic = purple_ic_by_pa( bud->account );
253                PurpleStatus *as;
254                int flags = 0;
255               
256                if( ic == NULL )
257                        return;
258               
259                flags |= purple_presence_is_online( bud->presence ) ? OPT_LOGGED_IN : 0;
260                flags |= purple_presence_is_available( bud->presence ) ? 0 : OPT_AWAY;
261               
262                as = purple_presence_get_active_status( bud->presence );
263               
264                imcb_buddy_status( ic, bud->name, flags, purple_status_get_name( as ),
265                                   purple_status_get_attr_string( as, "message" ) );
266        }
267}
268
269static void prplcb_blist_remove( PurpleBuddyList *list, PurpleBlistNode *node )
270{
271        PurpleBuddy *bud = (PurpleBuddy*) node;
272       
273        if( node->type == PURPLE_BLIST_BUDDY_NODE )
274        {
275                struct im_connection *ic = purple_ic_by_pa( bud->account );
276               
277                if( ic == NULL )
278                        return;
279               
280                imcb_remove_buddy( ic, bud->name, NULL );
281        }
282}
283
284static PurpleBlistUiOps bee_blist_uiops =
285{
286        NULL,
287        prplcb_blist_new,
288        NULL,
289        prplcb_blist_update,
290        prplcb_blist_remove,
291};
292
293static void prplcb_conv_im( PurpleConversation *conv, const char *who, const char *message, PurpleMessageFlags flags, time_t mtime )
294{
295        struct im_connection *ic = purple_ic_by_pa( conv->account );
296       
297        /* ..._SEND means it's an outgoing message, no need to echo those. */
298        if( !( flags & PURPLE_MESSAGE_SEND ) )
299                imcb_buddy_msg( ic, (char*) who, (char*) message, 0, mtime );
300}
301
302static PurpleConversationUiOps bee_conv_uiops = 
303{
304        NULL,                      /* create_conversation  */
305        NULL,                      /* destroy_conversation */
306        NULL,                      /* write_chat           */
307        prplcb_conv_im,            /* write_im             */
308        NULL,                      /* write_conv           */
309        NULL,                      /* chat_add_users       */
310        NULL,                      /* chat_rename_user     */
311        NULL,                      /* chat_remove_users    */
312        NULL,                      /* chat_update_user     */
313        NULL,                      /* present              */
314        NULL,                      /* has_focus            */
315        NULL,                      /* custom_smiley_add    */
316        NULL,                      /* custom_smiley_write  */
317        NULL,                      /* custom_smiley_close  */
318        NULL,                      /* send_confirm         */
319        NULL,
320        NULL,
321        NULL,
322        NULL
323};
324
325static void prplcb_debug_print( PurpleDebugLevel level, const char *category, const char *arg_s )
326{
327        printf( "DEBUG %s: %s", category, arg_s );
328}
329
330static PurpleDebugUiOps bee_debug_uiops =
331{
332        prplcb_debug_print,
333};
334
335static guint prplcb_ev_timeout_add( guint interval, GSourceFunc func, gpointer udata )
336{
337        return b_timeout_add( interval, (b_event_handler) func, udata );
338}
339
340static guint prplcb_ev_input_add( int fd, PurpleInputCondition cond, PurpleInputFunction func, gpointer udata )
341{
342        return b_input_add( fd, cond | B_EV_FLAG_FORCE_REPEAT, (b_event_handler) func, udata );
343}
344
345static gboolean prplcb_ev_remove( guint id )
346{
347        b_event_remove( (gint) id );
348        return TRUE;
349}
350
351static PurpleEventLoopUiOps glib_eventloops = 
352{
353        prplcb_ev_timeout_add,
354        prplcb_ev_remove,
355        prplcb_ev_input_add,
356        prplcb_ev_remove,
357};
358
359static void purple_ui_init()
360{
361        purple_blist_set_ui_ops( &bee_blist_uiops );
362        purple_connections_set_ui_ops( &bee_conn_uiops );
363        purple_conversations_set_ui_ops( &bee_conv_uiops );
364        //purple_debug_set_ui_ops( &bee_debug_uiops );
365}
366
367void purple_initmodule()
368{
369        GList *prots;
370       
371        if( B_EV_IO_READ != PURPLE_INPUT_READ ||
372            B_EV_IO_WRITE != PURPLE_INPUT_WRITE )
373        {
374                /* FIXME FIXME FIXME FIXME FIXME :-) */
375                exit( 1 );
376        }
377       
378        purple_util_set_user_dir("/tmp");
379        purple_debug_set_enabled(FALSE);
380        purple_core_set_ui_ops(&bee_core_uiops);
381        purple_eventloop_set_ui_ops(&glib_eventloops);
382        if( !purple_core_init( "BitlBee") )
383        {
384                /* Initializing the core failed. Terminate. */
385                fprintf( stderr, "libpurple initialization failed.\n" );
386                abort();
387        }
388       
389        /* This seems like stateful shit we don't want... */
390        purple_set_blist(purple_blist_new());
391        purple_blist_load();
392       
393        /* Meh? */
394        purple_prefs_load();
395       
396        for( prots = purple_plugins_get_protocols(); prots; prots = prots->next )
397        {
398                struct prpl *ret = g_new0( struct prpl, 1 );
399                PurplePlugin *prot = prots->data;
400               
401                ret->name = prot->info->id;
402                ret->login = purple_login;
403                ret->init = purple_init;
404                ret->logout = purple_logout;
405                ret->buddy_msg = purple_buddy_msg;
406                ret->away_states = purple_away_states;
407                ret->set_away = purple_set_away;
408                ret->add_buddy = purple_add_buddy;
409                ret->remove_buddy = purple_remove_buddy;
410                ret->keepalive = purple_keepalive;
411                ret->send_typing = purple_send_typing;
412                ret->handle_cmp = g_strcasecmp;
413               
414                register_protocol( ret );
415        }
416}
Note: See TracBrowser for help on using the repository browser.