static void tgp_info_load_channel_done (struct tgl_state *TLS, void *extra, int success, struct tgl_channel *C) { g_return_if_fail(success); PurpleNotifyUserInfo *info = purple_notify_user_info_new (); if (str_not_empty (C->about)) { purple_notify_user_info_add_pair (info, _("Description"), C->about); } if (str_not_empty (C->username)) { char *link = g_strdup_printf ("https://telegram.me/%s", C->username); purple_notify_user_info_add_pair (info, _("Link"), link); g_free (link); } if (str_not_empty (C->print_title)) { purple_notify_user_info_add_pair (info, _("Print Title"), C->print_title); } char *admins = g_strdup_printf ("%d", C->admins_count); purple_notify_user_info_add_pair (info, _("Administrators"), admins); g_free (admins); char *participants = g_strdup_printf ("%d", C->participants_count); purple_notify_user_info_add_pair (info, _("Participants"), participants); g_free (participants); char *kicked = g_strdup_printf ("%d", C->kicked_count); purple_notify_user_info_add_pair (info, _("Kicked"), kicked); g_free (kicked); purple_notify_userinfo (tls_get_conn (TLS), tgp_blist_lookup_purple_name (TLS, C->id), info, NULL, NULL); }
void tgp_msg_sys_out (struct tgl_state *TLS, const char *msg, tgl_peer_id_t to_id, int no_log) { int flags = PURPLE_MESSAGE_SYSTEM; if (no_log) { flags |= PURPLE_MESSAGE_NO_LOG; } time_t now; time (&now); switch (tgl_get_peer_type (to_id)) { case TGL_PEER_CHAT: p2tgl_got_chat_in (TLS, to_id, to_id, msg, flags, now); break; case TGL_PEER_USER: case TGL_PEER_ENCR_CHAT: { const char *name = tgp_blist_lookup_purple_name (TLS, to_id); PurpleConversation *conv = p2tgl_find_conversation_with_account (TLS, to_id); g_return_if_fail (name); if (! conv) { conv = purple_conversation_new (PURPLE_CONV_TYPE_IM, tls_get_pa (TLS), name); } purple_conversation_write (conv, name, msg, flags, now); break; } } }
void tgp_msg_err_out (struct tgl_state *TLS, const char *error, tgl_peer_id_t to) { int flags = PURPLE_MESSAGE_ERROR | PURPLE_MESSAGE_SYSTEM; time_t now; time (&now); switch (tgl_get_peer_type (to)) { case TGL_PEER_CHAT: p2tgl_got_chat_in (TLS, to, to, error, flags, now); break; case TGL_PEER_USER: case TGL_PEER_ENCR_CHAT: serv_got_im (tls_get_conn (TLS), tgp_blist_lookup_purple_name (TLS, to), error, flags, now); break; } }
static void tgp_chat_add_all_users (struct tgl_state *TLS, PurpleConversation *conv, struct tgl_chat *C) { GList *users = NULL, *flags = NULL; debug ("tgp_chat_add_all_users()"); int i = 0; for (; i < C->user_list_size; i++) { struct tgl_chat_user *uid = (C->user_list + i); const char *name = tgp_blist_lookup_purple_name (TLS, TGL_MK_USER(uid->user_id)); if (! name) { g_warn_if_reached(); continue; } users = g_list_append (users, g_strdup (name)); flags = g_list_append (flags, GINT_TO_POINTER(C->admin_id == uid->user_id ? PURPLE_CBFLAGS_FOUNDER : PURPLE_CBFLAGS_NONE)); } purple_conv_chat_add_users (PURPLE_CONV_CHAT(conv), users, NULL, flags, FALSE); g_list_free_full (users, g_free); g_list_free (flags); }
static char *tgp_msg_sticker_display (struct tgl_state *TLS, tgl_peer_id_t from, const char *filename, int *flags) { char *text = NULL; #ifdef HAVE_LIBWEBP connection_data *conn = TLS->ev_base; int img = p2tgl_imgstore_add_with_id_webp ((char *) filename); if (img <= 0) { failure ("Cannot display sticker, adding to imgstore failed"); return NULL; } used_images_add (conn, img); text = tgp_format_img (img); *flags |= PURPLE_MESSAGE_IMAGES; #else const char *txt_user = tgp_blist_lookup_purple_name (TLS, from); g_return_val_if_fail (txt_user, NULL); text = g_strdup_printf (_("%s sent a sticker."), txt_user); *flags |= PURPLE_MESSAGE_SYSTEM; #endif return text; }
static void tgp_info_load_user_done (struct tgl_state *TLS, void *extra, int success, struct tgl_user *U) { g_return_if_fail(success); // user info PurpleNotifyUserInfo *info = purple_notify_user_info_new (); if (str_not_empty (U->first_name) && str_not_empty (U->last_name)) { purple_notify_user_info_add_pair (info, _("First name"), U->first_name); purple_notify_user_info_add_pair (info, _("Last name"), U->last_name); } else { purple_notify_user_info_add_pair (info, _("Name"), U->print_name); } if (str_not_empty (U->username)) { char *username = g_strdup_printf ("@%s", U->username); purple_notify_user_info_add_pair (info, _("Username"), username); g_free (username); } char *status = tgp_format_user_status (&U->status); purple_notify_user_info_add_pair (info, _("Last seen"), status); g_free (status); if (str_not_empty (U->phone)) { char *phone = g_strdup_printf ("+%s", U->phone); purple_notify_user_info_add_pair (info, _("Phone"), phone); g_free (phone); } // secret chat info tgl_peer_t *O = extra; if (O && tgl_get_peer_type (O->id) == TGL_PEER_ENCR_CHAT) { struct tgl_secret_chat *secret = &O->encr_chat; if (secret->state == sc_waiting) { purple_notify_user_info_add_pair (info, "", _("Waiting for the user to get online...")); } else { const char *ttl_key = _("Self destruction timer"); if (secret->ttl) { char *ttl = g_strdup_printf ("%d", secret->ttl); purple_notify_user_info_add_pair (info, ttl_key, ttl); g_free (ttl); } else { purple_notify_user_info_add_pair (info, ttl_key, _("Timer is not enabled.")); } if (secret->first_key_sha[0]) { int sha1key = tgp_visualize_key (TLS, secret->first_key_sha); if (sha1key != -1) { char *ident_icon = tgp_format_img (sha1key); purple_notify_user_info_add_pair (info, _("Secret key"), ident_icon); g_free(ident_icon); } } } } const char *who = NULL; if (tgl_get_peer_type (O->id) == TGL_PEER_ENCR_CHAT) { who = tgp_blist_lookup_purple_name (TLS, O->id); } else { who = tgp_blist_lookup_purple_name (TLS, U->id); } purple_notify_userinfo (tls_get_conn (TLS), who, info, NULL, NULL); }
static char *format_service_msg (struct tgl_state *TLS, struct tgl_message *M) { g_return_val_if_fail(M && M->flags & TGLMF_SERVICE, NULL); connection_data *conn = TLS->ev_base; char *txt = NULL; tgl_peer_t *fromPeer = tgl_peer_get (TLS, M->from_id); g_return_val_if_fail(fromPeer != NULL, NULL); const char *txt_user = fromPeer->print_name; switch (M->action.type) { case tgl_message_action_chat_create: txt = g_strdup_printf (_("%2$s created chat %1$s."), M->action.title, txt_user); break; case tgl_message_action_chat_edit_title: txt = g_strdup_printf (_("%2$s changed title to %1$s."), M->action.new_title, txt_user); break; case tgl_message_action_chat_edit_photo: txt = g_strdup_printf (_("%s changed photo."), txt_user); break; case tgl_message_action_chat_delete_photo: txt = g_strdup_printf (_("%s deleted photo."), txt_user); break; case tgl_message_action_chat_add_user_by_link: { tgl_peer_t *actionPeer = tgl_peer_get (TLS, TGL_MK_USER (M->action.user)); if (actionPeer) { char *alias = actionPeer->print_name; PurpleConversation *conv = purple_find_chat (conn->gc, tgl_get_peer_id (M->to_id)); txt = g_strdup_printf (_("%1$s added user %2$s by link."), alias, txt_user); if (conv) { p2tgl_conv_add_user (TLS, conv, tgl_get_peer_id (fromPeer->id), NULL, 0, FALSE); } return txt; } break; } case tgl_message_action_chat_add_user: { tgl_peer_t *peer = tgl_peer_get (TLS, TGL_MK_USER (M->action.user)); if (peer) { char *alias = peer->print_name; txt = g_strdup_printf (_("%2$s added user %1$s."), alias, txt_user); PurpleConversation *conv = purple_find_chat (conn->gc, tgl_get_peer_id (M->to_id)); if (conv) { p2tgl_conv_add_user (TLS, conv, M->action.user, NULL, 0, FALSE); } } break; } case tgl_message_action_chat_delete_user: { tgl_peer_t *peer = tgl_peer_get (TLS, TGL_MK_USER (M->action.user)); if (peer) { tgl_peer_t *chatPeer = tgl_peer_get (TLS, M->to_id); g_return_val_if_fail(tgl_get_peer_type (chatPeer->id) == TGL_PEER_CHAT, NULL); // make sure that the chat is showing before deleting the user, otherwise the chat will be // initialised after removing the chat and the chat will still contain the deleted user PurpleConversation *conv = tgp_chat_show (TLS, &chatPeer->chat); if (conv) { char *alias = peer->print_name; const char *aliasLeft = tgp_blist_lookup_purple_name (TLS, TGL_MK_USER (M->action.user)); if (tgl_get_peer_id (M->from_id) != tgl_get_peer_id (peer->id)) { txt = g_strdup_printf (_("%2$s deleted user %1$s."), alias, txt_user); } g_return_val_if_fail (aliasLeft, NULL); purple_conv_chat_remove_user (purple_conversation_get_chat_data (conv), aliasLeft, txt); if (M->action.user == tgl_get_peer_id (TLS->our_id)) { purple_conv_chat_left (purple_conversation_get_chat_data (conv)); } // conv_del_user already printed a message, prevent a redundant message // from being printed by returning NULL g_free (txt); return NULL; } char *alias = peer->print_name; if (tgl_get_peer_id (M->from_id) != tgl_get_peer_id (peer->id)) { txt = g_strdup_printf (_("%2$s deleted user %1$s."), alias, txt_user); } } break; } case tgl_message_action_set_message_ttl: txt = g_strdup_printf (P_("%2$s set self destruction timer to %1$d second.", "%2$s set self destruction timer to %1$d seconds.", M->action.ttl), M->action.ttl, txt_user); break; case tgl_message_action_read_messages: txt = g_strdup_printf (P_("%2$s marked %1$d message read.", "%2$s marked %1$d messages read.", M->action.read_cnt), M->action.read_cnt, txt_user); break; case tgl_message_action_delete_messages: txt = g_strdup_printf (P_("%2$s deleted %1$d message.", "%2$s deleted %1$d messages.", M->action.delete_cnt), M->action.delete_cnt, txt_user); break; case tgl_message_action_screenshot_messages: txt = g_strdup_printf (P_("%2$s made a screenshot of %1$d message.", "%2$s made a screenshot of %1$d messages.", M->action.screenshot_cnt), M->action.screenshot_cnt, txt_user); break; default: g_warn_if_reached(); break; } return txt; }
static void tgp_msg_display (struct tgl_state *TLS, struct tgp_msg_loading *C) { connection_data *conn = TLS->ev_base; struct tgl_message *M = C->msg; char *text = NULL; int flags = 0; if (M->flags & (TGLMF_EMPTY | TGLMF_DELETED)) { return; } if (!(M->flags & TGLMF_CREATED)) { return; } if (!tgl_get_peer_type (M->to_id)) { warning ("Bad msg\n"); return; } // only display new messages, ignore updates or deletions if (!M->message || tgp_outgoing_msg (TLS, M) || !tgl_get_peer_type (M->to_id)) { return; } // Mark messages that contain a mention as if they contained our current nick name // FIXME: doesn't work in Adium if (M->flags & TGLMF_MENTION) { flags |= PURPLE_MESSAGE_NICK; } // handle messages that failed to load if (C->error) { const char *err = C->error_msg; if (! err) { err = _("failed loading message"); } tgp_msg_err_out (TLS, err, tgp_our_msg (TLS, M) ? M->from_id : M->to_id); return; } // format the message text if (M->flags & TGLMF_SERVICE) { text = format_service_msg (TLS, M); flags |= PURPLE_MESSAGE_SYSTEM; } else if (M->media.type != tgl_message_media_none) { switch (M->media.type) { case tgl_message_media_photo: { if (M->media.photo) { g_return_if_fail(C->data != NULL); text = tgp_msg_photo_display (TLS, C->data, &flags); if (str_not_empty (text)) { if (str_not_empty (M->media.caption)) { char *old = text; text = g_strdup_printf ("%s<br>%s", old, M->media.caption); g_free (old); } } } break; } case tgl_message_media_document: if (M->media.document->flags & TGLDF_STICKER) { g_return_if_fail(C->data != NULL); text = tgp_msg_sticker_display (TLS, M->from_id, C->data, &flags); } else if (M->media.document->flags & TGLDF_IMAGE) { g_return_if_fail(C->data != NULL); text = tgp_msg_photo_display (TLS, C->data, &flags); } else { if (! tgp_our_msg(TLS, M)) { tgprpl_recv_file (conn->gc, tgp_blist_lookup_purple_name (TLS, M->from_id), M); } return; } break; case tgl_message_media_video: case tgl_message_media_audio: { if (! tgp_our_msg(TLS, M)) { tgprpl_recv_file (conn->gc, tgp_blist_lookup_purple_name (TLS, M->from_id), M); } } break; case tgl_message_media_document_encr: if (M->media.encr_document->flags & TGLDF_STICKER) { g_return_if_fail(C->data != NULL); text = tgp_msg_sticker_display (TLS, M->from_id, C->data, &flags); } if (M->media.encr_document->flags & TGLDF_IMAGE) { g_return_if_fail(C->data != NULL); text = tgp_msg_photo_display (TLS, C->data, &flags); } else { if (! tgp_our_msg(TLS, M)) { tgprpl_recv_file (conn->gc, tgp_blist_lookup_purple_name (TLS, M->to_id), M); } return; } break; case tgl_message_media_contact: text = g_strdup_printf ("<b>%s %s</b> %s", M->media.first_name, M->media.last_name, M->media.phone); break; case tgl_message_media_venue: { char *address = NULL; if (M->media.venue.address && strcmp (M->media.venue.title, M->media.venue.address)) { address = g_strdup_printf (" %s", M->media.venue.address); } char *pos = format_geo_link_osm (M->media.venue.geo.latitude, M->media.geo.longitude); text = g_strdup_printf ("<a href=\"%s\">%s</a>%s", pos, M->media.venue.title ? M->media.venue.title : "", address ? address : ""); if (address) { g_free (address); } g_free (pos); break; } case tgl_message_media_geo: { char *pos = format_geo_link_osm (M->media.venue.geo.latitude, M->media.geo.longitude); text = g_strdup_printf ("<a href=\"%s\">%s</a>", pos, pos); g_free (pos); break; } case tgl_message_media_webpage: { char *msg = g_strdup (M->message); text = purple_markup_escape_text (msg, strlen (msg)); g_free (msg); break; } default: warning ("received unknown media type: %d", M->media.type); break; } } else { if (str_not_empty (M->message)) { text = purple_markup_escape_text (M->message, strlen (M->message)); } flags |= PURPLE_MESSAGE_RECV; } if (tgl_get_peer_type (M->to_id) != TGL_PEER_ENCR_CHAT && ! (M->flags & TGLMF_UNREAD)) { flags |= PURPLE_MESSAGE_DELAYED; } // some service messages (like removing/adding users from chats) might print the message // text through other means and leave the text empty if (! str_not_empty (text)) { return; } // display the message to the user switch (tgl_get_peer_type (M->to_id)) { case TGL_PEER_CHAT: { tgl_peer_t *P = tgl_peer_get (TLS, M->to_id); g_return_if_fail(P != NULL); if (tgp_chat_show (TLS, &P->chat)) { p2tgl_got_chat_in (TLS, M->to_id, M->from_id, text, flags, M->date); } break; } case TGL_PEER_ENCR_CHAT: { p2tgl_got_im_combo (TLS, M->to_id, text, flags, M->date); break; } case TGL_PEER_USER: { if (tgp_our_msg (TLS, M)) { flags |= PURPLE_MESSAGE_SEND; flags &= ~PURPLE_MESSAGE_RECV; p2tgl_got_im_combo (TLS, M->to_id, text, flags, M->date); } else { p2tgl_got_im_combo (TLS, M->from_id, text, flags, M->date); } break; } } g_free (text); }