Exemple #1
0
std::string markup_escape(std::string const &text) {
    gchar *escaped = purple_markup_escape_text(text.c_str(), text.size());
    std::string result(escaped);
    g_free(escaped);

    return result;
}
void SpectrumConversation::sendMessage(boost::shared_ptr<Swift::Message> &message) {
	// escape and send
	gchar *_markup = purple_markup_escape_text(message->getBody().c_str(), -1);
	if (purple_conversation_get_type(m_conv) == PURPLE_CONV_TYPE_IM) {
		purple_conv_im_send(PURPLE_CONV_IM(m_conv), _markup);
	}
	g_free(_markup);
}
static void flist_sfc_report(PurpleConnection *pc, JsonObject *root) {
    PurpleAccount *pa = purple_connection_get_account(pc);
    const gchar *callid, *reporter, *report;
    gchar *s, *escaped_reporter, *escaped_report, *message;
    GString *message_str;
    gdouble timestamp;
    gint logid; gboolean has_logid;

    callid = json_object_get_string_member(root, "callid");
    reporter = json_object_get_string_member(root, "character");
    report = json_object_get_string_member(root, "report");
    logid = json_object_get_parse_int_member(root, "logid", &has_logid);
    timestamp = json_object_get_double_member(root, "timestamp");

    g_return_if_fail(callid);
    g_return_if_fail(reporter);
    g_return_if_fail(report);

    message_str = g_string_new(NULL);
    s = g_strdup(purple_url_encode(flist_serialize_account(pa)));
    escaped_reporter = purple_markup_escape_text(reporter, -1);
    escaped_report = purple_markup_escape_text(report, -1);

    g_string_append_printf(message_str, "Moderator Alert. %s writes:\n", escaped_reporter);
    g_string_append_printf(message_str, "%s\n", escaped_report);
    g_string_append_printf(message_str, "<a href=\"flistsfc://%s/%s\">Confirm Alert</a>", s, purple_url_encode(callid));
    g_string_append(message_str, ", ");
    if(has_logid) {
        g_string_append_printf(message_str, "<a href=\"http://www.f-list.net/fchat/getLog.php?log=%d\">View Log</a>", logid);
    } else {
        g_string_append_printf(message_str, "(No Log)");
    }

    message = g_string_free(message_str, FALSE);
    serv_got_im(pc, GLOBAL_NAME, message, PURPLE_MESSAGE_RECV, time(NULL));

    g_free(escaped_report);
    g_free(escaped_reporter);
    g_free(message);
    g_free(s);
}
static gboolean flist_process_profile(FListAccount *fla, JsonObject *root) {
    FListProfiles *flp = _flist_profiles(fla);
    JsonObject *info;
    GList *categories, *cur;
    GHashTable *profile;
    const gchar *error;

    error = json_object_get_string_member(root, "error");
    if(error && strlen(error) > 0) {
        purple_debug_info(FLIST_DEBUG, "We requested a profile from the Web API, but it returned an error. Error Message: %s\n", error);
        return FALSE; //user probably opted out of API access
    }

    profile = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
    info = json_object_get_object_member(root, "info");
    categories = json_object_get_members(info);

    cur = categories;
    while(cur) {
        JsonObject *field_group;
        JsonArray *field_array;
        guint i, len;

        field_group = json_object_get_object_member(info, cur->data);
        field_array = json_object_get_array_member(field_group, "items");

        len = json_array_get_length(field_array);
        for(i = 0; i < len; i++) {
            JsonObject *field_object = json_array_get_object_element(field_array, i);
            const gchar *field_name = json_object_get_string_member(field_object, "name");
            gchar *unescaped = flist_html_unescape_utf8(json_object_get_string_member(field_object, "value"));
            gchar *field_value = purple_markup_escape_text(unescaped, strlen(unescaped));
            g_hash_table_insert(profile, (gpointer) field_name, (gpointer) field_value);
            g_free(unescaped);
        }

        cur = cur->next;
    }
    g_list_free(categories);

    flist_show_profile(fla->pc, flp->character, profile, FALSE, flp->profile_info);

    g_hash_table_destroy(profile);

    return TRUE;
}
gboolean flist_process_PRD(PurpleConnection *pc, JsonObject *root) {
    FListAccount *fla = pc->proto_data;
    FListProfiles *flp = _flist_profiles(fla);
    const gchar *type;
    const gchar *key;
    gchar *value, *unescaped;

    if(!flp->character) {
        purple_debug_error(FLIST_DEBUG, "Profile information received, but we are not expecting profile information.\n");
        return TRUE;
    }

    type = json_object_get_string_member(root, "type");
    if(!g_strcmp0(type, "start")) { /* we don't care! */
        if(flp->table) g_hash_table_destroy(flp->table);
        flp->table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
        return TRUE;
    }
    if(!g_strcmp0(type, "end")) {
        flist_show_profile(pc, flp->character, flp->table, FALSE, flp->profile_info);
        g_free(flp->character); flp->character = NULL;
        if(flp->table) {
            g_hash_table_destroy(flp->table); flp->table = NULL;
        }
        purple_notify_user_info_destroy(flp->profile_info); flp->profile_info = NULL;
        return TRUE;
    }
    if(!flp->table) {
        return TRUE; //this should never happen
    }

    key = json_object_get_string_member(root, "key");
    unescaped = flist_html_unescape_utf8(json_object_get_string_member(root, "value"));
    value = purple_markup_escape_text(unescaped, strlen(unescaped));
    g_hash_table_replace(flp->table, g_strdup(key), value);

    purple_debug_info(FLIST_DEBUG, "Profile information received for %s. Key: %s. Value: %s.\n", flp->character, key, value);

    g_free(unescaped);

    return TRUE;
}
Exemple #6
0
static char *format_message (struct tgl_message *M) {
  switch (M->media.type) {
    case tgl_message_media_contact:
      return g_strdup_printf ("<b>%s %s</b><br>%s", M->media.first_name, M->media.last_name, M->media.phone);
      break;
    case tgl_message_media_geo:
      return g_strdup_printf ("<a href=\"http://openstreetmap.org/?lat=%f&lon=%f&zoom=20\">"
                             "http://openstreetmap.org/?lat=%f&lon=%f&zoom=20</a>",
                             M->media.geo.latitude, M->media.geo.longitude,
                             M->media.geo.latitude, M->media.geo.longitude);
      return g_strdup_printf ("<b>%s %s</b><br>%s", M->media.first_name, M->media.last_name, M->media.phone);
      break;
    default:
      if (*M->message != 0) {
        return purple_markup_escape_text (M->message, strlen (M->message));
      }
      return NULL;
      break;
  }
}
static void flist_sfc_confirm(PurpleConnection *pc, JsonObject *root) {
    FListAccount *fla = pc->proto_data;
    const gchar *moderator, *reporter;
    gchar *message, *escaped_message, *bbcode_message;
    gdouble timestamp;

    moderator = json_object_get_string_member(root, "moderator");
    reporter = json_object_get_string_member(root, "character");
    timestamp = json_object_get_double_member(root, "timestamp");

    g_return_if_fail(moderator);
    g_return_if_fail(reporter);

    message = g_strdup_printf("Alert Confirmed. [b]%s[/b] is handling [b]%s[/b]'s report.", moderator, reporter);
    escaped_message = purple_markup_escape_text(message, -1);
    bbcode_message = flist_bbcode_to_html(fla, NULL, escaped_message);
    serv_got_im(pc, GLOBAL_NAME, bbcode_message, PURPLE_MESSAGE_RECV, time(NULL));
    g_free(bbcode_message);
    g_free(escaped_message);
    g_free(message);
}
Exemple #8
0
static void do_msg_sys(PurpleConnection *gc, guint8 *data, gint data_len)
{
	guint8 reply;
	gchar *msg, *msg_esc;
	qq_data * qd;

	g_return_if_fail(gc != NULL && gc->proto_data != NULL && data != NULL && data_len != 0);

	qd = (qq_data *)gc->proto_data;

	qq_get8(&reply, data+4);
	qq_get_vstr(&msg, NULL, sizeof(guint8), data+5);

	if (reply == 0x01) {
		purple_debug_error("QQ", "We are kicked out by QQ server\n");
		msg_esc = purple_markup_escape_text(msg, -1);
		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, msg_esc);
		g_free(msg);
		g_free(msg_esc);
		return;
	}
	
	qq_got_message(gc, msg);
}
static void update_message_received (struct tgl_state *TLS, struct tgl_message *M) {
  debug ("received message\n");
  telegram_conn *conn = TLS->ev_base;
  conn->updated = 1;

  if (M->service) {
    debug ("service message, skipping...\n");
    char *text = format_service_msg (TLS, M);
    if (text) {
      switch (tgl_get_peer_type (M->to_id)) {
        case TGL_PEER_CHAT:
          chat_add_message (TLS, M, text);
          break;
          
        case TGL_PEER_USER:
          p2tgl_got_im (TLS, M->from_id, text, PURPLE_MESSAGE_SYSTEM, M->date);
          break;
      }
      g_free (text);
    }
    conn->updated = 1;
    return;
  }
  
  if ((M->flags & (FLAG_MESSAGE_EMPTY | FLAG_DELETED)) || !(M->flags & FLAG_CREATED)) {
    return;
  }
  if (!tgl_get_peer_type (M->to_id)) {
    warning ("Bad msg\n");
    return;
  }

  if (M->media.type == tgl_message_media_photo) {
    tgl_do_load_photo (TLS, &M->media.photo, on_message_load_photo, M);
    return;
  }

  if (!M->message) {
    return;
  }

  char *text = purple_markup_escape_text (M->message, strlen (M->message));
  switch (tgl_get_peer_type (M->to_id)) {
    case TGL_PEER_CHAT:
      debug ("PEER_CHAT\n");
      if (!our_msg(TLS, M)) {
        chat_add_message (TLS, M, text);
      }
      break;
      
    case TGL_PEER_USER:
      debug ("PEER_USER\n");
      
      // p2tgl_got_im (TLS, M->to_id, text, PURPLE_MESSAGE_SEND, M->date);
      // :TODO: figure out how to add messages from different devices to history
      if (!our_msg(TLS, M)) {
        if (out_msg(TLS, M)) {
          p2tgl_got_im (TLS, M->to_id, text, PURPLE_MESSAGE_SEND, M->date);
        } else {
          p2tgl_got_im (TLS, M->from_id, text, PURPLE_MESSAGE_RECV, M->date);
        }
      }
      break;
      
    case TGL_PEER_ENCR_CHAT:
      break;
      
    case TGL_PEER_GEO_CHAT:
      break;
  }
  
  g_free (text);
}
Exemple #10
0
static void
entry_key_pressed(GntWidget *w, FinchConv *ggconv)
{
	const char *text = gnt_entry_get_text(GNT_ENTRY(ggconv->entry));
	if (*text == '/' && *(text + 1) != '/')
	{
		PurpleConversation *conv = ggconv->active_conv;
		PurpleCmdStatus status;
		const char *cmdline = text + 1;
		char *error = NULL, *escape;

		escape = g_markup_escape_text(cmdline, -1);
		status = purple_cmd_do_command(conv, cmdline, escape, &error);
		g_free(escape);

		switch (status)
		{
			case PURPLE_CMD_STATUS_OK:
				break;
			case PURPLE_CMD_STATUS_NOT_FOUND:
				purple_conversation_write(conv, "", _("No such command."),
						PURPLE_MESSAGE_NO_LOG, time(NULL));
				break;
			case PURPLE_CMD_STATUS_WRONG_ARGS:
				purple_conversation_write(conv, "", _("Syntax Error:  You typed the wrong number of arguments "
							"to that command."),
						PURPLE_MESSAGE_NO_LOG, time(NULL));
				break;
			case PURPLE_CMD_STATUS_FAILED:
				purple_conversation_write(conv, "", error ? error : _("Your command failed for an unknown reason."),
						PURPLE_MESSAGE_NO_LOG, time(NULL));
				break;
			case PURPLE_CMD_STATUS_WRONG_TYPE:
				if(purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM)
					purple_conversation_write(conv, "", _("That command only works in chats, not IMs."),
							PURPLE_MESSAGE_NO_LOG, time(NULL));
				else
					purple_conversation_write(conv, "", _("That command only works in IMs, not chats."),
							PURPLE_MESSAGE_NO_LOG, time(NULL));
				break;
			case PURPLE_CMD_STATUS_WRONG_PRPL:
				purple_conversation_write(conv, "", _("That command doesn't work on this protocol."),
						PURPLE_MESSAGE_NO_LOG, time(NULL));
				break;
		}
		g_free(error);
	}
	else if (!purple_account_is_connected(purple_conversation_get_account(ggconv->active_conv)))
	{
		purple_conversation_write(ggconv->active_conv, "", _("Message was not sent, because you are not signed on."),
				PURPLE_MESSAGE_ERROR | PURPLE_MESSAGE_NO_LOG, time(NULL));
	}
	else
	{
		char *escape = purple_markup_escape_text((*text == '/' ? text + 1 : text), -1);
		switch (purple_conversation_get_type(ggconv->active_conv))
		{
			case PURPLE_CONV_TYPE_IM:
				purple_conv_im_send_with_flags(PURPLE_CONV_IM(ggconv->active_conv), escape, PURPLE_MESSAGE_SEND);
				break;
			case PURPLE_CONV_TYPE_CHAT:
				purple_conv_chat_send(PURPLE_CONV_CHAT(ggconv->active_conv), escape);
				break;
			default:
				g_free(escape);
				g_return_if_reached();
		}
		g_free(escape);
		purple_idle_touch();
	}
	gnt_entry_add_to_history(GNT_ENTRY(ggconv->entry), text);
	gnt_entry_clear(GNT_ENTRY(ggconv->entry));
}
Exemple #11
0
/**
 * @brief Append the status information to a user_info struct
 *
 * The returned information is HTML-ready, appropriately escaped, as all information in a user_info struct should be HTML.
 *
 * @param gc The PurpleConnection
 * @param user_info A PurpleNotifyUserInfo object to which status information will be added
 * @param b The PurpleBuddy whose status is desired. This or the aim_userinfo_t (or both) must be passed to oscar_user_info_append_status().
 * @param userinfo The aim_userinfo_t of the buddy whose status is desired. This or the PurpleBuddy (or both) must be passed to oscar_user_info_append_status().
 * @param use_html_status If TRUE, prefer HTML-formatted away message over plaintext available message.
 */
void
oscar_user_info_append_status(PurpleConnection *gc, PurpleNotifyUserInfo *user_info, PurpleBuddy *b, aim_userinfo_t *userinfo, gboolean use_html_status)
{
	PurpleAccount *account = purple_connection_get_account(gc);
	OscarData *od;
	PurplePresence *presence = NULL;
	PurpleStatus *status = NULL;
	gchar *message = NULL, *itmsurl = NULL, *tmp;
	gboolean escaping_needed = TRUE;

	od = purple_connection_get_protocol_data(gc);

	if (b == NULL && userinfo == NULL)
		return;

	if (b == NULL)
		b = purple_find_buddy(purple_connection_get_account(gc), userinfo->bn);
	else
		userinfo = aim_locate_finduserinfo(od, purple_buddy_get_name(b));

	if (b) {
		presence = purple_buddy_get_presence(b);
		status = purple_presence_get_active_status(presence);
	}

	/* If we have both b and userinfo we favor userinfo, because if we're
	   viewing someone's profile then we want the HTML away message, and
	   the "message" attribute of the status contains only the plaintext
	   message. */
	if (userinfo) {
		if ((userinfo->flags & AIM_FLAG_AWAY) && use_html_status && userinfo->away_len > 0 && userinfo->away != NULL && userinfo->away_encoding != NULL) {
			/* Away message */
			message = oscar_encoding_to_utf8(userinfo->away_encoding, userinfo->away, userinfo->away_len);
			escaping_needed = FALSE;
		} else {
			/*
			 * Available message or non-HTML away message (because that's
			 * all we have right now.
			 */
			if ((userinfo->status != NULL) && userinfo->status[0] != '\0') {
				message = oscar_encoding_to_utf8(userinfo->status_encoding, userinfo->status, userinfo->status_len);
			}
#if defined (_WIN32) || defined (__APPLE__)
			if (userinfo->itmsurl && (userinfo->itmsurl[0] != '\0')) {
				itmsurl = oscar_encoding_to_utf8(userinfo->itmsurl_encoding, userinfo->itmsurl, userinfo->itmsurl_len);
			}
#endif
		}
	} else {
		message = g_strdup(purple_status_get_attr_string(status, "message"));
		itmsurl = g_strdup(purple_status_get_attr_string(status, "itmsurl"));
	}

	if (message) {
		tmp = oscar_util_format_string(message, purple_account_get_username(account));
		g_free(message);
		message = tmp;
		if (escaping_needed) {
			tmp = purple_markup_escape_text(message, -1);
			g_free(message);
			message = tmp;
		}
	}

	if (use_html_status && itmsurl) {
		tmp = g_strdup_printf("<a href=\"%s\">%s</a>", itmsurl, message);
		g_free(message);
		message = tmp;
	}

	if (b) {
		if (purple_presence_is_online(presence)) {
			gboolean is_away = ((status && !purple_status_is_available(status)) || (userinfo && (userinfo->flags & AIM_FLAG_AWAY)));
			if (oscar_util_valid_name_icq(purple_buddy_get_name(b)) || is_away || !message || !(*message)) {
				/* Append the status name for online ICQ statuses, away AIM statuses, and for all buddies with no message.
				 * If the status name and the message are the same, only show one. */
				const char *status_name = purple_status_get_name(status);
				if (status_name && message && !strcmp(status_name, message))
					status_name = NULL;

				tmp = g_strdup_printf("%s%s%s",
									   status_name ? status_name : "",
									   ((status_name && message) && *message) ? ": " : "",
									   (message && *message) ? message : "");
				g_free(message);
				message = tmp;
			}

		} else if (aim_ssi_waitingforauth(od->ssi.local,
			aim_ssi_itemlist_findparentname(od->ssi.local, purple_buddy_get_name(b)),
			purple_buddy_get_name(b)))
		{
			/* Note if an offline buddy is not authorized */
			tmp = g_strdup_printf("%s%s%s",
					_("Not Authorized"),
					(message && *message) ? ": " : "",
					(message && *message) ? message : "");
			g_free(message);
			message = tmp;
		} else {
			g_free(message);
			message = g_strdup(_("Offline"));
		}
	}

	if (presence) {
		const char *mood;
		const char *comment;
		char *description;
		status = purple_presence_get_status(presence, "mood");
		mood = icq_get_custom_icon_description(purple_status_get_attr_string(status, PURPLE_MOOD_NAME));
		if (mood) {
			comment = purple_status_get_attr_string(status, PURPLE_MOOD_COMMENT);
			if (comment) {
				char *escaped_comment = purple_markup_escape_text(comment, -1);
				description = g_strdup_printf("%s (%s)", _(mood), escaped_comment);
				g_free(escaped_comment);
			} else {
				description = g_strdup(_(mood));
			}
			purple_notify_user_info_add_pair(user_info, _("Mood"), description);
			g_free(description);
		}
	}

	purple_notify_user_info_add_pair(user_info, _("Status"), message);
	g_free(message);
}
Exemple #12
0
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);
}