source: skype/skype.c @ 62bb4e4

Last change on this file since 62bb4e4 was 62bb4e4, checked in by VMiklos <vmiklos@…>, at 2007-08-20T18:50:25Z

mark received messages as read so that skype won't say there are unread messages

  • Property mode set to 100644
File size: 7.0 KB
RevLine 
[f06e3ac]1/*
2 * This is the most simple possible BitlBee plugin. To use, compile it as
3 * a shared library and place it in the plugin directory:
4 *
5 * gcc -o example.so -shared example.c `pkg-config --cflags bitlbee`
6 * cp example.so /usr/local/lib/bitlbee
7 */
8#include <stdio.h>
[ed2e37f]9#include <poll.h>
[f06e3ac]10#include <bitlbee.h>
11
12#define SKYPE_PORT_DEFAULT "2727"
13
14struct skype_data
15{
16        struct im_connection *ic;
[a3d6427]17        char *username;
[f06e3ac]18        int fd;
19        char *txq;
20        int tx_len;
21        int r_inpa, w_inpa;
[77c1abe]22        // when we receive a new message id, we query the handle, then the body
23        // store the handle here
24        // TODO: it would be nicer to use a hashmap for this or something
25        char *handle;
[f06e3ac]26};
27
[adce2de]28struct skype_away_state
29{
30        char *code;
31        char *full_name;
32};
33
34const struct skype_away_state skype_away_state_list[] =
35{
36        { "ONLINE",  "Online" },
37        { "SKYPEME",  "Skype Me" },
38        { "AWAY",   "Away" },
39        { "NA",    "Not available" },
40        { "DND",      "Do Not Disturb" },
41        { "INVISIBLE",      "Invisible" },
42        { "OFFLINE",      "Offline" }
43};
44
[f06e3ac]45static void skype_init( account_t *acc )
46{
47        set_t *s;
48
49        s = set_add( &acc->set, "port", SKYPE_PORT_DEFAULT, set_eval_int, acc );
50        s->flags |= ACC_SET_OFFLINE_ONLY;
51
52        s = set_add( &acc->set, "server", NULL, set_eval_account, acc );
53        s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY;
54}
55
56int skype_write( struct im_connection *ic, char *buf, int len )
57{
58        struct skype_data *sd = ic->proto_data;
59
[9fd4241]60        printf("write(): %s", buf);
61        write( sd->fd, buf, len );
[f06e3ac]62
[9fd4241]63        return TRUE;
[f06e3ac]64}
65
[1323e36]66static gboolean skype_read_callback( gpointer data, gint fd, b_input_condition cond )
67{
68        struct im_connection *ic = data;
69        struct skype_data *sd = ic->proto_data;
70        char buf[1024];
71        int st;
[9fd4241]72        char **lines, **lineptr, *line, *ptr;
[1323e36]73
74        if( sd->fd == -1 )
75                return FALSE;
76        st = read( sd->fd, buf, sizeof( buf ) );
77        if( st > 0 )
78        {
79                buf[st] = '\0';
80                printf("read(): '%s'\n", buf);
[9fd4241]81                lines = g_strsplit(buf, "\n", 0);
82                lineptr = lines;
83                while((line = *lineptr))
84                {
85                        if(!strlen(line))
86                                break;
87                        printf("skype_read_callback() new line: '%s'\n", line);
88                        if(!strncmp(line, "USERS ", 6))
89                        {
90                                char **i;
91                                char **nicks;
92
93                                nicks = g_strsplit(line + 6, ", ", 0);
94                                i = nicks;
95                                while(*i)
96                                {
97                                        g_snprintf(buf, 1024, "GET USER %s ONLINESTATUS\n", *i);
98                                        skype_write( ic, buf, strlen( buf ) );
99                                        i++;
100                                }
101                                g_strfreev(nicks);
102                        }
103                        else if(!strncmp(line, "USER ", 5))
104                        {
[adce2de]105                                int flags = 0;
[be975f8]106                                char *status = strrchr(line, ' ');
107                                char *user = strchr(line, ' ');
[adce2de]108                                status++;
[be975f8]109                                ptr = strchr(++user, ' ');
110                                *ptr = '\0';
[a3d6427]111                                if(strcmp(user, sd->username) != 0)
112                                {
113                                        ptr = g_strdup_printf("%s@skype.com", user);
114                                        imcb_add_buddy(ic, ptr, NULL);
115                                        if(strcmp(status, "OFFLINE") != 0)
116                                                flags |= OPT_LOGGED_IN;
117                                        if(strcmp(status, "ONLINE") != 0 && strcmp(status, "SKYPEME") != 0)
118                                                flags |= OPT_AWAY;
119                                        imcb_buddy_status(ic, ptr, flags, NULL, NULL);
120                                        g_free(ptr);
121                                }
[9fd4241]122                        }
[77c1abe]123                        else if(!strncmp(line, "CHATMESSAGE ", 12))
124                        {
125                                char *id = strchr(line, ' ');
126                                if(++id)
127                                {
128                                        char *info = strchr(id, ' ');
129                                        *info = '\0';
130                                        info++;
131                                        if(!strcmp(info, "STATUS RECEIVED"))
132                                        {
133                                                // new message, request its body
134                                                printf("new received message  #%s\n", id);
135                                                g_snprintf(buf, 1024, "GET CHATMESSAGE %s FROM_HANDLE\n", id);
136                                                skype_write( ic, buf, strlen( buf ) );
137                                                g_snprintf(buf, 1024, "GET CHATMESSAGE %s BODY\n", id);
138                                                skype_write( ic, buf, strlen( buf ) );
[62bb4e4]139                                                g_snprintf(buf, 1024, "SET CHATMESSAGE %s SEEN\n", id);
140                                                skype_write( ic, buf, strlen( buf ) );
[77c1abe]141                                        }
142                                        else if(!strncmp(info, "FROM_HANDLE ", 12))
143                                        {
144                                                info += 12;
145                                                // new handle
146                                                sd->handle = g_strdup_printf("%s@skype.com", info);
147                                                printf("new handle: '%s'\n", info);
148                                        }
149                                        else if(!strncmp(info, "BODY ", 5))
150                                        {
151                                                info += 5;
152                                                // new body
153                                                printf("<%s> %s\n", sd->handle, info);
[ed2e37f]154                                                if(sd->handle)
155                                                        imcb_buddy_msg(ic, sd->handle, info, 0, 0);
[77c1abe]156                                                g_free(sd->handle);
157                                                sd->handle = NULL;
158                                        }
159                                }
160                        }
[9fd4241]161                        lineptr++;
162                }
163                g_strfreev(lines);
[1323e36]164        }
165        else if( st == 0 || ( st < 0 && !sockerr_again() ) )
166        {
167                closesocket( sd->fd );
168                sd->fd = -1;
169
170                imcb_error( ic, "Error while reading from server" );
171                imc_logout( ic, TRUE );
172                return FALSE;
173        }
174
175        /* EAGAIN/etc or a successful read. */
176        return TRUE;
177}
178
[f06e3ac]179gboolean skype_start_stream( struct im_connection *ic )
180{
[1323e36]181        struct skype_data *sd = ic->proto_data;
[f06e3ac]182        char *buf;
183        int st;
184
[1323e36]185        if( sd->r_inpa <= 0 )
186                sd->r_inpa = b_input_add( sd->fd, GAIM_INPUT_READ, skype_read_callback, ic );
187
[9fd4241]188        // download buddies
189        buf = g_strdup_printf("SEARCH FRIENDS\n");
[f06e3ac]190        st = skype_write( ic, buf, strlen( buf ) );
191        g_free(buf);
192        return st;
193}
194
195gboolean skype_connected( gpointer data, gint source, b_input_condition cond )
196{
197        struct im_connection *ic = data;
[1323e36]198        struct skype_data *sd = ic->proto_data;
[ed2e37f]199        struct pollfd pfd[1];
[f06e3ac]200
[ed2e37f]201        pfd[0].fd = sd->fd;
202        pfd[0].events = POLLOUT;
203
204        poll(pfd, 1, 1000);
205        if(pfd[0].revents & POLLHUP)
[1323e36]206        {
207                imcb_error( ic, "Could not connect to server" );
208                imc_logout( ic, TRUE );
[9fd4241]209                return FALSE;
[1323e36]210        }
[ed2e37f]211        imcb_connected(ic);
[f06e3ac]212        return skype_start_stream(ic);
213}
214
215static void skype_login( account_t *acc )
216{
217        struct im_connection *ic = imcb_new( acc );
218        struct skype_data *sd = g_new0( struct skype_data, 1 );
219
220        ic->proto_data = sd;
221
222        imcb_log( ic, "Connecting" );
223        printf("%s:%d\n", acc->server, set_getint( &acc->set, "port"));
224        sd->fd = proxy_connect(acc->server, set_getint( &acc->set, "port" ), skype_connected, ic );
225        printf("sd->fd: %d\n", sd->fd);
[77c1abe]226        /*imcb_add_buddy(ic, "test@skype.com", NULL);
227        imcb_buddy_status(ic, "test@skype.com", OPT_LOGGED_IN, NULL, NULL);
228        imcb_buddy_msg(ic, "test@skype.com", "test from skype plugin", 0, 0);*/
[a3d6427]229        sd->username = g_strdup( acc->user );
[f06e3ac]230
231        sd->ic = ic;
232}
233
234static void skype_logout( struct im_connection *ic )
235{
236        struct skype_data *sd = ic->proto_data;
[a3d6427]237        g_free(sd->username);
[f06e3ac]238        g_free(sd);
239}
240
[93ece66]241static int skype_buddy_msg( struct im_connection *ic, char *who, char *message, int flags )
242{
[77c1abe]243        char *buf, *ptr, *nick;
[93ece66]244        int st;
245
[77c1abe]246        nick = g_strdup_printf("%s", who);
247        ptr = strchr(nick, '@');
[0bb1b7f]248        if(ptr)
249                *ptr = '\0';
[93ece66]250
[77c1abe]251        buf = g_strdup_printf("MESSAGE %s %s\n", nick, message);
252        g_free(nick);
[93ece66]253        st = skype_write( ic, buf, strlen( buf ) );
254        g_free(buf);
255
256        return st;
257}
258
[f06e3ac]259static void skype_set_away( struct im_connection *ic, char *state_txt, char *message )
260{
261}
262
263static GList *skype_away_states( struct im_connection *ic )
264{
265        static GList *l = NULL;
[adce2de]266        int i;
267       
268        if( l == NULL )
269                for( i = 0; skype_away_state_list[i].full_name; i ++ )
270                        l = g_list_append( l, (void*) skype_away_state_list[i].full_name );
271       
[f06e3ac]272        return l;
273}
274
275static void skype_add_buddy( struct im_connection *ic, char *who, char *group )
276{
277}
278
279static void skype_remove_buddy( struct im_connection *ic, char *who, char *group )
280{
281}
282
283void init_plugin(void)
284{
285        struct prpl *ret = g_new0( struct prpl, 1 );
286
287        ret->name = "skype";
288        ret->login = skype_login;
289        ret->init = skype_init;
290        ret->logout = skype_logout;
[93ece66]291        ret->buddy_msg = skype_buddy_msg;
[f06e3ac]292        ret->away_states = skype_away_states;
293        ret->add_buddy = skype_add_buddy;
294        ret->remove_buddy = skype_remove_buddy;
295        ret->away_states = skype_away_states;
296        ret->set_away = skype_set_away;
297        ret->handle_cmp = g_strcasecmp;
298        register_protocol( ret );
299}
Note: See TracBrowser for help on using the repository browser.