ICQ status messages may have a redundant "Available" from the status name.
[thrasher.git] / thblist.c
blob901910c3473c0a5ae71f5dea10dad8b501e39abf
1 /*
2 * Thrasher Bird - XMPP transport via libpurple
3 * Copyright (C) 2008 Barracuda Networks, Inc.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with Thrasher Bird; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
19 #include <stdlib.h>
20 #include "blist.h"
21 #include "thperl.h"
22 #include "thrasher.h"
23 #include "thblist.h"
24 #include "status.h"
26 #include <server.h>
27 #include <account.h>
29 void thrasher_buddy_status_changed (PurpleBuddy *buddy, PurpleStatus *old,
30 PurpleStatus *new);
31 void thrasher_buddy_signed_on (PurpleBuddy *buddy);
32 void thrasher_buddy_signed_off (PurpleBuddy *buddy);
33 void thrasher_buddy_added (PurpleBuddy *buddy);
34 void thrasher_buddy_add_request (PurpleAccount *account, const char *remote_user,
35 const char *id, const char *alias,
36 const char *message);
37 static void * thrasher_buddy_request_authorize
38 (PurpleAccount *account,
39 const char *remote_user,
40 const char *id,
41 const char *alias,
42 const char *message,
43 gboolean on_list,
44 PurpleAccountRequestAuthorizationCb authorize_cb,
45 PurpleAccountRequestAuthorizationCb deny_cb,
46 void *user_data);
47 void thrasher_buddy_removed (PurpleBuddy *buddy);
48 static gpointer thrasher_blist_get_handle (void);
49 static char* status_text_for_buddy(PurpleBuddy *buddy, PurpleStatus *status);
51 static PurpleAccountUiOps thrasher_account_uiops =
53 // notify added
54 thrasher_buddy_add_request,
56 // status changed
57 NULL,
59 // request add
60 thrasher_buddy_add_request,
62 // request_authorize
63 thrasher_buddy_request_authorize,
65 // close_account_request
66 NULL,
67 // save_node
68 NULL,
69 // remove_node
70 NULL,
71 // save_account
72 NULL,
73 // Reserved
74 NULL
77 struct _PurpleStatusType
79 PurpleStatusPrimitive primitive;
81 char *id;
82 char *name;
83 char *primary_attr_id;
85 gboolean saveable;
86 gboolean user_settable;
87 gboolean independent;
89 GList *attrs;
93 struct _PurpleStatus
95 struct _PurpleStatusType *type;
96 PurplePresence *presence;
98 const char *title;
100 gboolean active;
102 GHashTable *attr_values;
106 * @brief This is the callback for the buddy-status-changed signal
107 * @param buddy PurpleBuddy struct
108 * @param old (unused)
109 * @param new @buddy new PurpleStatus
111 void thrasher_buddy_status_changed (PurpleBuddy *buddy,
112 PurpleStatus *old,
113 PurpleStatus *new)
115 PurpleGroup *group;
116 const char *group_name = NULL;
117 const char *alias = NULL;
119 g_return_if_fail(buddy != NULL);
120 g_return_if_fail(new != NULL);
122 group = purple_buddy_get_group(buddy);
124 if (group)
125 group_name = purple_group_get_name(group);
127 alias = purple_buddy_get_alias_only(buddy);
129 char* message = status_text_for_buddy(buddy, new);
130 if (! message) {
131 message = g_strdup(purple_status_get_attr_string(new, "message"));
134 thrasher_wrapper_presence_in(thrasher_account_get_jid(buddy->account),
135 purple_buddy_get_name(buddy),
136 alias,
137 group_name,
138 purple_status_type_get_primitive(new->type),
139 message);
140 g_free(message);
143 /* Returns a string that becomes owned by the caller or NULL. */
144 static char*
145 status_text_for_buddy(PurpleBuddy *buddy,
146 PurpleStatus *status) {
147 if (! buddy) {
148 return NULL;
150 if (! buddy->account->gc) {
151 return NULL;
154 const char *prpl_id = purple_account_get_protocol_id(buddy->account);
155 if (prpl_id) {
156 PurplePlugin *prpl = purple_find_prpl(prpl_id);
157 if (prpl) {
158 PurplePluginProtocolInfo *prpl_info
159 = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
160 if (prpl_info && prpl_info->status_text) {
161 char* status_text = prpl_info->status_text(buddy);
162 if (status && status_text
163 && purple_status_is_available(status)
164 && 0 == strcmp(prpl_id, "prpl-icq")
165 && 0 == strcmp(status_text,
166 purple_status_get_name(status))) {
167 /* The oscar prpl's status_text tries to suppress
168 * a redundant "Available" message, but won't if
169 * it's in the message attribute instead of the
170 * status name. libpurple's initial log on does
171 * not set this in the message, but subsequent
172 * status changes will.
174 status_text = g_strdup("");
176 return status_text;
180 return NULL;
182 void thrasher_buddy_authorize (const char *jid,
183 const char *legacy_username) {
184 g_return_if_fail(jid);
185 g_return_if_fail(legacy_username);
187 PurpleAccount *account = thrasher_get_account_by_jid(jid);
188 g_return_if_fail(account);
190 PurpleConnection *gc =
191 thrasher_get_connection_by_account(account);
192 g_return_if_fail(gc);
194 purple_debug_info("thrasher", "Authorizing %s for jid %s\n",
195 legacy_username, jid);
197 // defensive; probably only add_permit is necesary
198 serv_rem_deny(gc, legacy_username);
200 serv_add_permit(gc, legacy_username);
203 void thrasher_buddy_deauthorize (const char *jid,
204 const char *legacy_username) {
205 g_return_if_fail(jid);
206 g_return_if_fail(legacy_username);
208 PurpleAccount *account = thrasher_get_account_by_jid(jid);
209 g_return_if_fail(account);
211 PurpleConnection *gc =
212 thrasher_get_connection_by_account(account);
213 g_return_if_fail(gc);
215 purple_debug_info("thrasher", "Deauthorizing %s for jid %s\n",
216 legacy_username, jid);
218 // no corresponding deny, we don't have a reperesentation for that
219 serv_rem_permit(gc, legacy_username);
222 void thrasher_buddy_signed_on (PurpleBuddy *buddy)
224 PurplePresence *presence;
226 presence = purple_buddy_get_presence(buddy);
228 if (!presence)
229 return;
231 // libpurple uses this to populate some stuff about the
232 // buddy, particularly useful for XMPP file transfers but
233 // probably the cause of random other errors if we don't fill this
234 // out.
235 PurpleAccount* account = buddy->account;
236 g_return_if_fail(account);
237 PurpleConnection* connection = thrasher_connection_for_account(account);
238 g_return_if_fail(connection);
240 purple_debug_info("thblist",
241 "getting server info for %s\n\n---------\n\n",
242 buddy->name);
243 serv_get_info(connection, buddy->name);
245 /* Currently active status may be PURPLE_STATUS_UNAVAILABLE
246 * (translates XMPP dnd) instead of just "available".
248 PurpleStatus *status = purple_presence_get_active_status(presence);
250 thrasher_buddy_status_changed(buddy,
251 NULL,
252 status);
255 void thrasher_buddy_signed_off (PurpleBuddy *buddy)
257 PurplePresence *presence;
259 presence = purple_buddy_get_presence(buddy);
261 if (!presence)
262 return;
264 thrasher_buddy_status_changed(buddy,
265 NULL,
266 purple_presence_get_status(presence, "offline"));
269 static void * thrasher_buddy_request_authorize
270 (PurpleAccount *account,
271 const char *remote_user,
272 const char *id,
273 const char *alias,
274 const char *message,
275 gboolean on_list,
276 PurpleAccountRequestAuthorizationCb authorize_cb,
277 PurpleAccountRequestAuthorizationCb deny_cb,
278 void *user_data) {
279 // authorize_cb sometimes NULL?!?
280 purple_debug_info("thrasher", "request authorize, empty cb: %s\n",
281 authorize_cb ? "FALSE" : "TRUE");
282 thrasher_buddy_add_request(account, remote_user, "", alias, message);
284 if (authorize_cb) {
285 authorize_cb(user_data);
288 void *uihandle = NULL;
289 return uihandle;
292 /* thrasher_buddy_add_request
294 * Triggered on a buddy-added signal, this allows us to push new subscriptions.
297 void thrasher_buddy_added (PurpleBuddy *buddy) {
298 PurplePresence *presence = purple_buddy_get_presence(buddy);
299 PurpleStatus *status = purple_presence_get_active_status(presence);
300 PurpleStatusType *type = purple_status_get_type(status);
302 const char *jid = thrasher_account_get_jid(buddy->account);
303 const char *sender = purple_buddy_get_name(buddy);
304 const guint status_int = purple_status_type_get_primitive(type);
306 purple_debug_info("thrasher",
307 "buddy added to %s: %s\n",
308 jid, sender);
310 thrasher_wrapper_subscription_add(jid, sender, status_int);
314 void thrasher_buddy_add_request (PurpleAccount *account, const char *remote_user,
315 const char *id, const char *alias,
316 const char *message)
318 const char *jid = thrasher_account_get_jid(account);
319 purple_debug_info("thrasher",
320 "legacy user %s aka %s added %s to roster\n",
321 remote_user, alias, jid);
322 thrasher_wrapper_legacy_user_add_user(jid, remote_user);
326 void thrasher_buddy_removed (PurpleBuddy *buddy)
328 /* printf("Removed buddy:\t[%s]\t[%s]\n", purple_buddy_get_name(buddy),
329 * purple_status_get_name( purple_presence_get_active_status( purple_buddy_get_presence(buddy) ) )
330 * );
332 PurplePresence *presence = purple_buddy_get_presence(buddy);
333 PurpleStatus *status = purple_presence_get_active_status(presence);
334 PurpleStatusType *type = purple_status_get_type(status);
335 PurpleGroup *group = purple_buddy_get_group(buddy);
337 * Need to fire jid, sender, group_name, alias, and status back to perl */
339 // jid = thrasher_account_get_jid(buddy->account)
340 // sender = purple_buddy_get_name(buddy)
341 // group_name = purple_group_get_name(group)
342 // alias = purple_buddy_get_alias_only(buddy)
343 // status = purple_status_type_get_primitive(type)
347 static gpointer
348 thrasher_blist_get_handle ()
350 static int handle;
351 return &handle;
355 void thrasher_blist_init()
357 purple_accounts_set_ui_ops(&thrasher_account_uiops);
359 purple_signal_connect(purple_blist_get_handle(),
360 "buddy-status-changed",
361 thrasher_blist_get_handle(),
362 PURPLE_CALLBACK(thrasher_buddy_status_changed),
363 NULL);
365 purple_signal_connect(purple_blist_get_handle(),
366 "buddy-signed-on",
367 thrasher_blist_get_handle(),
368 PURPLE_CALLBACK(thrasher_buddy_signed_on),
369 NULL);
371 purple_signal_connect(purple_blist_get_handle(),
372 "buddy-signed-off",
373 thrasher_blist_get_handle(),
374 PURPLE_CALLBACK(thrasher_buddy_signed_off),
375 NULL);
377 // It looks like this only comes in for things already on our roster.
378 purple_signal_connect(purple_blist_get_handle(),
379 "buddy-added",
380 thrasher_blist_get_handle(),
381 PURPLE_CALLBACK(thrasher_buddy_added),
382 NULL);
385 purple_signal_connect(purple_blist_get_handle(),
386 "buddy-removed",
387 thrasher_blist_get_handle(),
388 PURPLE_CALLBACK(thrasher_buddy_removed),
389 NULL);