4 * Purple is the legal property of its developers, whose names are too numerous
5 * to list here. Please refer to the COPYRIGHT file distributed with this
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.
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.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
24 /* This file is the fullcrap */
28 #include "conversation.h"
41 #define SECS_BEFORE_RESENDING_AUTORESPONSE 600
42 #define SEX_BEFORE_RESENDING_AUTORESPONSE "Only after you're married"
45 serv_send_typing(PurpleConnection
*gc
, const char *name
, PurpleTypingState state
)
48 PurplePluginProtocolInfo
*prpl_info
;
51 prpl
= purple_connection_get_prpl(gc
);
52 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
54 if (prpl_info
->send_typing
)
55 return prpl_info
->send_typing(gc
, name
, state
);
61 static GSList
*last_auto_responses
= NULL
;
62 struct last_auto_response
{
69 expire_last_auto_responses(gpointer data
)
72 struct last_auto_response
*lar
;
74 tmp
= last_auto_responses
;
79 lar
= (struct last_auto_response
*)cur
->data
;
81 if ((time(NULL
) - lar
->sent
) > SECS_BEFORE_RESENDING_AUTORESPONSE
) {
82 last_auto_responses
= g_slist_remove(last_auto_responses
, lar
);
87 return FALSE
; /* do not run again */
90 static struct last_auto_response
*
91 get_last_auto_response(PurpleConnection
*gc
, const char *name
)
94 struct last_auto_response
*lar
;
96 /* because we're modifying or creating a lar, schedule the
97 * function to expire them as the pref dictates */
98 purple_timeout_add_seconds((SECS_BEFORE_RESENDING_AUTORESPONSE
+ 1), expire_last_auto_responses
, NULL
);
100 tmp
= last_auto_responses
;
103 lar
= (struct last_auto_response
*)tmp
->data
;
105 if (gc
== lar
->gc
&& !strncmp(name
, lar
->name
, sizeof(lar
->name
)))
111 lar
= (struct last_auto_response
*)g_new0(struct last_auto_response
, 1);
112 g_snprintf(lar
->name
, sizeof(lar
->name
), "%s", name
);
115 last_auto_responses
= g_slist_prepend(last_auto_responses
, lar
);
120 int serv_send_im(PurpleConnection
*gc
, const char *name
, const char *message
,
121 PurpleMessageFlags flags
)
123 PurpleConversation
*conv
= NULL
;
124 PurpleAccount
*account
= NULL
;
125 PurplePresence
*presence
= NULL
;
126 PurplePlugin
*prpl
= NULL
;
127 PurplePluginProtocolInfo
*prpl_info
= NULL
;
129 const gchar
*auto_reply_pref
= NULL
;
131 g_return_val_if_fail(gc
!= NULL
, val
);
133 prpl
= purple_connection_get_prpl(gc
);
135 g_return_val_if_fail(prpl
!= NULL
, val
);
137 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
139 account
= purple_connection_get_account(gc
);
140 presence
= purple_account_get_presence(account
);
142 conv
= purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM
, name
, account
);
144 if (prpl_info
->send_im
)
145 val
= prpl_info
->send_im(gc
, name
, message
, flags
);
148 * XXX - If "only auto-reply when away & idle" is set, then shouldn't
149 * this only reset lar->sent if we're away AND idle?
151 auto_reply_pref
= purple_prefs_get_string("/purple/away/auto_reply");
152 if((gc
->flags
& PURPLE_CONNECTION_AUTO_RESP
) &&
153 !purple_presence_is_available(presence
) &&
154 !purple_strequal(auto_reply_pref
, "never")) {
156 struct last_auto_response
*lar
;
157 lar
= get_last_auto_response(gc
, name
);
158 lar
->sent
= time(NULL
);
161 if(conv
&& purple_conv_im_get_send_typed_timeout(PURPLE_CONV_IM(conv
)))
162 purple_conv_im_stop_send_typed_timeout(PURPLE_CONV_IM(conv
));
167 void serv_get_info(PurpleConnection
*gc
, const char *name
)
170 PurplePluginProtocolInfo
*prpl_info
;
173 prpl
= purple_connection_get_prpl(gc
);
174 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
176 if (prpl_info
->get_info
)
177 prpl_info
->get_info(gc
, name
);
181 void serv_set_info(PurpleConnection
*gc
, const char *info
)
184 PurplePluginProtocolInfo
*prpl_info
;
185 PurpleAccount
*account
;
188 prpl
= purple_connection_get_prpl(gc
);
189 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
191 if (prpl_info
->set_info
) {
192 account
= purple_connection_get_account(gc
);
194 if (purple_signal_emit_return_1(purple_accounts_get_handle(),
195 "account-setting-info", account
, info
))
198 prpl_info
->set_info(gc
, info
);
200 purple_signal_emit(purple_accounts_get_handle(),
201 "account-set-info", account
, info
);
207 * Set buddy's alias on server roster/list
209 void serv_alias_buddy(PurpleBuddy
*b
)
211 PurpleAccount
*account
;
212 PurpleConnection
*gc
;
214 PurplePluginProtocolInfo
*prpl_info
;
217 account
= purple_buddy_get_account(b
);
220 gc
= purple_account_get_connection(account
);
223 prpl
= purple_connection_get_prpl(gc
);
224 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
226 if (prpl_info
->alias_buddy
)
227 prpl_info
->alias_buddy(gc
,
228 purple_buddy_get_name(b
),
229 purple_buddy_get_local_buddy_alias(b
));
236 serv_got_alias(PurpleConnection
*gc
, const char *who
, const char *alias
)
238 PurpleAccount
*account
;
241 PurpleConversation
*conv
;
243 account
= purple_connection_get_account(gc
);
244 buddies
= purple_find_buddies(account
, who
);
246 while (buddies
!= NULL
)
248 const char *server_alias
;
251 buddies
= g_slist_delete_link(buddies
, buddies
);
253 server_alias
= purple_buddy_get_server_alias(b
);
255 if (purple_strequal(server_alias
, alias
))
258 purple_blist_server_alias_buddy(b
, alias
);
260 conv
= purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM
, purple_buddy_get_name(b
), account
);
261 if (conv
!= NULL
&& alias
!= NULL
&& !purple_strequal(alias
, who
))
263 char *escaped
= g_markup_escape_text(who
, -1);
264 char *escaped2
= g_markup_escape_text(alias
, -1);
265 char *tmp
= g_strdup_printf(_("%s is now known as %s.\n"),
268 purple_conversation_write(conv
, NULL
, tmp
,
269 PURPLE_MESSAGE_SYSTEM
| PURPLE_MESSAGE_NO_LINKIFY
,
280 purple_serv_got_private_alias(PurpleConnection
*gc
, const char *who
, const char *alias
)
282 PurpleAccount
*account
= NULL
;
283 GSList
*buddies
= NULL
;
284 PurpleBuddy
*b
= NULL
;
286 account
= purple_connection_get_account(gc
);
287 buddies
= purple_find_buddies(account
, who
);
289 while(buddies
!= NULL
) {
293 buddies
= g_slist_delete_link(buddies
, buddies
);
295 balias
= purple_buddy_get_local_buddy_alias(b
);
296 if (purple_strequal(balias
, alias
))
299 purple_blist_alias_buddy(b
, alias
);
304 PurpleAttentionType
*purple_get_attention_type_from_code(PurpleAccount
*account
, guint type_code
)
307 PurpleAttentionType
* attn
;
308 GList
*(*get_attention_types
)(PurpleAccount
*);
310 g_return_val_if_fail(account
!= NULL
, NULL
);
312 prpl
= purple_find_prpl(purple_account_get_protocol_id(account
));
314 /* Lookup the attention type in the protocol's attention_types list, if any. */
315 get_attention_types
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
)->get_attention_types
;
316 if (get_attention_types
) {
317 GList
*attention_types
;
319 attention_types
= get_attention_types(account
);
320 attn
= (PurpleAttentionType
*)g_list_nth_data(attention_types
, type_code
);
329 serv_send_attention(PurpleConnection
*gc
, const char *who
, guint type_code
)
331 purple_prpl_send_attention(gc
, who
, type_code
);
335 serv_got_attention(PurpleConnection
*gc
, const char *who
, guint type_code
)
337 purple_prpl_got_attention(gc
, who
, type_code
);
342 * Move a buddy from one group to another on server.
344 * Note: For now we'll not deal with changing gc's at the same time, but
345 * it should be possible. Probably needs to be done, someday. Although,
346 * the UI for that would be difficult, because groups are Purple-wide.
348 void serv_move_buddy(PurpleBuddy
*b
, PurpleGroup
*og
, PurpleGroup
*ng
)
350 PurpleAccount
*account
;
351 PurpleConnection
*gc
;
353 PurplePluginProtocolInfo
*prpl_info
;
355 g_return_if_fail(b
!= NULL
);
356 g_return_if_fail(og
!= NULL
);
357 g_return_if_fail(ng
!= NULL
);
359 account
= purple_buddy_get_account(b
);
360 gc
= purple_account_get_connection(account
);
363 prpl
= purple_connection_get_prpl(gc
);
364 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
366 if (prpl_info
->group_buddy
)
367 prpl_info
->group_buddy(gc
, purple_buddy_get_name(b
),
368 purple_group_get_name(og
),
369 purple_group_get_name(ng
));
373 void serv_add_permit(PurpleConnection
*gc
, const char *name
)
376 PurplePluginProtocolInfo
*prpl_info
;
379 prpl
= purple_connection_get_prpl(gc
);
380 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
382 if (prpl_info
->add_permit
)
383 prpl_info
->add_permit(gc
, name
);
387 void serv_add_deny(PurpleConnection
*gc
, const char *name
)
390 PurplePluginProtocolInfo
*prpl_info
;
393 prpl
= purple_connection_get_prpl(gc
);
394 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
396 if (prpl_info
->add_deny
)
397 prpl_info
->add_deny(gc
, name
);
401 void serv_rem_permit(PurpleConnection
*gc
, const char *name
)
404 PurplePluginProtocolInfo
*prpl_info
;
407 prpl
= purple_connection_get_prpl(gc
);
408 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
410 if (prpl_info
->rem_permit
)
411 prpl_info
->rem_permit(gc
, name
);
415 void serv_rem_deny(PurpleConnection
*gc
, const char *name
)
418 PurplePluginProtocolInfo
*prpl_info
;
421 prpl
= purple_connection_get_prpl(gc
);
422 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
424 if (prpl_info
->rem_deny
)
425 prpl_info
->rem_deny(gc
, name
);
429 void serv_set_permit_deny(PurpleConnection
*gc
)
432 PurplePluginProtocolInfo
*prpl_info
;
435 prpl
= purple_connection_get_prpl(gc
);
436 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
439 * this is called when either you import a buddy list, and make lots
440 * of changes that way, or when the user toggles the permit/deny mode
441 * in the prefs. In either case you should probably be resetting and
442 * resending the permit/deny info when you get this.
444 if (prpl_info
->set_permit_deny
)
445 prpl_info
->set_permit_deny(gc
);
449 void serv_join_chat(PurpleConnection
*gc
, GHashTable
*data
)
452 PurplePluginProtocolInfo
*prpl_info
;
455 prpl
= purple_connection_get_prpl(gc
);
456 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
458 if (prpl_info
->join_chat
)
459 prpl_info
->join_chat(gc
, data
);
464 void serv_reject_chat(PurpleConnection
*gc
, GHashTable
*data
)
467 PurplePluginProtocolInfo
*prpl_info
;
470 prpl
= purple_connection_get_prpl(gc
);
471 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
473 if (prpl_info
->reject_chat
)
474 prpl_info
->reject_chat(gc
, data
);
478 void serv_chat_invite(PurpleConnection
*gc
, int id
, const char *message
, const char *name
)
480 PurplePlugin
*prpl
= NULL
;
481 PurplePluginProtocolInfo
*prpl_info
= NULL
;
482 PurpleConversation
*conv
;
483 char *buffy
= message
&& *message
? g_strdup(message
) : NULL
;
485 conv
= purple_find_chat(gc
, id
);
491 prpl
= purple_connection_get_prpl(gc
);
494 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
496 purple_signal_emit(purple_conversations_get_handle(), "chat-inviting-user",
499 if (prpl_info
&& prpl_info
->chat_invite
)
500 prpl_info
->chat_invite(gc
, id
, buffy
, name
);
502 purple_signal_emit(purple_conversations_get_handle(), "chat-invited-user",
508 /* Ya know, nothing uses this except purple_conversation_destroy(),
509 * I think I'll just merge it into that later...
510 * Then again, something might want to use this, from outside prpl-land
511 * to leave a chat without destroying the conversation.
513 void serv_chat_leave(PurpleConnection
*gc
, int id
)
516 PurplePluginProtocolInfo
*prpl_info
;
518 prpl
= purple_connection_get_prpl(gc
);
519 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
521 if (prpl_info
->chat_leave
)
522 prpl_info
->chat_leave(gc
, id
);
525 void serv_chat_whisper(PurpleConnection
*gc
, int id
, const char *who
, const char *message
)
528 PurplePluginProtocolInfo
*prpl_info
;
531 prpl
= purple_connection_get_prpl(gc
);
532 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
534 if (prpl_info
->chat_whisper
)
535 prpl_info
->chat_whisper(gc
, id
, who
, message
);
539 int serv_chat_send(PurpleConnection
*gc
, int id
, const char *message
, PurpleMessageFlags flags
)
542 PurplePluginProtocolInfo
*prpl_info
;
544 prpl
= purple_connection_get_prpl(gc
);
545 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
547 if (prpl_info
->chat_send
)
548 return prpl_info
->chat_send(gc
, id
, message
, flags
);
554 * woo. i'm actually going to comment this function. isn't that fun. make
555 * sure to follow along, kids
557 void serv_got_im(PurpleConnection
*gc
, const char *who
, const char *msg
,
558 PurpleMessageFlags flags
, time_t mtime
)
560 PurpleAccount
*account
;
561 PurpleConversation
*conv
;
562 char *message
, *name
;
566 g_return_if_fail(msg
!= NULL
);
568 account
= purple_connection_get_account(gc
);
571 purple_debug_error("server",
572 "serv_got_im ignoring negative timestamp\n");
573 /* TODO: Would be more appropriate to use a value that indicates
574 that the timestamp is unknown, and surface that in the UI. */
579 * XXX: Should we be setting this here, or relying on prpls to set it?
581 flags
|= PURPLE_MESSAGE_RECV
;
583 if (!purple_privacy_check(account
, who
)) {
584 purple_signal_emit(purple_conversations_get_handle(), "blocked-im-msg",
585 account
, who
, msg
, flags
, (unsigned int)mtime
);
590 * We should update the conversation window buttons and menu,
593 conv
= purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM
, who
, gc
->account
);
596 * Make copies of the message and the sender in case plugins want
597 * to free these strings and replace them with a modifed version.
599 buffy
= g_strdup(msg
);
600 angel
= g_strdup(who
);
602 plugin_return
= GPOINTER_TO_INT(
603 purple_signal_emit_return_1(purple_conversations_get_handle(),
604 "receiving-im-msg", gc
->account
,
605 &angel
, &buffy
, conv
, &flags
));
607 if (!buffy
|| !angel
|| plugin_return
) {
616 purple_signal_emit(purple_conversations_get_handle(), "received-im-msg", gc
->account
,
617 name
, message
, conv
, flags
);
619 /* search for conversation again in case it was created by received-im-msg handler */
621 conv
= purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM
, name
, gc
->account
);
624 conv
= purple_conversation_new(PURPLE_CONV_TYPE_IM
, account
, name
);
626 purple_conv_im_write(PURPLE_CONV_IM(conv
), name
, message
, flags
, mtime
);
630 * Don't autorespond if:
632 * - it's not supported on this connection
635 * - or we're not idle and the 'only auto respond if idle' pref
638 if (gc
->flags
& PURPLE_CONNECTION_AUTO_RESP
)
640 PurplePresence
*presence
;
641 PurpleStatus
*status
;
642 PurpleStatusType
*status_type
;
643 PurpleStatusPrimitive primitive
;
644 const gchar
*auto_reply_pref
;
645 const char *away_msg
= NULL
;
646 gboolean mobile
= FALSE
;
648 auto_reply_pref
= purple_prefs_get_string("/purple/away/auto_reply");
650 presence
= purple_account_get_presence(account
);
651 status
= purple_presence_get_active_status(presence
);
652 status_type
= purple_status_get_type(status
);
653 primitive
= purple_status_type_get_primitive(status_type
);
654 mobile
= purple_presence_is_status_primitive_active(presence
, PURPLE_STATUS_MOBILE
);
655 if ((primitive
== PURPLE_STATUS_AVAILABLE
) ||
656 (primitive
== PURPLE_STATUS_INVISIBLE
) ||
658 purple_strequal(auto_reply_pref
, "never") ||
659 (!purple_presence_is_idle(presence
) && purple_strequal(auto_reply_pref
, "awayidle")))
665 away_msg
= purple_value_get_string(
666 purple_status_get_attr_value(status
, "message"));
668 if ((away_msg
!= NULL
) && (*away_msg
!= '\0')) {
669 struct last_auto_response
*lar
;
670 time_t now
= time(NULL
);
673 * This used to be based on the conversation window. But um, if
674 * you went away, and someone sent you a message and got your
675 * auto-response, and then you closed the window, and then they
676 * sent you another one, they'd get the auto-response back too
677 * soon. Besides that, we need to keep track of this even if we've
678 * got a queue. So the rest of this block is just the auto-response,
681 lar
= get_last_auto_response(gc
, name
);
682 if ((now
- lar
->sent
) >= SECS_BEFORE_RESENDING_AUTORESPONSE
)
685 * We don't want to send an autoresponse in response to the other user's
686 * autoresponse. We do, however, not want to then send one in response to the
687 * _next_ message, so we still set lar->sent to now.
691 if (!(flags
& PURPLE_MESSAGE_AUTO_RESP
))
693 serv_send_im(gc
, name
, away_msg
, PURPLE_MESSAGE_AUTO_RESP
);
695 purple_conv_im_write(PURPLE_CONV_IM(conv
), NULL
, away_msg
,
696 PURPLE_MESSAGE_SEND
| PURPLE_MESSAGE_AUTO_RESP
,
706 void serv_got_typing(PurpleConnection
*gc
, const char *name
, int timeout
,
707 PurpleTypingState state
) {
708 PurpleConversation
*conv
;
709 PurpleConvIm
*im
= NULL
;
711 conv
= purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM
, name
, gc
->account
);
713 im
= PURPLE_CONV_IM(conv
);
715 purple_conv_im_set_typing_state(im
, state
);
720 purple_signal_emit(purple_conversations_get_handle(),
721 "buddy-typing", gc
->account
, name
);
724 purple_signal_emit(purple_conversations_get_handle(),
725 "buddy-typed", gc
->account
, name
);
727 case PURPLE_NOT_TYPING
:
728 purple_signal_emit(purple_conversations_get_handle(),
729 "buddy-typing-stopped", gc
->account
, name
);
734 if (conv
!= NULL
&& timeout
> 0)
735 purple_conv_im_start_typing_timeout(im
, timeout
);
738 void serv_got_typing_stopped(PurpleConnection
*gc
, const char *name
) {
740 PurpleConversation
*conv
;
743 conv
= purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM
, name
, gc
->account
);
746 im
= PURPLE_CONV_IM(conv
);
748 if (im
->typing_state
== PURPLE_NOT_TYPING
)
751 purple_conv_im_stop_typing_timeout(im
);
752 purple_conv_im_set_typing_state(im
, PURPLE_NOT_TYPING
);
756 purple_signal_emit(purple_conversations_get_handle(),
757 "buddy-typing-stopped", gc
->account
, name
);
761 struct chat_invite_data
{
762 PurpleConnection
*gc
;
763 GHashTable
*components
;
766 static void chat_invite_data_free(struct chat_invite_data
*cid
)
769 g_hash_table_destroy(cid
->components
);
774 static void chat_invite_reject(struct chat_invite_data
*cid
)
776 serv_reject_chat(cid
->gc
, cid
->components
);
777 chat_invite_data_free(cid
);
781 static void chat_invite_accept(struct chat_invite_data
*cid
)
783 serv_join_chat(cid
->gc
, cid
->components
);
784 chat_invite_data_free(cid
);
789 void serv_got_chat_invite(PurpleConnection
*gc
, const char *name
,
790 const char *who
, const char *message
, GHashTable
*data
)
792 PurpleAccount
*account
;
794 struct chat_invite_data
*cid
;
797 g_return_if_fail(name
!= NULL
);
798 g_return_if_fail(who
!= NULL
);
800 account
= purple_connection_get_account(gc
);
801 if (!purple_privacy_check(account
, who
)) {
802 purple_signal_emit(purple_conversations_get_handle(), "chat-invite-blocked",
803 account
, who
, name
, message
, data
);
807 cid
= g_new0(struct chat_invite_data
, 1);
809 plugin_return
= GPOINTER_TO_INT(purple_signal_emit_return_1(
810 purple_conversations_get_handle(),
811 "chat-invited", account
, who
, name
, message
, data
));
814 cid
->components
= data
;
816 if (plugin_return
== 0)
820 g_snprintf(buf2
, sizeof(buf2
),
821 _("%s has invited %s to the chat room %s:\n%s"),
822 who
, purple_account_get_username(account
), name
, message
);
825 g_snprintf(buf2
, sizeof(buf2
),
826 _("%s has invited %s to the chat room %s\n"),
827 who
, purple_account_get_username(account
), name
);
830 purple_request_accept_cancel(gc
, NULL
, _("Accept chat invitation?"), buf2
,
831 PURPLE_DEFAULT_ACTION_NONE
, account
, who
, NULL
,
832 cid
, G_CALLBACK(chat_invite_accept
),
833 G_CALLBACK(chat_invite_reject
));
835 else if (plugin_return
> 0)
836 chat_invite_accept(cid
);
838 chat_invite_reject(cid
);
841 PurpleConversation
*serv_got_joined_chat(PurpleConnection
*gc
,
842 int id
, const char *name
)
844 PurpleConversation
*conv
;
845 PurpleConvChat
*chat
;
846 PurpleAccount
*account
;
848 account
= purple_connection_get_account(gc
);
850 g_return_val_if_fail(account
!= NULL
, NULL
);
851 g_return_val_if_fail(name
!= NULL
, NULL
);
853 conv
= purple_conversation_new(PURPLE_CONV_TYPE_CHAT
, account
, name
);
854 g_return_val_if_fail(conv
!= NULL
, NULL
);
856 chat
= PURPLE_CONV_CHAT(conv
);
858 if (!g_slist_find(gc
->buddy_chats
, conv
))
859 gc
->buddy_chats
= g_slist_append(gc
->buddy_chats
, conv
);
861 purple_conv_chat_set_id(chat
, id
);
863 purple_signal_emit(purple_conversations_get_handle(), "chat-joined", conv
);
868 void serv_got_chat_left(PurpleConnection
*g
, int id
)
871 PurpleConversation
*conv
= NULL
;
872 PurpleConvChat
*chat
= NULL
;
874 for (bcs
= g
->buddy_chats
; bcs
!= NULL
; bcs
= bcs
->next
) {
875 conv
= (PurpleConversation
*)bcs
->data
;
877 chat
= PURPLE_CONV_CHAT(conv
);
879 if (purple_conv_chat_get_id(chat
) == id
)
888 purple_debug(PURPLE_DEBUG_INFO
, "server", "Leaving room: %s\n",
889 purple_conversation_get_name(conv
));
891 g
->buddy_chats
= g_slist_remove(g
->buddy_chats
, conv
);
893 purple_conv_chat_left(PURPLE_CONV_CHAT(conv
));
895 purple_signal_emit(purple_conversations_get_handle(), "chat-left", conv
);
898 void purple_serv_got_join_chat_failed(PurpleConnection
*gc
, GHashTable
*data
)
900 purple_signal_emit(purple_conversations_get_handle(), "chat-join-failed",
904 void serv_got_chat_in(PurpleConnection
*g
, int id
, const char *who
,
905 PurpleMessageFlags flags
, const char *message
, time_t mtime
)
908 PurpleConversation
*conv
= NULL
;
909 PurpleConvChat
*chat
= NULL
;
913 g_return_if_fail(who
!= NULL
);
914 g_return_if_fail(message
!= NULL
);
917 purple_debug_error("server",
918 "serv_got_chat_in ignoring negative timestamp\n");
919 /* TODO: Would be more appropriate to use a value that indicates
920 that the timestamp is unknown, and surface that in the UI. */
924 for (bcs
= g
->buddy_chats
; bcs
!= NULL
; bcs
= bcs
->next
) {
925 conv
= (PurpleConversation
*)bcs
->data
;
927 chat
= PURPLE_CONV_CHAT(conv
);
929 if (purple_conv_chat_get_id(chat
) == id
)
938 /* Did I send the message? */
939 if (purple_strequal(purple_conv_chat_get_nick(chat
),
940 purple_normalize(purple_conversation_get_account(conv
), who
))) {
941 flags
|= PURPLE_MESSAGE_SEND
;
942 flags
&= ~PURPLE_MESSAGE_RECV
; /* Just in case some prpl sets it! */
944 flags
|= PURPLE_MESSAGE_RECV
;
948 * Make copies of the message and the sender in case plugins want
949 * to free these strings and replace them with a modifed version.
951 buffy
= g_strdup(message
);
952 angel
= g_strdup(who
);
954 plugin_return
= GPOINTER_TO_INT(
955 purple_signal_emit_return_1(purple_conversations_get_handle(),
956 "receiving-chat-msg", g
->account
,
957 &angel
, &buffy
, conv
, &flags
));
959 if (!buffy
|| !angel
|| plugin_return
) {
968 purple_signal_emit(purple_conversations_get_handle(), "received-chat-msg", g
->account
,
969 who
, message
, conv
, flags
);
971 purple_conv_chat_write(chat
, who
, message
, flags
, mtime
);
977 void serv_send_file(PurpleConnection
*gc
, const char *who
, const char *file
)
980 PurplePluginProtocolInfo
*prpl_info
;
983 prpl
= purple_connection_get_prpl(gc
);
984 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
986 if (prpl_info
->send_file
&&
987 (!prpl_info
->can_receive_file
988 || prpl_info
->can_receive_file(gc
, who
)))
989 prpl_info
->send_file(gc
, who
, file
);