Philipp Hörist pushed to branch master at gajim / gajim
Commits: 7aa38beb by Philipp Hörist at 2022-10-17T23:11:41+02:00 new: Archive: Add new columns
- - - - - a4cff0e8 by Philipp Hörist at 2022-10-17T23:11:41+02:00 refactor: Remove unused code
We only use MAM for history
- - - - - 6f5a03d5 by Philipp Hörist at 2022-10-17T23:11:41+02:00 refactor: Remove unused code
- - - - - 8c4ee941 by Philipp Hörist at 2022-10-17T23:11:41+02:00 refactor: Simplify instances dict init
- - - - - bf75eda4 by Philipp Hörist at 2022-10-17T23:11:41+02:00 refactor: AccountWizard: Save account color early
- - - - - 2276c302 by Philipp Hörist at 2022-10-17T23:11:41+02:00 refactor: Settings: Align default settings with account creation
- - - - - 27a41e04 by Philipp Hörist at 2022-10-17T23:11:41+02:00 refactor: Move account interface methods into Application
- - - - -
11 changed files:
- gajim/common/application.py - gajim/common/events.py - gajim/common/modules/message.py - gajim/common/setting_values.py - gajim/common/storage/archive.py - gajim/common/structs.py - gajim/gtk/account_wizard.py - gajim/gtk/accounts.py - gajim/gtk/application.py - gajim/gtk/remove_account.py - gajim/gui_interface.py
Changes:
===================================== gajim/common/application.py ===================================== @@ -31,6 +31,8 @@ from gi.repository import Gio from gi.repository import GLib from gi.repository import Soup +from nbxmpp.const import ConnectionType +from nbxmpp.const import ConnectionProtocol
from gajim.common import app from gajim.common import ged @@ -40,10 +42,13 @@ from gajim.common.commands import ChatCommands from gajim.common.dbus import logind from gajim.common.events import AccountDisconnected +from gajim.common.events import AccountDisabled +from gajim.common.events import AccountEnabled from gajim.common.events import AllowGajimUpdateCheck from gajim.common.events import GajimUpdateAvailable from gajim.common.client import Client from gajim.common.helpers import make_http_request +from gajim.common.helpers import get_random_string from gajim.common.storage.events import EventStorage from gajim.common.task_manager import TaskManager from gajim.common.settings import Settings @@ -270,3 +275,88 @@ def _on_update_response(self, return
self._log.info('Gajim is up to date') + + def create_account(self, + account: str, + username: str, + domain: str, + password: str, + proxy_name: str, + custom_host: tuple[str, + ConnectionProtocol, + ConnectionType], + anonymous: bool = False + ) -> None: + + account_label = f'{username}@{domain}' + if anonymous: + username = 'anon' + account_label = f'anon@{domain}' + + config: dict[str, Union[str, int, bool]] = { + 'name': username, + 'resource': f'gajim.{get_random_string(8)}', + 'account_label': account_label, + 'hostname': domain, + 'anonymous_auth': anonymous, + } + + if proxy_name is not None: + config['proxy'] = proxy_name + + use_custom_host = custom_host is not None + config['use_custom_host'] = use_custom_host + if custom_host: + host, _protocol, type_ = custom_host + host, port = host.rsplit(':', maxsplit=1) + config['custom_port'] = int(port) + config['custom_host'] = host + config['custom_type'] = type_.value + + app.settings.add_account(account) + for opt, value in config.items(): + app.settings.set_account_setting(account, opt, value) # pyright: ignore # noqa + + # Password module depends on existing config + passwords.save_password(account, password) + + def enable_account(self, account: str) -> None: + app.connections[account] = Client(account) + + app.plugin_manager.register_modules_for_account( + app.connections[account]) + + app.automatic_rooms[account] = {} + app.to_be_removed[account] = [] + app.nicks[account] = app.settings.get_account_setting(account, 'name') + app.settings.set_account_setting(account, 'active', True) + + app.ged.raise_event(AccountEnabled(account=account)) + + app.get_client(account).change_status('online', '') + + def disable_account(self, account: str) -> None: + app.settings.set_account_setting(account, 'roster_version', '') + app.settings.set_account_setting(account, 'active', False) + + # Code in account-disabled handlers may use app.get_client() + app.ged.raise_event(AccountDisabled(account=account)) + + app.get_client(account).cleanup() + del app.connections[account] + if account in app.interface.instances: + del app.interface.instances[account] + del app.nicks[account] + del app.automatic_rooms[account] + del app.to_be_removed[account] + + def remove_account(self, account: str) -> None: + if app.settings.get_account_setting(account, 'active'): + self.disable_account(account) + + app.storage.cache.remove_roster(account) + # Delete password must be before del_per() because it calls set_per() + # which would recreate the account with defaults values if not found + passwords.delete_password(account) + app.settings.remove_account(account) + app.app.remove_account_actions(account)
===================================== gajim/common/events.py ===================================== @@ -393,7 +393,6 @@ class MessageReceived(ApplicationEvent): stanza_id: str fjid: str resource: str - session: Any delayed: Optional[float] msg_log_id: int displaymarking: Optional[Displaymarking]
===================================== gajim/common/modules/message.py ===================================== @@ -126,18 +126,6 @@ def _message_received(self,
stanza_id, message_id = self._get_unique_id(properties)
- if properties.type.is_groupchat and properties.has_server_delay: - # Only for XEP-0045 MUC History - # Don’t check for message text because the message could be - # encrypted. - if app.storage.archive.deduplicate_muc_message( - self._account, - properties.jid.bare, - properties.jid.resource, - properties.timestamp, - properties.id): - raise nbxmpp.NodeProcessed - if (properties.is_self_message or properties.is_muc_pm): archive_jid = self._con.get_own_jid().bare if app.storage.archive.find_stanza_id( @@ -150,8 +138,6 @@ def _message_received(self,
msgtxt = properties.body
- session = None - additional_data = AdditionalDataDict()
if properties.has_user_delay: @@ -182,7 +168,6 @@ def _message_received(self, 'stanza_id': stanza_id, 'unique_id': stanza_id or message_id, 'msgtxt': msgtxt, - 'session': session, 'delayed': properties.user_timestamp is not None, 'msg_log_id': None, 'displaymarking': displaymarking,
===================================== gajim/common/setting_values.py ===================================== @@ -407,13 +407,13 @@ class _ACCOUNT_DEFAULT: 'account': { 'account_color': 'rgb(85, 85, 85)', 'account_label': '', - 'active': True, + 'active': False, 'adjust_priority_with_status': False, 'anonymous_auth': False, 'answer_receipts': True, 'attached_gpg_keys': '', 'autoauth': False, - 'autoconnect': False, + 'autoconnect': True, 'autopriority_away': 40, 'autopriority_chat': 50, 'autopriority_dnd': 20, @@ -455,14 +455,14 @@ class _ACCOUNT_DEFAULT: 'resource': 'gajim.$rand', 'restore_last_status': False, 'roster_version': '', - 'savepass': False, + 'savepass': True, 'send_chatstate_default': 'composing_only', 'send_idle_time': True, 'send_marker_default': True, 'send_os_info': True, 'send_time_info': True, 'subscription_request_msg': '', - 'sync_with_global_status': False, + 'sync_with_global_status': True, 'test_ft_proxies_on_startup': False, 'use_custom_host': False, 'use_ft_proxies': False,
===================================== gajim/common/storage/archive.py ===================================== @@ -50,7 +50,7 @@ from gajim.common.storage.base import SqliteStorage from gajim.common.storage.base import timeit
-CURRENT_USER_VERSION = 6 +CURRENT_USER_VERSION = 7
ARCHIVE_SQL_STATEMENT = ''' CREATE TABLE jids( @@ -63,6 +63,8 @@ account_id INTEGER, jid_id INTEGER, contact_name TEXT, + occupant_id TEXT, + real_jid TEXT, time INTEGER, kind INTEGER, show INTEGER, @@ -258,6 +260,14 @@ def _migrate(self) -> None: ] self._execute_multiple(statements)
+ if user_version < 7: + statements = [ + 'ALTER TABLE logs ADD COLUMN "real_jid" TEXT', + 'ALTER TABLE logs ADD COLUMN "occupant_id" TEXT', + 'PRAGMA user_version=7' + ] + self._execute_multiple(statements) + @staticmethod def _like(search_str: str) -> str: return f'%{search_str}%' @@ -865,59 +875,6 @@ def get_recent_muc_nicks(self, contact: GroupchatContact) -> list[str]:
return nicknames
- @timeit - def deduplicate_muc_message(self, - account: str, - jid: str, - resource: str, - timestamp: float, - message_id: str - ) -> bool: - ''' - Check if a message is already in the `logs` table - - :param account: The account - - :param jid: The muc jid as string - - :param resource: The resource - - :param timestamp: The timestamp in UTC epoch - - :param message_id: The message-id - ''' - - # Add 60 seconds around the timestamp - start_time = timestamp - 60 - end_time = timestamp + 60 - - account_id = self.get_account_id(account) - log.debug('Search for MUC duplicate') - log.debug('start: %s, end: %s, jid: %s, resource: %s, message-id: %s', - start_time, end_time, jid, resource, message_id) - - sql = ''' - SELECT * FROM logs - NATURAL JOIN jids WHERE - jid = ? AND - contact_name = ? AND - message_id = ? AND - account_id = ? AND - time BETWEEN ? AND ? - ''' - - result = self._con.execute(sql, (jid, - resource, - message_id, - account_id, - start_time, - end_time)).fetchone() - - if result is not None: - log.debug('Found duplicate') - return True - return False - @timeit def find_stanza_id(self, account: str,
===================================== gajim/common/structs.py ===================================== @@ -158,7 +158,6 @@ def __init__(self, self.timestamp = None self.message_id = None self.stanza = None - self.session = None self.delayed = None # TODO never set
self.is_loggable = True
===================================== gajim/gtk/account_wizard.py ===================================== @@ -215,7 +215,7 @@ def _on_assistant_button_clicked(self,
elif button_name == 'connect': if page == 'success': - app.interface.enable_account(self.get_page('success').account) + app.app.enable_account(self.get_page('success').account) self.destroy()
elif button_name == 'back': @@ -371,12 +371,12 @@ def _on_login_successful(self, client: Client, _signal_name: str) -> None: if client.proxy is not None: proxy_name = self.get_page('advanced').get_proxy()
- app.interface.create_account(account, - client.username, - client.domain, - client.password, - proxy_name, - client.custom_host) + app.app.create_account(account, + client.username, + client.domain, + client.password, + proxy_name, + client.custom_host) self.get_page('success').set_account(account) self.show_page('success', Gtk.StackTransitionType.SLIDE_LEFT)
@@ -393,13 +393,13 @@ def _on_anonymous_supported(self, if client.proxy is not None: proxy_name = self.get_page('advanced').get_proxy()
- app.interface.create_account(account, - None, - client.domain, - client.password, - proxy_name, - client.custom_host, - anonymous=True) + app.app.create_account(account, + None, + client.domain, + client.password, + proxy_name, + client.custom_host, + anonymous=True) self.get_page('success').set_account(account) self.show_page('success', Gtk.StackTransitionType.SLIDE_LEFT)
@@ -549,12 +549,12 @@ def _on_register_result(self, task: Task) -> None: if self._client.proxy is not None: proxy_name = self.get_page('advanced').get_proxy()
- app.interface.create_account(account, - username, - self._client.domain, - password, - proxy_name, - self._client.custom_host) + app.app.create_account(account, + username, + self._client.domain, + password, + proxy_name, + self._client.custom_host)
self.get_page('success').set_account(account) self.show_page('success', Gtk.StackTransitionType.SLIDE_LEFT) @@ -1080,6 +1080,7 @@ def set_account(self, account: str) -> None: self._ui.account_color_button.set_rgba(rgba) self._color = rgba.to_string() self._set_badge_color(self._color) + self._save_config()
@property def account(self) -> Optional[str]:
===================================== gajim/gtk/accounts.py ===================================== @@ -569,9 +569,9 @@ def _disable() -> None: return Gdk.EVENT_STOP
if state: - app.interface.enable_account(account) + app.app.enable_account(account) else: - app.interface.disable_account(account) + app.app.disable_account(account)
return Gdk.EVENT_PROPAGATE
@@ -582,7 +582,7 @@ def _on_state_changed(self, ) -> None:
if client_state.is_disconnected: - app.interface.disable_account(client.account) + app.app.disable_account(client.account)
class AddNewAccountPage(Gtk.Box):
===================================== gajim/gtk/application.py ===================================== @@ -47,6 +47,8 @@ from nbxmpp.namespaces import Namespace from nbxmpp import JID from nbxmpp.protocol import InvalidJid +from nbxmpp.const import ConnectionType +from nbxmpp.const import ConnectionProtocol from gi.repository import Gio from gi.repository import GLib from gi.repository import Gtk @@ -70,6 +72,7 @@ from gajim.gui import menus from gajim.gui import structs from gajim.gui.about import AboutDialog +from gajim.gui.accounts import AccountsWindow from gajim.gui.avatar import AvatarStorage from gajim.gui.builder import get_builder from gajim.gui.const import ACCOUNT_ACTIONS @@ -83,6 +86,7 @@ from gajim.gui.discovery import ServiceDiscoveryWindow from gajim.gui.start_chat import StartChatDialog from gajim.gui.util import get_app_window +from gajim.gui.util import get_app_windows from gajim.gui.util import load_user_iconsets from gajim.gui.util import open_window
@@ -521,6 +525,66 @@ def _on_feature_discovered(self, event: events.FeatureDiscovered) -> None: action = '%s-block-contact' % event.account self.set_action_state(action, True)
+ def create_account(self, + account: str, + username: str, + domain: str, + password: str, + proxy_name: str, + custom_host: tuple[str, + ConnectionProtocol, + ConnectionType], + anonymous: bool = False + ) -> None: + + CoreApplication.create_account(self, + account, + username, + domain, + password, + proxy_name, + custom_host, + anonymous) + + app.css_config.refresh() + + # Action must be added before account window is updated + self.add_account_actions(account) + + window = cast(AccountsWindow, get_app_window('AccountsWindow')) + if window is not None: + window.add_account(account) + + def enable_account(self, account: str) -> None: + CoreApplication.enable_account(self, account) + menus.build_accounts_menu() + self.update_app_actions_state() + window = cast(AccountsWindow, get_app_window('AccountsWindow')) + if window is not None: + window.enable_account(account, True) + + def disable_account(self, account: str) -> None: + for win in get_app_windows(account): + # Close all account specific windows, except the RemoveAccount + # dialog. It shows if the removal was successful. + if type(win).__name__ == 'RemoveAccount': + continue + win.destroy() + + CoreApplication.disable_account(self, account) + + menus.build_accounts_menu() + self.update_app_actions_state() + + def remove_account(self, account: str) -> None: + CoreApplication.remove_account(self, account) + + self.remove_account_actions(account) + + window = cast(AccountsWindow, get_app_window('AccountsWindow')) + if window is not None: + window.remove_account(account) + # Action Callbacks
@staticmethod @@ -580,6 +644,9 @@ def _on_services_action(_action: Gio.SimpleAction, param: GLib.Variant) -> None: account = param.get_string() server_jid = app.settings.get_account_setting(account, 'hostname') + if account not in app.interface.instances: + app.interface.instances[account] = {'disco': {}} + disco = app.interface.instances[account]['disco'] if server_jid in disco: disco[server_jid].window.present()
===================================== gajim/gtk/remove_account.py ===================================== @@ -89,7 +89,7 @@ def _on_account_disconnected(self, _event: AccountDisconnected) -> None:
if self._account_removed: self.show_page('success') - app.interface.remove_account(self.account) + app.app.remove_account(self.account)
def _set_remove_from_server_checkbox(self) -> None: enabled = self._client is not None and self._client.state.is_available @@ -126,7 +126,7 @@ def _on_remove(self, *args: Any) -> None: return
if self._client is None or self._client.state.is_disconnected: - app.interface.remove_account(self.account) + app.app.remove_account(self.account) self.show_page('success') return
===================================== gajim/gui_interface.py ===================================== @@ -57,10 +57,7 @@ from gajim.common import proxy65_manager from gajim.common import socks5 from gajim.common import helpers -from gajim.common import passwords
-from gajim.common.events import AccountEnabled -from gajim.common.events import AccountDisabled from gajim.common.events import FileCompleted from gajim.common.events import FileHashError from gajim.common.events import FileProgress @@ -69,7 +66,6 @@ from gajim.common.modules.contacts import GroupchatContact from gajim.common.structs import OutgoingMessage from gajim.common.i18n import _ -from gajim.common.client import Client from gajim.common.const import FTState from gajim.common.file_props import FileProp from gajim.common.types import ChatContactT @@ -80,10 +76,6 @@ from gajim.gui.filechoosers import FileChooserDialog from gajim.gui.file_transfer_send import SendFileDialog from gajim.gui.filetransfer import FileTransfersWindow -from gajim.gui.menus import build_accounts_menu -from gajim.gui.util import get_app_window -from gajim.gui.util import get_app_windows -from gajim.gui.util import get_color_for_account from gajim.gui.control import ChatControl from gajim.plugins.repository import PluginRepository
@@ -115,10 +107,6 @@ def __init__(self): self.instances: dict[str, Any] = {}
for acc in app.settings.get_active_accounts(): - self.instances[acc] = { - 'infos': {}, - 'disco': {} - } app.automatic_rooms[acc] = {} app.to_be_removed[acc] = [] app.nicks[acc] = app.settings.get_account_setting(acc, 'name') @@ -128,7 +116,6 @@ def _create_core_handlers_list(self) -> None: self.handlers = { 'signed-in': [self.handle_event_signed_in], 'message-sent': [self.handle_event_msgsent], - 'message-not-sent': [self.handle_event_msgnotsent], } # pylint: enable=line-too-long
@@ -179,24 +166,6 @@ def handle_event_msgsent(event): return helpers.play_sound('message_sent', event.account)
- @staticmethod - def handle_event_msgnotsent(event): - # ('MSGNOTSENT', account, (jid, ierror_msg, msg, time, session)) - msg = _('error while sending %(message)s ( %(error)s )') % { - 'message': event.message, - 'error': event.error} - if not event.session: - # No session. This can happen when sending a message from - # gajim-remote - log.warning(msg) - return - event.session.roster_message( - event.jid, - msg, - event.time_, - event.conn.name, - msg_type='error') - # Jingle File Transfer @staticmethod def handle_event_file_error(title: str, message: str) -> None: @@ -469,125 +438,6 @@ def start_chat_from_jid(account: str, app.app.activate_action( 'start-chat', GLib.Variant('as', [str(jid), message or '']))
- @staticmethod - def create_account(account: str, - username: str, - domain: str, - password: str, - proxy_name: str, - custom_host: str, - anonymous: bool = False - ) -> None: - - account_label = f'{username}@{domain}' - if anonymous: - username = 'anon' - account_label = f'anon@{domain}' - - config = {} - config['active'] = False - config['name'] = username - config['resource'] = f'gajim.{helpers.get_random_string(8)}' - config['account_label'] = account_label - config['account_color'] = get_color_for_account(f'{username}@{domain}') - config['hostname'] = domain - config['savepass'] = True - config['anonymous_auth'] = anonymous - config['autoconnect'] = True - config['sync_with_global_status'] = True - - if proxy_name is not None: - config['proxy'] = proxy_name - - use_custom_host = custom_host is not None - config['use_custom_host'] = use_custom_host - if custom_host: - host, _protocol, type_ = custom_host - host, port = host.rsplit(':', maxsplit=1) - config['custom_port'] = int(port) - config['custom_host'] = host - config['custom_type'] = type_.value - - app.settings.add_account(account) - for opt, value in config.items(): - app.settings.set_account_setting(account, opt, value) - - # Password module depends on existing config - passwords.save_password(account, password) - - app.css_config.refresh() - - # Action must be added before account window is updated - app.app.add_account_actions(account) - - window = get_app_window('AccountsWindow') - if window is not None: - window.add_account(account) - - def enable_account(self, account: str) -> None: - app.connections[account] = Client(account) - - app.plugin_manager.register_modules_for_account( - app.connections[account]) - - # update variables - self.instances[account] = { - 'infos': {}, - 'disco': {} - } - - app.automatic_rooms[account] = {} - app.to_be_removed[account] = [] - app.nicks[account] = app.settings.get_account_setting(account, 'name') - app.settings.set_account_setting(account, 'active', True) - build_accounts_menu() - app.app.update_app_actions_state() - - app.ged.raise_event(AccountEnabled(account=account)) - - app.get_client(account).change_status('online', '') - window = get_app_window('AccountsWindow') - if window is not None: - GLib.idle_add(window.enable_account, account, True) - - def disable_account(self, account: str) -> None: - for win in get_app_windows(account): - # Close all account specific windows, except the RemoveAccount - # dialog. It shows if the removal was successful. - if type(win).__name__ == 'RemoveAccount': - continue - win.destroy() - - app.settings.set_account_setting(account, 'roster_version', '') - app.settings.set_account_setting(account, 'active', False) - build_accounts_menu() - app.app.update_app_actions_state() - - # Code in account-disabled handlers may use app.get_client() - app.ged.raise_event(AccountDisabled(account=account)) - - app.get_client(account).cleanup() - del app.connections[account] - del self.instances[account] - del app.nicks[account] - del app.automatic_rooms[account] - del app.to_be_removed[account] - - def remove_account(self, account: str) -> None: - if app.settings.get_account_setting(account, 'active'): - self.disable_account(account) - - app.storage.cache.remove_roster(account) - # Delete password must be before del_per() because it calls set_per() - # which would recreate the account with defaults values if not found - passwords.delete_password(account) - app.settings.remove_account(account) - app.app.remove_account_actions(account) - - window = get_app_window('AccountsWindow') - if window is not None: - window.remove_account(account) - def autoconnect(self) -> None: ''' Auto connect at startup
View it on GitLab: https://dev.gajim.org/gajim/gajim/-/compare/99f66cdb0a7d9ef9a70c4b743aa1f0ea...