source: skype/skype.c @ b06e647

Last change on this file since b06e647 was de2f05e, checked in by Miklos Vajna <vmiklos@…>, at 2007-11-20T09:47:43Z

fixes for the recent upstream API changes

  • Property mode set to 100644
File size: 19.4 KB
Line 
1/*
2 *  skype.c - Skype plugin for BitlBee
3 *
4 *  Copyright (c) 2007 by Miklos Vajna <vmiklos@frugalware.org>
5 *
6 *  Several ideas are used from the BitlBee Jabber plugin, which is
7 *
8 *  Copyright (c) 2006 by Wilmer van der Gaast <wilmer@gaast.net>
9 *
10 *  This program is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License as published by
12 *  the Free Software Foundation; either version 2 of the License, or
13 *  (at your option) any later version.
14 *
15 *  This program is distributed in the hope that it will be useful,
16 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 *  GNU General Public License for more details.
19 *
20 *  You should have received a copy of the GNU General Public License
21 *  along with this program; if not, write to the Free Software
22 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
23 *  USA.
24 */
25
26#include <stdio.h>
27#include <poll.h>
28#include <bitlbee.h>
29#include <glib.h>
30
31#define SKYPE_PORT_DEFAULT "2727"
32
33/*
34 * Enumerations
35 */
36
37typedef enum
38{
39        SKYPE_CALL_RINGING = 1,
40        SKYPE_CALL_MISSED
41} skype_call_status;
42
43typedef enum
44{
45        SKYPE_FILETRANSFER_NEW = 1,
46        SKYPE_FILETRANSFER_FAILED
47} skype_filetransfer_status;
48
49/*
50 * Structures
51 */
52
53struct skype_data
54{
55        struct im_connection *ic;
56        char *username;
57        /* The effective file descriptor. We store it here so any function can
58         * write() to it. */
59        int fd;
60        /* File descriptor returned by bitlbee. we store it so we know when
61         * we're connected and when we aren't. */
62        int bfd;
63        /* When we receive a new message id, we query the properties, finally
64         * the chatname. Store the properties here so that we can use
65         * imcb_buddy_msg() when we got the chatname. */
66        char *handle;
67        /* List, because of multiline messages. */
68        GList *body;
69        char *type;
70        /* This is necessary because we send a notification when we get the
71         * handle. So we store the state here and then we can send a
72         * notification about the handle is in a given status. */
73        skype_call_status call_status;
74        /* Same for file transfers. */
75        skype_filetransfer_status filetransfer_status;
76        /* Using /j #nick we want to have a groupchat with two people. Usually
77         * not (default). */
78        char* groupchat_with;
79        /* The user who invited us to the chat. */
80        char* adder;
81        /* If we are waiting for a confirmation about we changed the topic. */
82        int topic_wait;
83};
84
85struct skype_away_state
86{
87        char *code;
88        char *full_name;
89};
90
91struct skype_buddy_ask_data
92{
93        struct im_connection *ic;
94        char *handle;
95};
96
97/*
98 * Tables
99 */
100
101const struct skype_away_state skype_away_state_list[] =
102{
103        { "ONLINE",  "Online" },
104        { "SKYPEME",  "Skype Me" },
105        { "AWAY",   "Away" },
106        { "NA",    "Not available" },
107        { "DND",      "Do Not Disturb" },
108        { "INVISIBLE",      "Invisible" },
109        { "OFFLINE",      "Offline" },
110        { NULL, NULL}
111};
112
113/*
114 * Functions
115 */
116
117static void skype_init( account_t *acc )
118{
119        set_t *s;
120
121        s = set_add( &acc->set, "port", SKYPE_PORT_DEFAULT, set_eval_int, acc );
122        s->flags |= ACC_SET_OFFLINE_ONLY;
123
124        s = set_add( &acc->set, "server", NULL, set_eval_account, acc );
125        s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY;
126}
127
128int skype_write( struct im_connection *ic, char *buf, int len )
129{
130        struct skype_data *sd = ic->proto_data;
131        struct pollfd pfd[1];
132
133        pfd[0].fd = sd->fd;
134        pfd[0].events = POLLOUT;
135
136        /* This poll is necessary or we'll get a SIGPIPE when we write() to
137         * sd->fd. */
138        poll(pfd, 1, 1000);
139        if(pfd[0].revents & POLLHUP)
140        {
141                imcb_error( ic, "Could not connect to server" );
142                imc_logout( ic, TRUE );
143                return FALSE;
144        }
145        write( sd->fd, buf, len );
146
147        return TRUE;
148}
149
150static void skype_buddy_ask_yes( gpointer w, struct skype_buddy_ask_data *bla )
151{
152        char *buf = g_strdup_printf("SET USER %s ISAUTHORIZED TRUE", bla->handle);
153        skype_write( bla->ic, buf, strlen( buf ) );
154        g_free(buf);
155        g_free(bla->handle);
156        g_free(bla);
157}
158
159static void skype_buddy_ask_no( gpointer w, struct skype_buddy_ask_data *bla )
160{
161        char *buf = g_strdup_printf("SET USER %s ISAUTHORIZED FALSE", bla->handle);
162        skype_write( bla->ic, buf, strlen( buf ) );
163        g_free(buf);
164        g_free(bla->handle);
165        g_free(bla);
166}
167
168void skype_buddy_ask( struct im_connection *ic, char *handle, char *message)
169{
170        struct skype_buddy_ask_data *bla = g_new0( struct skype_buddy_ask_data, 1 );
171        char *buf;
172
173        bla->ic = ic;
174        bla->handle = g_strdup(handle);
175
176        buf = g_strdup_printf( "The user %s wants to add you to his/her buddy list, saying: '%s'.", handle, message);
177        imcb_ask( ic, buf, bla, skype_buddy_ask_yes, skype_buddy_ask_no );
178        g_free( buf );
179}
180
181struct groupchat *skype_chat_by_name( struct im_connection *ic, char *name )
182{
183        struct groupchat *ret;
184
185        for( ret = ic->groupchats; ret; ret = ret->next )
186        {
187                if(strcmp(name, ret->title ) == 0 )
188                        break;
189        }
190
191        return ret;
192}
193
194static gboolean skype_read_callback( gpointer data, gint fd, b_input_condition cond )
195{
196        struct im_connection *ic = data;
197        struct skype_data *sd = ic->proto_data;
198        char buf[1024];
199        int st;
200        char **lines, **lineptr, *line, *ptr;
201
202        if( !sd || sd->fd == -1 )
203                return FALSE;
204        /* Read the whole data. */
205        st = read( sd->fd, buf, sizeof( buf ) );
206        if( st > 0 )
207        {
208                buf[st] = '\0';
209                /* Then split it up to lines. */
210                lines = g_strsplit(buf, "\n", 0);
211                lineptr = lines;
212                while((line = *lineptr))
213                {
214                        if(!strlen(line))
215                                break;
216                        if(!strncmp(line, "USERS ", 6))
217                        {
218                                char **i;
219                                char **nicks;
220
221                                nicks = g_strsplit(line + 6, ", ", 0);
222                                i = nicks;
223                                while(*i)
224                                {
225                                        g_snprintf(buf, 1024, "GET USER %s ONLINESTATUS\n", *i);
226                                        skype_write( ic, buf, strlen( buf ) );
227                                        i++;
228                                }
229                                g_strfreev(nicks);
230                        }
231                        else if(!strncmp(line, "USER ", 5))
232                        {
233                                int flags = 0;
234                                char *status = strrchr(line, ' ');
235                                char *user = strchr(line, ' ');
236                                status++;
237                                ptr = strchr(++user, ' ');
238                                *ptr = '\0';
239                                ptr++;
240                                if(!strncmp(ptr, "ONLINESTATUS ", 13) &&
241                                                strcmp(user, sd->username) != 0
242                                                && strcmp(user, "echo123") != 0)
243                                {
244                                        ptr = g_strdup_printf("%s@skype.com", user);
245                                        imcb_add_buddy(ic, ptr, NULL);
246                                        if(strcmp(status, "OFFLINE") != 0)
247                                                flags |= OPT_LOGGED_IN;
248                                        if(strcmp(status, "ONLINE") != 0 && strcmp(status, "SKYPEME") != 0)
249                                                flags |= OPT_AWAY;
250                                        imcb_buddy_status(ic, ptr, flags, NULL, NULL);
251                                        g_free(ptr);
252                                }
253                                else if(!strncmp(ptr, "RECEIVEDAUTHREQUEST ", 20))
254                                {
255                                        char *message = ptr + 20;
256                                        if(strlen(message))
257                                                skype_buddy_ask(ic, user, message);
258                                }
259                                else if(!strncmp(ptr, "BUDDYSTATUS ", 12))
260                                {
261                                        char *st = ptr + 12;
262                                        if(!strcmp(st, "3"))
263                                        {
264                                                char *buf = g_strdup_printf("%s@skype.com", user);
265                                                imcb_add_buddy(ic, buf, NULL);
266                                                g_free(buf);
267                                        }
268                                }
269                        }
270                        else if(!strncmp(line, "CHATMESSAGE ", 12))
271                        {
272                                char *id = strchr(line, ' ');
273                                if(++id)
274                                {
275                                        char *info = strchr(id, ' ');
276                                        *info = '\0';
277                                        info++;
278                                        if(!strcmp(info, "STATUS RECEIVED"))
279                                        {
280                                                /* New message ID:
281                                                 * (1) Request its from field
282                                                 * (2) Request its body
283                                                 * (3) Request its type
284                                                 * (4) Query chatname
285                                                 */
286                                                g_snprintf(buf, 1024, "GET CHATMESSAGE %s FROM_HANDLE\n", id);
287                                                skype_write( ic, buf, strlen( buf ) );
288                                                g_snprintf(buf, 1024, "GET CHATMESSAGE %s BODY\n", id);
289                                                skype_write( ic, buf, strlen( buf ) );
290                                                g_snprintf(buf, 1024, "GET CHATMESSAGE %s TYPE\n", id);
291                                                skype_write( ic, buf, strlen( buf ) );
292                                                g_snprintf(buf, 1024, "GET CHATMESSAGE %s CHATNAME\n", id);
293                                                skype_write( ic, buf, strlen( buf ) );
294                                        }
295                                        else if(!strncmp(info, "FROM_HANDLE ", 12))
296                                        {
297                                                info += 12;
298                                                /* New from field value. Store
299                                                 * it, then we can later use it
300                                                 * when we got the message's
301                                                 * body. */
302                                                g_free(sd->handle);
303                                                sd->handle = g_strdup_printf("%s@skype.com", info);
304                                        }
305                                        else if(!strncmp(info, "EDITED_BY ", 10))
306                                        {
307                                                info += 10;
308                                                /* This is the same as
309                                                 * FROM_HANDLE, except that we
310                                                 * never request these lines
311                                                 * from Skype, we just get
312                                                 * them. */
313                                                g_free(sd->handle);
314                                                sd->handle = g_strdup_printf("%s@skype.com", info);
315                                        }
316                                        else if(!strncmp(info, "BODY ", 5))
317                                        {
318                                                info += 5;
319                                                sd->body = g_list_append(sd->body, g_strdup(info));
320                                        }
321                                        else if(!strncmp(info, "TYPE ", 5))
322                                        {
323                                                info += 5;
324                                                g_free(sd->type);
325                                                sd->type = g_strdup(info);
326                                        }
327                                        else if(!strncmp(info, "CHATNAME ", 9))
328                                        {
329                                                info += 9;
330                                                if(sd->handle && sd->body && sd->type)
331                                                {
332                                                        struct groupchat *gc = skype_chat_by_name(ic, info);
333                                                        int i;
334                                                        for(i=0;i<g_list_length(sd->body);i++)
335                                                        {
336                                                                char *body = g_list_nth_data(sd->body, i);
337                                                                if(!strcmp(sd->type, "SAID"))
338                                                                {
339                                                                        if(!gc)
340                                                                                /* Private message */
341                                                                                imcb_buddy_msg(ic, sd->handle, body, 0, 0);
342                                                                        else
343                                                                                /* Groupchat message */
344                                                                                imcb_chat_msg(gc, sd->handle, body, 0, 0);
345                                                                }
346                                                                else if(!strcmp(sd->type, "SETTOPIC"))
347                                                                {
348                                                                        if(gc)
349                                                                                imcb_chat_topic(gc, sd->handle, body, 0);
350                                                                }
351                                                                else if(!strcmp(sd->type, "LEFT"))
352                                                                {
353                                                                        if(gc)
354                                                                                imcb_chat_remove_buddy(gc, sd->handle, NULL);
355                                                                }
356                                                        }
357                                                        g_list_free(sd->body);
358                                                        sd->body = NULL;
359                                                }
360                                        }
361                                }
362                        }
363                        else if(!strncmp(line, "CALL ", 5))
364                        {
365                                char *id = strchr(line, ' ');
366                                if(++id)
367                                {
368                                        char *info = strchr(id, ' ');
369                                        *info = '\0';
370                                        info++;
371                                        if(!strcmp(info, "STATUS RINGING"))
372                                        {
373                                                g_snprintf(buf, 1024, "GET CALL %s PARTNER_HANDLE\n", id);
374                                                skype_write( ic, buf, strlen( buf ) );
375                                                sd->call_status = SKYPE_CALL_RINGING;
376                                        }
377                                        else if(!strcmp(info, "STATUS MISSED"))
378                                        {
379                                                g_snprintf(buf, 1024, "GET CALL %s PARTNER_HANDLE\n", id);
380                                                skype_write( ic, buf, strlen( buf ) );
381                                                sd->call_status = SKYPE_CALL_MISSED;
382                                        }
383                                        else if(!strncmp(info, "PARTNER_HANDLE ", 15))
384                                        {
385                                                info += 15;
386                                                if(sd->call_status) {
387                                                        switch(sd->call_status)
388                                                        {
389                                                                case SKYPE_CALL_RINGING:
390                                                                        imcb_log(ic, "The user %s is currently ringing you.", info);
391                                                                        break;
392                                                                case SKYPE_CALL_MISSED:
393                                                                        imcb_log(ic, "You have missed a call from user %s.", info);
394                                                                        break;
395                                                        }
396                                                        sd->call_status = 0;
397                                                }
398                                        }
399                                }
400                        }
401                        else if(!strncmp(line, "FILETRANSFER ", 13))
402                        {
403                                char *id = strchr(line, ' ');
404                                if(++id)
405                                {
406                                        char *info = strchr(id, ' ');
407                                        *info = '\0';
408                                        info++;
409                                        if(!strcmp(info, "STATUS NEW"))
410                                        {
411                                                g_snprintf(buf, 1024, "GET FILETRANSFER %s PARTNER_HANDLE\n", id);
412                                                skype_write( ic, buf, strlen( buf ) );
413                                                sd->filetransfer_status = SKYPE_FILETRANSFER_NEW;
414                                        }
415                                        else if(!strcmp(info, "STATUS FAILED"))
416                                        {
417                                                g_snprintf(buf, 1024, "GET FILETRANSFER %s PARTNER_HANDLE\n", id);
418                                                skype_write( ic, buf, strlen( buf ) );
419                                                sd->filetransfer_status = SKYPE_FILETRANSFER_FAILED;
420                                        }
421                                        else if(!strncmp(info, "PARTNER_HANDLE ", 15))
422                                        {
423                                                info += 15;
424                                                if(sd->filetransfer_status) {
425                                                        switch(sd->filetransfer_status)
426                                                        {
427                                                                case SKYPE_FILETRANSFER_NEW:
428                                                                        imcb_log(ic, "The user %s offered a new file for you.", info);
429                                                                        break;
430                                                                case SKYPE_FILETRANSFER_FAILED:
431                                                                        imcb_log(ic, "Failed to transfer file from user %s.", info);
432                                                                        break;
433                                                        }
434                                                        sd->filetransfer_status = 0;
435                                                }
436                                        }
437                                }
438                        }
439                        else if(!strncmp(line, "CHAT ", 5))
440                        {
441                                char *id = strchr(line, ' ');
442                                if(++id)
443                                {
444                                        char *info = strchr(id, ' ');
445                                        if(info)
446                                                *info = '\0';
447                                        info++;
448                                        if(!strcmp(info, "STATUS MULTI_SUBSCRIBED"))
449                                        {
450                                                imcb_chat_new( ic, id );
451                                                g_snprintf(buf, 1024, "GET CHAT %s ADDER\n", id);
452                                                skype_write(ic, buf, strlen(buf));
453                                                g_snprintf(buf, 1024, "GET CHAT %s TOPIC\n", id);
454                                                skype_write(ic, buf, strlen(buf));
455                                        }
456                                        else if(!strcmp(info, "STATUS DIALOG") && sd->groupchat_with)
457                                        {
458                                                struct groupchat *gc = imcb_chat_new( ic, id );
459                                                /* According to the docs this
460                                                 * is necessary. However it
461                                                 * does not seem the situation
462                                                 * and it would open an extra
463                                                 * window on our client, so
464                                                 * just leave it out. */
465                                                /*g_snprintf(buf, 1024, "OPEN CHAT %s\n", id);
466                                                skype_write(ic, buf, strlen(buf));*/
467                                                g_snprintf(buf, 1024, "%s@skype.com", sd->groupchat_with);
468                                                imcb_chat_add_buddy(gc, buf);
469                                                imcb_chat_add_buddy(gc, sd->username);
470                                                g_free(sd->groupchat_with);
471                                                sd->groupchat_with = NULL;
472                                                g_snprintf(buf, 1024, "GET CHAT %s ADDER\n", id);
473                                                skype_write(ic, buf, strlen(buf));
474                                                g_snprintf(buf, 1024, "GET CHAT %s TOPIC\n", id);
475                                                skype_write(ic, buf, strlen(buf));
476                                        }
477                                        else if(!strcmp(info, "STATUS UNSUBSCRIBED"))
478                                        {
479                                                struct groupchat *gc = skype_chat_by_name(ic, id);
480                                                if(gc)
481                                                        gc->data = (void*)FALSE;
482                                        }
483                                        else if(!strncmp(info, "ADDER ", 6))
484                                        {
485                                                info += 6;
486                                                g_free(sd->adder);
487                                                sd->adder = g_strdup_printf("%s@skype.com", info);
488                                        }
489                                        else if(!strncmp(info, "TOPIC ", 6))
490                                        {
491                                                info += 6;
492                                                struct groupchat *gc = skype_chat_by_name(ic, id);
493                                                if(gc && (sd->adder || sd->topic_wait))
494                                                {
495                                                        if(sd->topic_wait)
496                                                        {
497                                                                sd->adder = g_strdup(sd->username);
498                                                                sd->topic_wait = 0;
499                                                        }
500                                                        imcb_chat_topic(gc, sd->adder, info, 0);
501                                                        g_free(sd->adder);
502                                                        sd->adder = NULL;
503                                                }
504                                        }
505                                        else if(!strncmp(info, "ACTIVEMEMBERS ", 14))
506                                        {
507                                                info += 14;
508                                                struct groupchat *gc = skype_chat_by_name(ic, id);
509                                                /* Hack! We set ->data to TRUE
510                                                 * while we're on the channel
511                                                 * so that we won't rejoin
512                                                 * after a /part. */
513                                                if(gc && !gc->data)
514                                                {
515                                                        char **members = g_strsplit(info, " ", 0);
516                                                        int i;
517                                                        for(i=0;members[i];i++)
518                                                        {
519                                                                if(!strcmp(members[i], sd->username))
520                                                                        continue;
521                                                                g_snprintf(buf, 1024, "%s@skype.com", members[i]);
522                                                                if(!g_list_find_custom(gc->in_room, buf, (GCompareFunc)strcmp))
523                                                                        imcb_chat_add_buddy(gc, buf);
524                                                        }
525                                                        imcb_chat_add_buddy(gc, sd->username);
526                                                        g_strfreev(members);
527                                                }
528                                        }
529                                }
530                        }
531                        lineptr++;
532                }
533                g_strfreev(lines);
534        }
535        else if( st == 0 || ( st < 0 && !sockerr_again() ) )
536        {
537                closesocket( sd->fd );
538                sd->fd = -1;
539
540                imcb_error( ic, "Error while reading from server" );
541                imc_logout( ic, TRUE );
542                return FALSE;
543        }
544        return TRUE;
545}
546
547gboolean skype_start_stream( struct im_connection *ic )
548{
549        struct skype_data *sd = ic->proto_data;
550        char *buf;
551        int st;
552
553        if(!sd)
554                return FALSE;
555
556        if( sd->bfd <= 0 )
557                sd->bfd = b_input_add( sd->fd, GAIM_INPUT_READ, skype_read_callback, ic );
558
559        /* This will download all buddies. */
560        buf = g_strdup_printf("SEARCH FRIENDS\n");
561        st = skype_write( ic, buf, strlen( buf ) );
562        g_free(buf);
563        buf = g_strdup_printf("SET USERSTATUS ONLINE\n");
564        skype_write( ic, buf, strlen( buf ) );
565        g_free(buf);
566        return st;
567}
568
569gboolean skype_connected( gpointer data, gint source, b_input_condition cond )
570{
571        struct im_connection *ic = data;
572        imcb_connected(ic);
573        return skype_start_stream(ic);
574}
575
576static void skype_login( account_t *acc )
577{
578        struct im_connection *ic = imcb_new( acc );
579        struct skype_data *sd = g_new0( struct skype_data, 1 );
580
581        ic->proto_data = sd;
582
583        imcb_log( ic, "Connecting" );
584        sd->fd = proxy_connect(acc->server, set_getint( &acc->set, "port" ), skype_connected, ic );
585        sd->username = g_strdup( acc->user );
586
587        sd->ic = ic;
588}
589
590static void skype_logout( struct im_connection *ic )
591{
592        struct skype_data *sd = ic->proto_data;
593        char *buf;
594
595        buf = g_strdup_printf("SET USERSTATUS OFFLINE\n");
596        skype_write( ic, buf, strlen( buf ) );
597        g_free(buf);
598
599        g_free(sd->username);
600        g_free(sd->handle);
601        g_free(sd);
602        ic->proto_data = NULL;
603}
604
605static int skype_buddy_msg( struct im_connection *ic, char *who, char *message, int flags )
606{
607        char *buf, *ptr, *nick;
608        int st;
609
610        nick = g_strdup(who);
611        ptr = strchr(nick, '@');
612        if(ptr)
613                *ptr = '\0';
614
615        buf = g_strdup_printf("MESSAGE %s %s\n", nick, message);
616        g_free(nick);
617        st = skype_write( ic, buf, strlen( buf ) );
618        g_free(buf);
619
620        return st;
621}
622
623const struct skype_away_state *skype_away_state_by_name( char *name )
624{
625        int i;
626
627        for( i = 0; skype_away_state_list[i].full_name; i ++ )
628                if( g_strcasecmp( skype_away_state_list[i].full_name, name ) == 0 )
629                        return( skype_away_state_list + i );
630
631        return NULL;
632}
633
634static void skype_set_away( struct im_connection *ic, char *state_txt, char *message )
635{
636        const struct skype_away_state *state;
637        char *buf;
638
639        if( strcmp( state_txt, GAIM_AWAY_CUSTOM ) == 0 )
640                state = skype_away_state_by_name( "Away" );
641        else
642                state = skype_away_state_by_name( state_txt );
643        buf = g_strdup_printf("SET USERSTATUS %s\n", state->code);
644        skype_write( ic, buf, strlen( buf ) );
645        g_free(buf);
646}
647
648static GList *skype_away_states( struct im_connection *ic )
649{
650        static GList *l = NULL;
651        int i;
652       
653        if( l == NULL )
654                for( i = 0; skype_away_state_list[i].full_name; i ++ )
655                        l = g_list_append( l, (void*) skype_away_state_list[i].full_name );
656       
657        return l;
658}
659
660static void skype_add_buddy( struct im_connection *ic, char *who, char *group )
661{
662        char *buf, *nick, *ptr;
663
664        nick = g_strdup(who);
665        ptr = strchr(nick, '@');
666        if(ptr)
667                *ptr = '\0';
668        buf = g_strdup_printf("SET USER %s BUDDYSTATUS 2 Please authorize me\n", nick);
669        skype_write( ic, buf, strlen( buf ) );
670        g_free(nick);
671}
672
673static void skype_remove_buddy( struct im_connection *ic, char *who, char *group )
674{
675        char *buf, *nick, *ptr;
676
677        nick = g_strdup(who);
678        ptr = strchr(nick, '@');
679        if(ptr)
680                *ptr = '\0';
681        buf = g_strdup_printf("SET USER %s BUDDYSTATUS 1\n", nick);
682        skype_write( ic, buf, strlen( buf ) );
683        g_free(nick);
684}
685
686void skype_chat_msg( struct groupchat *gc, char *message, int flags )
687{
688        struct im_connection *ic = gc->ic;
689        char *buf;
690        buf = g_strdup_printf("CHATMESSAGE %s %s\n", gc->title, message);
691        skype_write( ic, buf, strlen( buf ) );
692        g_free(buf);
693}
694
695void skype_chat_leave( struct groupchat *gc )
696{
697        struct im_connection *ic = gc->ic;
698        char *buf;
699        buf = g_strdup_printf("ALTER CHAT %s LEAVE\n", gc->title);
700        skype_write( ic, buf, strlen( buf ) );
701        g_free(buf);
702        gc->data = (void*)TRUE;
703}
704
705void skype_chat_invite(struct groupchat *gc, char *who, char *message)
706{
707        struct im_connection *ic = gc->ic;
708        char *buf, *ptr, *nick;
709        nick = g_strdup(message);
710        ptr = strchr(nick, '@');
711        if(ptr)
712                *ptr = '\0';
713        buf = g_strdup_printf("ALTER CHAT %s ADDMEMBERS %s\n", gc->title, nick);
714        skype_write( ic, buf, strlen( buf ) );
715        g_free(buf);
716        g_free(nick);
717}
718
719void skype_chat_topic(struct groupchat *gc, char *message)
720{
721        struct im_connection *ic = gc->ic;
722        struct skype_data *sd = ic->proto_data;
723        char *buf;
724        buf = g_strdup_printf("ALTER CHAT %s SETTOPIC %s\n", gc->title, message);
725        skype_write( ic, buf, strlen( buf ) );
726        g_free(buf);
727        sd->topic_wait = 1;
728}
729
730struct groupchat *skype_chat_with(struct im_connection *ic, char *who)
731{
732        struct skype_data *sd = ic->proto_data;
733        char *ptr, *nick, *buf;
734        nick = g_strdup(who);
735        ptr = strchr(nick, '@');
736        if(ptr)
737                *ptr = '\0';
738        buf = g_strdup_printf("CHAT CREATE %s\n", nick);
739        skype_write(ic, buf, strlen(buf));
740        g_free(buf);
741        sd->groupchat_with = g_strdup(nick);
742        g_free(nick);
743        return(NULL);
744}
745
746void init_plugin(void)
747{
748        struct prpl *ret = g_new0( struct prpl, 1 );
749
750        ret->name = "skype";
751        ret->login = skype_login;
752        ret->init = skype_init;
753        ret->logout = skype_logout;
754        ret->buddy_msg = skype_buddy_msg;
755        ret->away_states = skype_away_states;
756        ret->set_away = skype_set_away;
757        ret->add_buddy = skype_add_buddy;
758        ret->remove_buddy = skype_remove_buddy;
759        ret->chat_msg = skype_chat_msg;
760        ret->chat_leave = skype_chat_leave;
761        ret->chat_invite = skype_chat_invite;
762        ret->chat_with = skype_chat_with;
763        ret->handle_cmp = g_strcasecmp;
764        ret->chat_topic = skype_chat_topic;
765        register_protocol( ret );
766}
Note: See TracBrowser for help on using the repository browser.