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; } } }
static int tgprpl_send_chat (PurpleConnection * gc, int id, const char *message, PurpleMessageFlags flags) { debug ("tgprpl_send_chat()\n"); telegram_conn *conn = purple_connection_get_protocol_data (gc); gchar *raw = purple_unescape_html(message); tgl_do_send_message (conn->TLS, TGL_MK_CHAT(id), raw, (int)strlen (raw), 0, 0); g_free (raw); p2tgl_got_chat_in(conn->TLS, TGL_MK_CHAT(id), TGL_MK_USER(conn->TLS->our_id), message, PURPLE_MESSAGE_RECV, time(NULL)); return 1; }
static 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: p2tgl_got_im (TLS, to, error, flags, now); break; } }
static void tgp_chat_on_loaded_chat_full_joining (struct tgl_state *TLS, void *_, int success, struct tgl_chat *C) { debug ("tgp_chat_on_loaded_chat_full_joining()"); if (! success) { tgp_notify_on_error_gw (TLS, NULL, success); return; } tgp_chat_on_loaded_chat_full (TLS, C); tgp_chat_show (TLS, C); // Check if the users attempts to join an empty chat if (! C->user_list_size) { p2tgl_got_chat_in (TLS, C->id, C->id, _("You have already left this chat."), PURPLE_MESSAGE_SYSTEM, time (NULL)); } }
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; // only display new messages, ignore updates or deletions if ((M->flags & (TGLMF_EMPTY | TGLMF_DELETED)) || !(M->flags & TGLMF_CREATED) || !M->message || tgp_outgoing_msg (TLS, M) || !tgl_get_peer_type (M->to_id)) { return; } if (M->flags & TGLMF_SERVICE) { text = format_service_msg (TLS, M); flags |= PURPLE_MESSAGE_SYSTEM; } else if (M->media.type == tgl_message_media_document && M->media.document->flags & TGLDF_STICKER) { #ifdef HAVE_LIBWEBP char *filename = C->data; int img = p2tgl_imgstore_add_with_id_webp (filename); if (img <= 0) { failure ("Cannot display sticker, adding to imgstore failed"); return; } used_images_add (conn, img); text = format_img_full (img); flags |= PURPLE_MESSAGE_IMAGES; g_free (filename); #else char *txt_user = p2tgl_strdup_alias (tgl_peer_get (TLS, M->from_id)); text = g_strdup_printf ("%s sent a sticker", txt_user); flags |= PURPLE_MESSAGE_SYSTEM; g_free (txt_user); #endif } else if (M->media.type == tgl_message_media_photo || (M->media.type == tgl_message_media_document_encr && M->media.encr_document->flags & TGLDF_IMAGE)) { char *filename = C->data; int img = p2tgl_imgstore_add_with_id (filename); if (img <= 0) { failure ("Cannot display picture message, adding to imgstore failed."); return; } used_images_add (conn, img); text = format_img_full (img); flags |= PURPLE_MESSAGE_IMAGES; g_free (filename); } else if (M->media.type == tgl_message_media_document) { char *who = p2tgl_strdup_id (M->from_id); if (! tgp_our_msg(TLS, M)) { tgprpl_recv_file (conn->gc, who, M->media.document); } g_free (who); return; } else if (M->media.type == tgl_message_media_document_encr) { char *who = p2tgl_strdup_id (M->to_id); if (! tgp_our_msg(TLS, M)) { tgprpl_recv_encr_file (conn->gc, who, M->media.encr_document); } g_free (who); return; } else { text = format_message (M); flags |= PURPLE_MESSAGE_RECV; } if (! text || ! *text) { warning ("No text to display"); return; } switch (tgl_get_peer_type (M->to_id)) { case TGL_PEER_CHAT: { if (chat_show (conn->gc, tgl_get_peer_id (M->to_id))) { p2tgl_got_chat_in (TLS, M->to_id, M->from_id, text, flags, M->date); } pending_reads_add (conn->pending_reads, M->to_id); break; } case TGL_PEER_ENCR_CHAT: { p2tgl_got_im (TLS, M->to_id, text, flags, M->date); pending_reads_add (conn->pending_reads, M->to_id); 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 (TLS, M->from_id, text, flags, M->date); pending_reads_add (conn->pending_reads, M->from_id); } break; } } if (p2tgl_status_is_present (purple_account_get_active_status (conn->pa)) && p2tgl_send_notifications(conn->pa)) { pending_reads_send_all (conn->pending_reads, conn->TLS); } g_free (text); }
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; // Filter message updates and deletes, are not created and // all messages in general that were already displayed, or shouldn't be displayed if ((M->flags & (FLAG_MESSAGE_EMPTY | FLAG_DELETED)) || !(M->flags & FLAG_CREATED) || !M->message || our_msg (TLS, M) || !tgl_get_peer_type (M->to_id)) { return; } if (M->service) { text = format_service_msg (TLS, M); flags |= PURPLE_MESSAGE_SYSTEM; } else if (M->media.type == tgl_message_media_document) { char *who = p2tgl_strdup_id (M->from_id); if (! out_msg(TLS, M)) { tgprpl_recv_file (conn->gc, who, &M->media.document); } g_free (who); return; } else if (M->media.type == tgl_message_media_document_encr) { char *who = p2tgl_strdup_id (M->from_id); if (! out_msg(TLS, M)) { tgprpl_recv_encr_file (conn->gc, who, &M->media.encr_document); } g_free (who); } else if (M->media.type == tgl_message_media_photo) { char *filename = C->data; int imgStoreId = p2tgl_imgstore_add_with_id (filename); if (imgStoreId <= 0) { failure ("Cannot display picture message, adding to imgstore failed."); return; } used_images_add (conn, imgStoreId); text = format_img_full (imgStoreId); flags |= PURPLE_MESSAGE_IMAGES; } else { text = format_message (M); flags |= PURPLE_MESSAGE_RECV; } if (! text || ! *text) { warning ("No text to display"); return; } switch (tgl_get_peer_type (M->to_id)) { case TGL_PEER_CHAT: { if (chat_show (conn->gc, tgl_get_peer_id (M->to_id))) { p2tgl_got_chat_in (TLS, M->to_id, M->from_id, text, flags, M->date); } pending_reads_add (conn->pending_reads, M->to_id); break; } case TGL_PEER_ENCR_CHAT: { p2tgl_got_im (TLS, M->to_id, text, flags, M->date); pending_reads_add (conn->pending_reads, M->to_id); break; } case TGL_PEER_USER: { if (out_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 (TLS, M->from_id, text, flags, M->date); pending_reads_add (conn->pending_reads, M->from_id); } break; } } if (p2tgl_status_is_present (purple_account_get_active_status (conn->pa))) { pending_reads_send_all (conn->pending_reads, conn->TLS); } g_free (text); }
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); }