Thu, 02 Nov 2023 23:38:51 -0500
Add symbol visibility on IRCv3 protocol plugin
This only adds visibility to things that have `Since: 3.0.0` _and_ are not already tagged with `G_GNUC_INTERNAL`.
It also assumes that the version is the same as libpurple, but that 3.0 is the minimum instead of 2.0, so everything is `PURPLE_IRCV3_AVAILABLE_IN_ALL`.
Testing Done:
Compiled on Linux and Windows.
Bugs closed: PIDGIN-17840
Reviewed at https://reviews.imfreedom.org/r/2773/
/* * Purple - Internet Messaging Library * Copyright (C) Pidgin Developers <devel@pidgin.im> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see <https://www.gnu.org/licenses/>. */ #include <glib/gi18n-lib.h> #include "purpleircv3protocolconversation.h" #include "purpleircv3connection.h" #include "purpleircv3core.h" /****************************************************************************** * PurpleProtocolConversation Implementation *****************************************************************************/ static void purple_ircv3_protocol_conversation_send_message_async(PurpleProtocolConversation *protocol, PurpleConversation *conversation, PurpleMessage *message, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data) { PurpleIRCv3Connection *v3_connection = NULL; PurpleAccount *account = NULL; PurpleConnection *connection = NULL; GTask *task = NULL; const char *id = NULL; account = purple_conversation_get_account(conversation); connection = purple_account_get_connection(account); v3_connection = PURPLE_IRCV3_CONNECTION(connection); id = purple_conversation_get_id(conversation); /* TODO: the new message dialog sets the name but not the id and we want to * use the id only, so for now if id is NULL we grab the name. */ if(purple_strempty(id)) { id = purple_conversation_get_name(conversation); } purple_ircv3_connection_writef(v3_connection, "PRIVMSG %s :%s", id, purple_message_get_contents(message)); task = g_task_new(protocol, cancellable, callback, data); g_task_return_boolean(task, TRUE); g_clear_object(&task); /* This will be made conditional when we add echo-message support. * https://ircv3.net/specs/extensions/echo-message */ purple_conversation_write_message(conversation, message); } static gboolean purple_ircv3_protocol_conversation_send_message_finish(G_GNUC_UNUSED PurpleProtocolConversation *protocol, GAsyncResult *result, GError **error) { return g_task_propagate_boolean(G_TASK(result), error); } static PurpleChannelJoinDetails * purple_ircv3_protocol_conversation_get_channel_join_details(G_GNUC_UNUSED PurpleProtocolConversation *protocol, G_GNUC_UNUSED PurpleAccount *account) { return purple_channel_join_details_new(FALSE, TRUE); } static void purple_ircv3_protocol_conversation_join_channel_async(PurpleProtocolConversation *protocol, PurpleAccount *account, PurpleChannelJoinDetails* details, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer data) { PurpleIRCv3Connection *v3_connection = NULL; PurpleConnection *connection = NULL; PurpleConversation *conversation = NULL; PurpleConversationManager *manager = NULL; GString *cmd = NULL; GTask *task = NULL; const char *name = NULL; const char *password = NULL; connection = purple_account_get_connection(account); v3_connection = PURPLE_IRCV3_CONNECTION(connection); task = g_task_new(protocol, cancellable, callback, data); /* Validate that the name isn't empty. */ /* TODO: check that name match the ISUPPORT channel prefixes. */ name = purple_channel_join_details_get_name(details); if(purple_strempty(name)) { g_task_return_new_error(task, PURPLE_IRCV3_DOMAIN, 0, "channel name is empty"); g_clear_object(&task); return; } manager = purple_conversation_manager_get_default(); conversation = purple_conversation_manager_find_with_id(manager, account, name); /* If the conversation already exists, just return TRUE. */ if(PURPLE_IS_CONVERSATION(conversation)) { g_task_return_boolean(task, TRUE); g_clear_object(&task); return; } /* Build our join string. */ cmd = g_string_new("JOIN "); g_string_append_printf(cmd, "%s", name); password = purple_channel_join_details_get_password(details); if(!purple_strempty(password)) { g_string_append_printf(cmd, " %s", password); } conversation = g_object_new( PURPLE_TYPE_CONVERSATION, "account", account, "type", PurpleConversationTypeChannel, "id", name, "name", name, NULL); purple_conversation_manager_register(manager, conversation); g_clear_object(&conversation); purple_ircv3_connection_writef(v3_connection, "%s", cmd->str); g_string_free(cmd, TRUE); g_task_return_boolean(task, TRUE); g_clear_object(&task); } static gboolean purple_ircv3_protocol_conversation_join_channel_finish(G_GNUC_UNUSED PurpleProtocolConversation *protocol, GAsyncResult *result, GError **error) { return g_task_propagate_boolean(G_TASK(result), error); } void purple_ircv3_protocol_conversation_init(PurpleProtocolConversationInterface *iface) { iface->send_message_async = purple_ircv3_protocol_conversation_send_message_async; iface->send_message_finish = purple_ircv3_protocol_conversation_send_message_finish; iface->get_channel_join_details = purple_ircv3_protocol_conversation_get_channel_join_details; iface->join_channel_async = purple_ircv3_protocol_conversation_join_channel_async; iface->join_channel_finish = purple_ircv3_protocol_conversation_join_channel_finish; }