1
0
Fork 0
forked from sch/KaikOut

Automate installation of configurations;

Update document README.
This commit is contained in:
Schimon Jehudah, Adv. 2024-11-21 12:11:11 +02:00
parent ff2e1835d2
commit c9bf69bbfd
9 changed files with 137 additions and 88 deletions

View file

@ -99,12 +99,6 @@ Start by executing the command `kaikout` and enter Username and Password of an e
$ kaikout $ kaikout
``` ```
You can also start KaikOut as follows:
```
$ kaikout --jid ACCOUNT_JABBER_ID --password ACCOUNT_PASSWORD
```
It is advised to use a dedicated extra account for KaikOut. It is advised to use a dedicated extra account for KaikOut.
## Recommended Clients ## Recommended Clients

View file

@ -6,17 +6,37 @@
# See the file LICENSE for copying permission. # See the file LICENSE for copying permission.
# from kaikout.about import Documentation # from kaikout.about import Documentation
from kaikout.utilities import Config from kaikout.utilities import Config, Toml
# from kaikout.xmpp.chat import XmppChat # from kaikout.xmpp.chat import XmppChat
from kaikout.xmpp.client import XmppClient from kaikout.xmpp.client import XmppClient
from getpass import getpass from getpass import getpass
from argparse import ArgumentParser from argparse import ArgumentParser
import logging import logging
# import os import os
import shutil
# import slixmpp # import slixmpp
# import sys # import sys
def main(): def main():
directory = os.path.dirname(__file__)
# Copy data files
directory_data = Config.get_default_config_directory()
# TODO Utilize the actual data directory
#directory_data = Config.get_default_data_directory()
if not os.path.exists(directory_data):
directory_assets = os.path.join(directory, 'assets')
directory_assets_new = shutil.copytree(directory_assets, directory_data)
print(f'Data directory {directory_assets_new} has been created and populated.')
# Copy settings files
directory_settings = Config.get_default_config_directory()
if not os.path.exists(directory_settings):
directory_configs = os.path.join(directory, 'configs')
directory_settings_new = shutil.copytree(directory_configs, directory_settings)
print(f'Configuration directory {directory_settings_new} has been created and populated.')
# Setup the command line arguments. # Setup the command line arguments.
parser = ArgumentParser(description=XmppClient.__doc__) parser = ArgumentParser(description=XmppClient.__doc__)
@ -28,32 +48,52 @@ def main():
action="store_const", dest="loglevel", action="store_const", dest="loglevel",
const=logging.DEBUG, default=logging.INFO) const=logging.DEBUG, default=logging.INFO)
# JID and password options.
parser.add_argument("-j", "--jid", dest="jid",
help="JID to use")
parser.add_argument("-p", "--password", dest="password",
help="password to use")
args = parser.parse_args() args = parser.parse_args()
# Setup logging. # Setup logging.
logging.basicConfig(level=args.loglevel, logging.basicConfig(level=args.loglevel,
format='%(levelname)-8s %(message)s') format='%(levelname)-8s %(message)s')
account_xmpp = Config.get_values('accounts.toml', 'xmpp') # Configure settings file
file_settings = os.path.join(directory_settings, 'accounts.toml')
if not os.path.exists(file_settings):
directory_configs = os.path.join(directory, 'configs')
file_settings_empty = os.path.join(directory_configs, 'accounts.toml')
shutil.copyfile(file_settings_empty, file_settings)
if args.jid is None and not account_xmpp['client']['jid']: data_settings = Toml.open_file(file_settings)
args.jid = input("Username: ")
if args.password is None and not account_xmpp['client']['password']: # Configure account
args.password = getpass("Password: ") data_settings_account = data_settings['xmpp']['client']
settings_account = {
'alias': 'Set an Alias',
'jid': 'Set a Jabber ID',
'password': 'Input Password'
}
for key in settings_account:
data_settings_account_value = data_settings_account[key]
if not data_settings_account_value:
settings_account_message = settings_account[key]
while not data_settings_account_value:
if key == 'password':
data_settings_account_value = getpass(f'{settings_account_message}: ')
else:
data_settings_account_value = input(f'{settings_account_message}: ')
data_settings_account[key] = data_settings_account_value
Toml.save_file(file_settings, data_settings)
# Try configuration file # Try configuration file
account_xmpp = Config.get_values('accounts.toml', 'xmpp')
if 'client' in account_xmpp: if 'client' in account_xmpp:
jid = account_xmpp['client']['jid'] account_xmpp_client = account_xmpp['client']
password = account_xmpp['client']['password'] jid = account_xmpp_client['jid']
alias = account_xmpp['client']['alias'] if 'alias' in account_xmpp['client'] else None password = account_xmpp_client['password']
hostname = account_xmpp['client']['hostname'] if 'hostname' in account_xmpp['client'] else None alias = account_xmpp_client['alias'] if 'alias' in account_xmpp_client else None
port = account_xmpp['client']['port'] if 'port' in account_xmpp['client'] else None hostname = account_xmpp_client['hostname'] if 'hostname' in account_xmpp_client else None
port = account_xmpp_client['port'] if 'port' in account_xmpp_client else None
XmppClient(jid, password, hostname, port, alias) XmppClient(jid, password, hostname, port, alias)
if __name__ == '__main__': if __name__ == '__main__':

View file

@ -16,16 +16,16 @@ class Config:
def get_default_data_directory(): def get_default_data_directory():
if os.environ.get('HOME'): directory_home = os.environ.get('HOME')
data_home = os.path.join(os.environ.get('HOME'), '.local', 'share') if directory_home:
data_home = os.path.join(directory_home, '.local', 'share')
return os.path.join(data_home, 'kaikout') return os.path.join(data_home, 'kaikout')
elif sys.platform == 'win32': elif sys.platform == 'win32':
data_home = os.environ.get('APPDATA') data_home = os.environ.get('APPDATA')
if data_home is None: if data_home is None:
return os.path.join( return 'kaikout_data'
os.path.dirname(__file__) + '/kaikout_data')
else: else:
return os.path.join(os.path.dirname(__file__) + '/kaikout_data') return 'kaikout_data'
def get_default_config_directory(): def get_default_config_directory():
@ -42,19 +42,20 @@ class Config:
str str
Path to configuration directory. Path to configuration directory.
""" """
# config_home = xdg.BaseDirectory.xdg_config_home # directory_config_home = xdg.BaseDirectory.xdg_config_home
config_home = os.environ.get('XDG_CONFIG_HOME') directory_config_home = os.environ.get('XDG_CONFIG_HOME')
if config_home is None: if directory_config_home is None:
if os.environ.get('HOME') is None: directory_home = os.environ.get('HOME')
if directory_home is None:
if sys.platform == 'win32': if sys.platform == 'win32':
config_home = os.environ.get('APPDATA') directory_config_home = os.environ.get('APPDATA')
if config_home is None: if directory_config_home is None:
return os.path.abspath('.') return 'kaikout_config'
else: else:
return os.path.abspath('.') return 'kaikout_config'
else: else:
config_home = os.path.join(os.environ.get('HOME'), '.config') directory_config_home = os.path.join(directory_home, '.config')
return os.path.join(config_home, 'kaikout') return os.path.join(directory_config_home, 'kaikout')
def get_values(filename, key=None): def get_values(filename, key=None):

View file

@ -26,8 +26,8 @@ BDAY = "20 June 2024"
#DESC = "" #DESC = ""
[xmpp.client] [xmpp.client]
alias = "KaikOut" alias = ""
jid = "/KaikOut" jid = ""
password = "" password = ""
[tox] [tox]

View file

@ -482,10 +482,9 @@ class Toml:
elif sys.platform == 'win32': elif sys.platform == 'win32':
data_home = os.environ.get('APPDATA') data_home = os.environ.get('APPDATA')
if data_home is None: if data_home is None:
return os.path.join( return 'kaikout_data'
os.path.dirname(__file__), 'kaikout_data')
else: else:
return os.path.join(os.path.dirname(__file__), 'kaikout_data') return 'kaikout_data'
def get_data_file(data_dir, room): def get_data_file(data_dir, room):

View file

@ -37,16 +37,16 @@ class Config:
str str
Path to data directory. Path to data directory.
""" """
if os.environ.get('HOME'): directory_home = os.environ.get('HOME')
data_home = os.path.join(os.environ.get('HOME'), '.local', 'share') if directory_home:
data_home = os.path.join(directory_home, '.local', 'share')
return os.path.join(data_home, 'kaikout') return os.path.join(data_home, 'kaikout')
elif sys.platform == 'win32': elif sys.platform == 'win32':
data_home = os.environ.get('APPDATA') data_home = os.environ.get('APPDATA')
if data_home is None: if data_home is None:
return os.path.join( return 'kaikout_data'
os.path.dirname(__file__), 'kaikout_data')
else: else:
return os.path.join(os.path.dirname(__file__), 'kaikout_data') return 'kaikout_data'
def get_default_config_directory(): def get_default_config_directory():
@ -63,21 +63,20 @@ class Config:
str str
Path to configuration directory. Path to configuration directory.
""" """
# config_home = xdg.BaseDirectory.xdg_config_home # directory_config_home = xdg.BaseDirectory.xdg_config_home
config_home = os.environ.get('XDG_CONFIG_HOME') directory_config_home = os.environ.get('XDG_CONFIG_HOME')
if config_home is None: if directory_config_home is None:
if os.environ.get('HOME') is None: directory_home = os.environ.get('HOME')
if directory_home is None:
if sys.platform == 'win32': if sys.platform == 'win32':
config_home = os.environ.get('APPDATA') directory_config_home = os.environ.get('APPDATA')
if config_home is None: if directory_config_home is None:
return os.path.abspath('.') return 'kaikout_config'
else: else:
return os.path.abspath('.') return 'kaikout_config'
else: else:
config_home = os.path.join( directory_config_home = os.path.join(directory_home, '.config')
os.environ.get('HOME'), '.config' return os.path.join(directory_config_home, 'kaikout')
)
return os.path.join(config_home, 'kaikout')
def get_setting_value(db_file, key): def get_setting_value(db_file, key):
@ -349,33 +348,8 @@ class BlockList:
filename = BlockList.get_filename() filename = BlockList.get_filename()
with open(filename, 'w') as f: f.write(content) with open(filename, 'w') as f: f.write(content)
class Url:
def check_xmpp_uri(uri):
"""
Check validity of XMPP URI.
Parameters
----------
uri : str
URI.
Returns
-------
jid : str
JID or None.
"""
jid = urlsplit(uri).path
if parseaddr(jid)[1] != jid:
jid = False
return jid
class String: class String:
def md5_hash(url): def md5_hash(url):
""" """
Hash URL string to MD5 checksum. Hash URL string to MD5 checksum.
@ -394,3 +368,36 @@ class String:
url_hashed = hashlib.md5(url_encoded) url_hashed = hashlib.md5(url_encoded)
url_digest = url_hashed.hexdigest() url_digest = url_hashed.hexdigest()
return url_digest return url_digest
class Toml:
def open_file(filename: str) -> dict:
with open(filename, mode="rb") as fn:
data = tomllib.load(fn)
return data
def save_file(filename: str, data: dict) -> None:
with open(filename, 'w') as fn:
data_as_string = tomli_w.dumps(data)
fn.write(data_as_string)
class Url:
def check_xmpp_uri(uri):
"""
Check validity of XMPP URI.
Parameters
----------
uri : str
URI.
Returns
-------
jid : str
JID or None.
"""
jid = urlsplit(uri).path
if parseaddr(jid)[1] != jid:
jid = False
return jid

View file

@ -1,2 +1,2 @@
__version__ = '0.0.6' __version__ = '0.0.7'
__version_info__ = (0, 0, 6) __version_info__ = (0, 0, 7)

View file

@ -20,6 +20,7 @@ from kaikout.xmpp.bookmark import XmppBookmark
from kaikout.xmpp.muc import XmppMuc from kaikout.xmpp.muc import XmppMuc
from kaikout.xmpp.status import XmppStatus from kaikout.xmpp.status import XmppStatus
from kaikout.log import Logger, Message from kaikout.log import Logger, Message
import random
logger = Logger(__name__) logger = Logger(__name__)
@ -37,12 +38,16 @@ class XmppGroupchat:
alias = bookmark["nick"] alias = bookmark["nick"]
room = bookmark["jid"] room = bookmark["jid"]
Message.printer('Joining to MUC {} ...'.format(room)) Message.printer('Joining to MUC {} ...'.format(room))
result = await XmppMuc.join(self, room, alias) result = await XmppMuc.join(self, room, alias)
if result == 'ban': if result == 'ban':
await XmppBookmark.remove(self, room) await XmppBookmark.remove(self, room)
logger.warning('{} is banned from {}'.format(self.alias, room)) logger.warning('{} is banned from {}'.format(self.alias, room))
logger.warning('Groupchat {} has been removed from bookmarks' logger.warning('Groupchat {} has been removed from bookmarks'
.format(room)) .format(room))
elif result == 'conflict':
number = str(random.randrange(1000, 5000))
await XmppMuc.join(self, room, alias + '_' + number)
else: else:
mucs_join_success.append(room) mucs_join_success.append(room)
logger.info('Autojoin groupchat\n' logger.info('Autojoin groupchat\n'

View file

@ -156,6 +156,9 @@ class XmppMuc:
e.presence['error']['code'] == '403'): e.presence['error']['code'] == '403'):
logger.warning('{} is banned from {}'.format(self.alias, jid)) logger.warning('{} is banned from {}'.format(self.alias, jid))
result = 'ban' result = 'ban'
elif e.condition == 'conflict':
logger.warning(e.presence['error']['text'])
result = 'conflict'
else: else:
result = 'error' result = 'error'
except Exception as e: except Exception as e: