Example #1
0
static void
detach_signals(PurpleConversation *conv)
{
	PidginConversation *gtkconv = NULL;
	PidginWindow *gtkwin = NULL;
	GSList *ids = NULL, *l;

	gtkconv = PIDGIN_CONVERSATION(conv);
	if (!gtkconv)
		return;
	gtkwin  = gtkconv->win;

	ids = purple_conversation_get_data(conv, "notify-imhtml-signals");
	for (l = ids; l != NULL; l = l->next)
		g_signal_handler_disconnect(gtkconv->imhtml, GPOINTER_TO_INT(l->data));
	g_slist_free(ids);

	ids = purple_conversation_get_data(conv, "notify-entry-signals");
	for (l = ids; l != NULL; l = l->next)
		g_signal_handler_disconnect(gtkconv->entry, GPOINTER_TO_INT(l->data));
	g_slist_free(ids);

	purple_conversation_set_data(conv, "notify-message-count", GINT_TO_POINTER(0));

	purple_conversation_set_data(conv, "notify-imhtml-signals", NULL);
	purple_conversation_set_data(conv, "notify-entry-signals", NULL);
}
Example #2
0
static int
attach_signals(PurpleConversation *conv)
{
	PidginConversation *gtkconv = NULL;
	PidginWindow *gtkwin = NULL;
	GSList *imhtml_ids = NULL, *entry_ids = NULL;
	guint id;

	gtkconv = PIDGIN_CONVERSATION(conv);
	if (!gtkconv) {
		purple_debug_misc("notify", "Failed to find gtkconv\n");
		return 0;
	}

	gtkwin  = gtkconv->win;

	if (purple_prefs_get_bool("/plugins/gtk/X11/notify/notify_focus")) {
		/* TODO should really find a way to make this work no matter
		 * where the focus is inside the conv window, without having
		 * to bind to focus-in-event on the g(d|t)kwindow */
		/* try setting the signal on the focus-in-event for
		 * gtkwin->notebook->container? */
		id = g_signal_connect(G_OBJECT(gtkconv->entry), "focus-in-event",
		                      G_CALLBACK(unnotify_cb), conv);
		entry_ids = g_slist_append(entry_ids, GUINT_TO_POINTER(id));

		id = g_signal_connect(G_OBJECT(gtkconv->imhtml), "focus-in-event",
		                      G_CALLBACK(unnotify_cb), conv);
		imhtml_ids = g_slist_append(imhtml_ids, GUINT_TO_POINTER(id));
	}

	if (purple_prefs_get_bool("/plugins/gtk/X11/notify/notify_click")) {
		/* TODO similarly should really find a way to allow for
		 * clicking in other places of the window */
		id = g_signal_connect(G_OBJECT(gtkconv->entry), "button-press-event",
		                      G_CALLBACK(unnotify_cb), conv);
		entry_ids = g_slist_append(entry_ids, GUINT_TO_POINTER(id));

		id = g_signal_connect(G_OBJECT(gtkconv->imhtml), "button-press-event",
		                      G_CALLBACK(unnotify_cb), conv);
		imhtml_ids = g_slist_append(imhtml_ids, GUINT_TO_POINTER(id));
	}

	if (purple_prefs_get_bool("/plugins/gtk/X11/notify/notify_type")) {
		id = g_signal_connect(G_OBJECT(gtkconv->entry), "key-press-event",
		                      G_CALLBACK(unnotify_cb), conv);
		entry_ids = g_slist_append(entry_ids, GUINT_TO_POINTER(id));
	}

	purple_conversation_set_data(conv, "notify-imhtml-signals", imhtml_ids);
	purple_conversation_set_data(conv, "notify-entry-signals", entry_ids);

	return 0;
}
Example #3
0
static void
unnotify(PurpleConversation *conv, gboolean reset)
{
	PurpleConversation *active_conv = NULL;
	PidginWindow *purplewin = NULL;

	g_return_if_fail(conv != NULL);
	if (PIDGIN_CONVERSATION(conv) == NULL)
		return;

	purplewin = PIDGIN_CONVERSATION(conv)->win;
	active_conv = pidgin_conv_window_get_active_conversation(purplewin);

	/* reset the conversation window title */
	purple_conversation_autoset_title(active_conv);

	if (reset) {
		/* Only need to actually remove the urgent hinting here, since
		 * removing it just to have it readded in re-notify is an
		 * unnecessary couple extra RTs to the server */
		handle_urgent(purplewin, FALSE);
		purple_conversation_set_data(conv, "notify-message-count", GINT_TO_POINTER(0));
		/* Same logic as for the urgent hint, xprops are also a RT.
		 * This needs to go here so that it gets the updated message
		 * count. */
		handle_count_xprop(purplewin);
	}

	return;
}
Example #4
0
static gboolean twitter_conv_icon_displaying_chat_cb(PurpleAccount * account, const char *who, char **message, PurpleConversation * conv, PurpleMessageFlags flags, void *account_signal)
{
    GtkIMHtml      *imhtml;
    GtkTextBuffer  *text_buffer;
    gint            linenumber = 0;

    if (account != account_signal)
        return FALSE;

    purple_debug_info(PLUGIN_ID, "called %s\n", G_STRFUNC);

    /* get text buffer */
    imhtml = GTK_IMHTML(PIDGIN_CONVERSATION(conv)->imhtml);
    text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(imhtml));

    /* store number of lines */
    linenumber = gtk_text_buffer_get_line_count(text_buffer);

    //this is just used to pass the current line number (before the insertion of the new text)
    //to the _displayed_chat_cb func. 
    //Since pidgin is (mostly) single threaded, this is probably overkill and we could just use
    //a single global int. 
    //On another note, we don't insert the icon here because the message may not end up being displayed
    //based on what other plugins do
    purple_conversation_set_data(conv, PLUGIN_ID "-icon-ln", GINT_TO_POINTER(linenumber));

    return FALSE;
}
static void
hide_conv(PidginConversation *gtkconv, gboolean closetimer)
{
	GList *list;

	purple_signal_emit(pidgin_conversations_get_handle(),
			"conversation-hiding", gtkconv);

	for (list = g_list_copy(gtkconv->convs); list; list = g_list_delete_link(list, list)) {
		PurpleConversation *conv = list->data;
		if (closetimer) {
			guint timer = GPOINTER_TO_INT(purple_conversation_get_data(conv, "close-timer"));
			if (timer)
				purple_timeout_remove(timer);
			timer = purple_timeout_add_seconds(CLOSE_CONV_TIMEOUT_SECS, close_already, conv);
			purple_conversation_set_data(conv, "close-timer", GINT_TO_POINTER(timer));
		}
#if 0
		/* I will miss you */
		purple_conversation_set_ui_ops(conv, NULL);
#else
		pidgin_conv_window_remove_gtkconv(gtkconv->win, gtkconv);
		pidgin_conv_window_add_gtkconv(hidden_convwin, gtkconv);
#endif
	}
}
Example #6
0
static void
timestamp_new_convo(PurpleConversation *conv)
{
	if (!g_list_find(purple_get_conversations(), conv))
		return;

	purple_conversation_set_data(conv, "timestamp-last", GINT_TO_POINTER(0));
}
Example #7
0
void PurpleLine::signal_conversation_created(PurpleConversation *conv) {
    if (purple_conversation_get_account(conv) != acct)
        return;

    // Start queuing messages while the history is fetched
    purple_conversation_set_data(conv, "line-message-queue", new std::vector<line::Message>());

    fetch_conversation_history(conv, 10, false);
}
Example #8
0
static void twitter_conv_icon_conversation_created_cb(PurpleConversation * conv, PurpleAccount * account)
{
    GList         **conv_icons;
    if (purple_conversation_get_account(conv) != account)
        return;
    conv_icons = g_new0(GList *, 1);

    purple_conversation_set_data(conv, PLUGIN_ID "-conv-icons", conv_icons);
}
Example #9
0
static void
conv_created(PurpleConversation *conv)
{
	purple_conversation_set_data(conv, "notify-message-count",
	                           GINT_TO_POINTER(0));

	/* always attach the signals, notify() will take care of conversation
	 * type checking */
	attach_signals(conv);
}
Example #10
0
void irc_msg_join(struct irc_conn *irc, const char *name, const char *from, char **args)
{
	PurpleConnection *gc = purple_account_get_connection(irc->account);
	PurpleConversation *convo;
	char *nick = irc_mask_nick(from), *userhost;
	struct irc_buddy *ib;
	static int id = 1;

	if (!gc) {
		g_free(nick);
		return;
	}

	if (!purple_utf8_strcasecmp(nick, purple_connection_get_display_name(gc))) {
		/* We are joining a channel for the first time */
		serv_got_joined_chat(gc, id++, args[0]);
		g_free(nick);
		convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
							    args[0],
							    irc->account);

		if (convo == NULL) {
			purple_debug_error("irc", "tried to join %s but couldn't\n", args[0]);
			return;
		}
		purple_conversation_set_data(convo, IRC_NAMES_FLAG,
					   GINT_TO_POINTER(FALSE));
		/* Until purple_conversation_present does something that
		 * one would expect in Pidgin, this call produces buggy
		 * behavior both for the /join and auto-join cases. */
		/* purple_conversation_present(convo); */
		return;
	}

	convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, args[0], irc->account);
	if (convo == NULL) {
		purple_debug(PURPLE_DEBUG_ERROR, "irc", "JOIN for %s failed\n", args[0]);
		g_free(nick);
		return;
	}

	userhost = irc_mask_userhost(from);
	purple_conv_chat_add_user(PURPLE_CONV_CHAT(convo), nick, userhost, PURPLE_CBFLAGS_NONE, TRUE);

	if ((ib = g_hash_table_lookup(irc->buddies, nick)) != NULL) {
		ib->flag = TRUE;
		irc_buddy_status(nick, ib, irc);
	}

	g_free(userhost);
	g_free(nick);
}
Example #11
0
std::string PurpleLine::conv_attachment_add(PurpleConversation *conv,
    line::ContentType::type type, std::string id)
{
    auto atts = (std::vector<Attachment> *)purple_conversation_get_data(conv, "line-attachments");
    if (!atts) {
        atts = new std::vector<Attachment>();
        purple_conversation_set_data(conv, "line-attachments", atts);
    }

    atts->emplace_back(type, id);

    return std::to_string(atts->size());
}
Example #12
0
void PurpleLine::signal_deleting_conversation(PurpleConversation *conv) {
    if (purple_conversation_get_account(conv) != acct)
        return;

    auto queue = (std::vector<line::Message> *)
        purple_conversation_get_data(conv, "line-message-queue");

    if (queue) {
        purple_conversation_set_data(conv, "line-message-queue", nullptr);
        delete queue;
    }

    int64_t *end_seq_p = (int64_t *)purple_conversation_get_data(conv, "line-end-seq");
    if (end_seq_p) {
        purple_conversation_set_data(conv, "line-end-seq", nullptr);
        delete end_seq_p;
    }

    auto atts = (std::vector<Attachment> *)purple_conversation_get_data(conv, "line-attachments");
    if (atts) {
        purple_conversation_set_data(conv, "line-attachments", nullptr);
        delete atts;
    }
}
Example #13
0
static void
skypeweb_join_chat(PurpleConnection *pc, GHashTable *data)
{
	SkypeWebAccount *sa = purple_connection_get_protocol_data(pc);
	gchar *chatname;
	gchar *post;
	GString *url;
	PurpleChatConversation *chatconv;
	
	chatname = (gchar *)g_hash_table_lookup(data, "chatname");
	if (chatname == NULL)
	{
		return;
	}
	
	chatconv = purple_conversations_find_chat_with_account(chatname, sa->account);
	if (chatconv != NULL) {
		purple_conversation_present(PURPLE_CONVERSATION(chatconv));
		return;
	}
	
	url = g_string_new("/v1/threads/");
	g_string_append_printf(url, "%s", purple_url_encode(chatname));
	g_string_append(url, "/members/");
	g_string_append_printf(url, "8:%s", purple_url_encode(sa->username));
	
	post = "{\"role\":\"User\"}";
	
	skypeweb_post_or_get(sa, SKYPEWEB_METHOD_PUT | SKYPEWEB_METHOD_SSL, sa->messages_host, url->str, post, NULL, NULL, TRUE);
	
	g_string_free(url, TRUE);
	
	skypeweb_get_conversation_history(sa, chatname);
	skypeweb_get_thread_users(sa, chatname);
	
	chatconv = purple_serv_got_joined_chat(pc, g_str_hash(chatname), chatname);
	purple_conversation_set_data(PURPLE_CONVERSATION(chatconv), "chatname", g_strdup(chatname));
	
	purple_conversation_present(PURPLE_CONVERSATION(chatconv));
}
Example #14
0
static gboolean
timestamp_displaying_conv_msg(PurpleAccount *account, const char *who,
			      char **buffer, PurpleConversation *conv,
			      PurpleMessageFlags flags, void *data)
{
	time_t now = time(NULL) / interval * interval;
	time_t then;

	if (!g_list_find(purple_get_conversations(), conv))
		return FALSE;

	then = GPOINTER_TO_INT(purple_conversation_get_data(
		conv, "timestamp-last"));

	if (now - then >= interval) {
		timestamp_display(conv, then, now);
		purple_conversation_set_data(
			conv, "timestamp-last", GINT_TO_POINTER(now));
	}

	return FALSE;
}
Example #15
0
static int
notify(PurpleConversation *conv, gboolean increment)
{
	gint count;
	gboolean has_focus;
	PidginWindow *purplewin = NULL;

	if (conv == NULL || PIDGIN_CONVERSATION(conv) == NULL)
		return 0;

	/* We want to remove the notifications, but not reset the counter */
	unnotify(conv, FALSE);

	purplewin = PIDGIN_CONVERSATION(conv)->win;

	/* If we aren't doing notifications for this type of conversation, return */
	if (((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) &&
	     !purple_prefs_get_bool("/plugins/gtk/X11/notify/type_im")) ||
	    ((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) &&
	     !purple_prefs_get_bool("/plugins/gtk/X11/notify/type_chat")))
		return 0;

	g_object_get(G_OBJECT(purplewin->window),
	             "has-toplevel-focus", &has_focus, NULL);

	if (purple_prefs_get_bool("/plugins/gtk/X11/notify/type_focused") ||
	    !has_focus) {
		if (increment) {
			count = GPOINTER_TO_INT(purple_conversation_get_data(conv, "notify-message-count"));
			count++;
			purple_conversation_set_data(conv, "notify-message-count", GINT_TO_POINTER(count));
		}

		notify_win(purplewin, conv);
	}

	return 0;
}
Example #16
0
static void
deleting_conv(PurpleConversation *conv)
{
	PidginWindow *purplewin = NULL;
	PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);

	if (gtkconv == NULL)
		return;

	detach_signals(conv);

	purplewin = gtkconv->win;

	handle_urgent(purplewin, FALSE);
	purple_conversation_set_data(conv, "notify-message-count", GINT_TO_POINTER(0));

	return;

#if 0
	/* i think this line crashes */
	if (count_messages(purplewin))
		notify_win(purplewin);
#endif
}
Example #17
0
void PurpleLine::fetch_conversation_history(PurpleConversation *conv, int count, bool requested) {
    PurpleConversationType type = conv->type;
    std::string name(purple_conversation_get_name(conv));

    int64_t end_seq = -1;

    int64_t *end_seq_p = (int64_t *)purple_conversation_get_data(conv, "line-end-seq");
    if (end_seq_p)
        end_seq = *end_seq_p;

    if (end_seq != -1)
        c_out->send_getPreviousMessages(name, end_seq - 1, count);
    else
        c_out->send_getRecentMessages(name, count);

    c_out->send([this, requested, type, name, end_seq]() {
        int64_t new_end_seq = end_seq;

        std::vector<line::Message> recent_msgs;

        if (end_seq != -1)
            c_out->recv_getPreviousMessages(recent_msgs);
        else
            c_out->recv_getRecentMessages(recent_msgs);

        PurpleConversation *conv = purple_find_conversation_with_account(type, name.c_str(), acct);
        if (!conv)
            return; // Conversation died while fetching messages

        auto *queue = (std::vector<line::Message> *)
            purple_conversation_get_data(conv, "line-message-queue");

        purple_conversation_set_data(conv, "line-message-queue", nullptr);

        // Find least seq value from messages for future history queries
        for (line::Message &msg: recent_msgs) {
            if (msg.contentMetadata.count("seq")) {
                try {
                    int64_t seq = std::stoll(msg.contentMetadata["seq"]);

                    if (new_end_seq == -1 || seq < new_end_seq)
                        new_end_seq = seq;
                } catch (...) { /* ignore parse error */ }
            }
        }

        if (queue) {
            // If there's a message queue, remove any already-queued messages in the recent message
            // list to prevent them showing up twice.

            recent_msgs.erase(
                std::remove_if(
                    recent_msgs.begin(),
                    recent_msgs.end(),
                    [&queue](line::Message &rm) {
                        auto r = find_if(
                            queue->begin(),
                            queue->end(),
                            [&rm](line::Message &qm) { return qm.id == rm.id; });

                        return (r != queue->end());
                    }),
                recent_msgs.end());
        }

        if (recent_msgs.size()) {
            purple_conversation_write(
                conv,
                "",
                "<strong>Message history</strong>",
                (PurpleMessageFlags)PURPLE_MESSAGE_RAW,
                time(NULL));

            for (auto msgi = recent_msgs.rbegin(); msgi != recent_msgs.rend(); msgi++)
                write_message(*msgi, true);

            purple_conversation_write(
                conv,
                "",
                "<hr>",
                (PurpleMessageFlags)PURPLE_MESSAGE_RAW,
                time(NULL));
        } else {
            if (requested) {
                // If history was requested by the user and there is none, let the user know

                purple_conversation_write(
                    conv,
                    "",
                    "<strong>No more history</strong>",
                    (PurpleMessageFlags)PURPLE_MESSAGE_RAW,
                    time(NULL));
            }
        }

        // If there's a message queue, play it back now
        if (queue) {
            for (line::Message &msg: *queue)
                write_message(msg, false);

            delete queue;
        }

        int64_t *end_seq_p = (int64_t *)purple_conversation_get_data(conv, "line-end-seq");
        if (end_seq_p)
            delete end_seq_p;

        purple_conversation_set_data(conv, "line-end-seq", new int64_t(new_end_seq));
    });
}
Example #18
0
void irc_msg_names(struct irc_conn *irc, const char *name, const char *from, char **args)
{
	char *names, *cur, *end, *tmp, *msg;
	PurpleConversation *convo;

	if (!strcmp(name, "366")) {
		convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, args[1], irc->account);
		if (!convo) {
			purple_debug(PURPLE_DEBUG_ERROR, "irc", "Got a NAMES list for %s, which doesn't exist\n", args[1]);
			g_string_free(irc->names, TRUE);
			irc->names = NULL;
			return;
		}

		names = cur = g_string_free(irc->names, FALSE);
		irc->names = NULL;
		if (purple_conversation_get_data(convo, IRC_NAMES_FLAG)) {
			msg = g_strdup_printf(_("Users on %s: %s"), args[1], names ? names : "");
			if (purple_conversation_get_type(convo) == PURPLE_CONV_TYPE_CHAT)
				purple_conv_chat_write(PURPLE_CONV_CHAT(convo), "", msg, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL));
			else
				purple_conv_im_write(PURPLE_CONV_IM(convo), "", msg, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL));
			g_free(msg);
		} else {
			GList *users = NULL;
			GList *flags = NULL;

			while (*cur) {
				PurpleConvChatBuddyFlags f = PURPLE_CBFLAGS_NONE;
				end = strchr(cur, ' ');
				if (!end)
					end = cur + strlen(cur);
				if (*cur == '@') {
					f = PURPLE_CBFLAGS_OP;
					cur++;
				} else if (*cur == '%') {
					f = PURPLE_CBFLAGS_HALFOP;
					cur++;
				} else if(*cur == '+') {
					f = PURPLE_CBFLAGS_VOICE;
					cur++;
				} else if(irc->mode_chars
					  && strchr(irc->mode_chars, *cur)) {
					if (*cur == '~')
						f = PURPLE_CBFLAGS_FOUNDER;
					cur++;
				}
				tmp = g_strndup(cur, end - cur);
				users = g_list_prepend(users, tmp);
				flags = g_list_prepend(flags, GINT_TO_POINTER(f));
				cur = end;
				if (*cur)
					cur++;
			}

			if (users != NULL) {
				GList *l;

				purple_conv_chat_add_users(PURPLE_CONV_CHAT(convo), users, NULL, flags, FALSE);

				for (l = users; l != NULL; l = l->next)
					g_free(l->data);

				g_list_free(users);
				g_list_free(flags);
			}

			purple_conversation_set_data(convo, IRC_NAMES_FLAG,
						   GINT_TO_POINTER(TRUE));
		}
		g_free(names);
	} else {
		if (!irc->names)
			irc->names = g_string_new("");

		if (irc->names->len && irc->names->str[irc->names->len - 1] != ' ')
			irc->names = g_string_append_c(irc->names, ' ');
		irc->names = g_string_append(irc->names, args[3]);
	}
}