diff --git a/gajim/common/connection_handlers.py b/gajim/common/connection_handlers.py index 883b6aa61..657067170 100644 --- a/gajim/common/connection_handlers.py +++ b/gajim/common/connection_handlers.py @@ -479,6 +479,22 @@ class ConnectionVcard: self.connection.SendAndCallForResponse( iq, self._avatar_publish_result, {'sha': sha}) + def upload_room_avatar(self, room_jid, data): + iq = nbxmpp.Iq(typ='set', to=room_jid) + vcard = iq.addChild('vCard', namespace=nbxmpp.NS_VCARD) + photo = vcard.addChild('PHOTO') + photo.addChild('TYPE', payload='image/png') + photo.addChild('BINVAL', payload=data) + + self.connection.SendAndCallForResponse( + iq, self._upload_room_avatar_result) + + def _upload_room_avatar_result(self, stanza): + if not nbxmpp.isResultNode(stanza): + reason = stanza.getErrorMsg() or stanza.getError() + app.nec.push_incoming_event(InformationEvent( + None, dialog_name='avatar-upload-error', args=reason)) + def _avatar_publish_result(self, con, stanza, sha): if stanza.getType() == 'result': current_sha = app.config.get_per( diff --git a/gajim/dialog_messages.py b/gajim/dialog_messages.py index 67d9e3e9e..2fc56e5cf 100644 --- a/gajim/dialog_messages.py +++ b/gajim/dialog_messages.py @@ -173,6 +173,10 @@ messages = { _('For the choosen encryption there is no encryption method available'), ErrorDialog), + 'avatar-upload-error': Message( + _('Avatar upload failed'), + '%s', + ErrorDialog), } diff --git a/gajim/groupchat_control.py b/gajim/groupchat_control.py index d99c2bf85..21a60fc90 100644 --- a/gajim/groupchat_control.py +++ b/gajim/groupchat_control.py @@ -29,6 +29,7 @@ import time import locale +import base64 from gi.repository import Gtk from gi.repository import Gdk @@ -61,6 +62,7 @@ from gajim.common import contacts from gajim.chat_control import ChatControl from gajim.chat_control_base import ChatControlBase +from gajim.filechoosers import AvatarChooserDialog from gajim.command_system.implementation.hosts import PrivateChatCommands from gajim.command_system.implementation.hosts import GroupChatCommands @@ -558,6 +560,7 @@ class GroupchatControl(ChatControlBase): ('bookmark-', self._on_bookmark_room), ('request-voice-', self._on_request_voice), ('execute-command-', self._on_execute_command), + ('upload-avatar-', self._on_upload_avatar), ] for action in actions: @@ -644,6 +647,10 @@ class GroupchatControl(ChatControlBase): tooltip_text = _('No File Transfer available') self.sendfile_button.set_tooltip_text(tooltip_text) + # Upload Avatar + vcard_support = muc_caps_cache.supports(self.room_jid, nbxmpp.NS_VCARD) + win.lookup_action('upload-avatar-' + self.control_id).set_enabled( + online and vcard_support and contact.affiliation == 'owner') def _connect_window_state_change(self, parent_win): if self._state_change_handler_id is None: @@ -759,6 +766,27 @@ class GroupchatControl(ChatControlBase): """ adhoc_commands.CommandWindow(self.account, self.room_jid) + def _on_upload_avatar(self, action, param): + def _on_accept(filename): + with open(filename, 'rb') as file: + data = file.read() + sha = app.interface.save_avatar(data, publish=True) + if sha is None: + dialogs.ErrorDialog( + _('Could not load image'), + transient_for=self.parent_win.window) + return + + publish = app.interface.get_avatar(sha, publish=True) + avatar = base64.b64encode(publish).decode('utf-8') + + app.connections[self.account].upload_room_avatar( + self.room_jid, avatar) + + AvatarChooserDialog(_on_accept, + transient_for=self.parent_win.window, + modal=True) + def show_roster(self): new_state = not self.hpaned.get_child2().is_visible() image = self.hide_roster_button.get_image() diff --git a/gajim/gui_menu_builder.py b/gajim/gui_menu_builder.py index 5442a2713..a26a047eb 100644 --- a/gajim/gui_menu_builder.py +++ b/gajim/gui_menu_builder.py @@ -642,6 +642,7 @@ def get_groupchat_menu(control_id): (_('Manage Room'), [ ('win.change-subject-', _('Change Subject')), ('win.configure-', _('Configure Room')), + ('win.upload-avatar-', _('Upload Avatar…')), ('win.destroy-', _('Destroy Room')), ]), ('win.change-nick-', _('Change Nick')),