mirror of
https://codeberg.org/sch/BukuBot
synced 2024-12-22 18:05:24 +01:00
Rename Slixmark to buku-xmpp;
Segregate code into modules.
This commit is contained in:
parent
27f843d3b6
commit
d03839d578
7 changed files with 502 additions and 382 deletions
66
__main__.py
Normal file
66
__main__.py
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Slixmark: The XMPP Bookmark Manager
|
||||||
|
# Copyright (C) 2024 Schimon Zackary
|
||||||
|
# This file is part of Slixmark.
|
||||||
|
# See the file LICENSE for copying permission.
|
||||||
|
|
||||||
|
import buku
|
||||||
|
from bukuxmpp.about import Documentation
|
||||||
|
from bukuxmpp.config import Configuration
|
||||||
|
from bukuxmpp.xmpp.chat import Chat
|
||||||
|
from bukuxmpp.xmpp.client import Client
|
||||||
|
from getpass import getpass
|
||||||
|
from argparse import ArgumentParser
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import slixmpp
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# bookmarks_db = buku.BukuDb(dbfile='temp.db')
|
||||||
|
# bookmarks_db.get_tag_all
|
||||||
|
# bookmarks_db.search_keywords_and_filter_by_tags
|
||||||
|
# bookmarks_db.exclude_results_from_search
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
# Setup the command line arguments.
|
||||||
|
parser = ArgumentParser(description=Client.__doc__)
|
||||||
|
|
||||||
|
# Output verbosity options.
|
||||||
|
parser.add_argument("-q", "--quiet", help="set logging to ERROR",
|
||||||
|
action="store_const", dest="loglevel",
|
||||||
|
const=logging.ERROR, default=logging.INFO)
|
||||||
|
parser.add_argument("-d", "--debug", help="set logging to DEBUG",
|
||||||
|
action="store_const", dest="loglevel",
|
||||||
|
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()
|
||||||
|
|
||||||
|
# Setup logging.
|
||||||
|
logging.basicConfig(level=args.loglevel,
|
||||||
|
format='%(levelname)-8s %(message)s')
|
||||||
|
|
||||||
|
if args.jid is None:
|
||||||
|
args.jid = input("Username: ")
|
||||||
|
if args.password is None:
|
||||||
|
args.password = getpass("Password: ")
|
||||||
|
|
||||||
|
# Setup the bot and register plugins. Note that while plugins may
|
||||||
|
# have interdependencies, the order in which you register them does
|
||||||
|
# not matter.
|
||||||
|
xmpp = Client(args.jid, args.password)
|
||||||
|
xmpp.connect()
|
||||||
|
xmpp.process()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
99
about.py
Normal file
99
about.py
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
class Documentation:
|
||||||
|
|
||||||
|
def about():
|
||||||
|
return ('Slixmark'
|
||||||
|
'\n'
|
||||||
|
'Jabber/XMPP Bookmark Manager'
|
||||||
|
'\n\n'
|
||||||
|
'Slixmark is an XMPP bot that facilitates accessing and '
|
||||||
|
'managing bookmarks remotely.'
|
||||||
|
'\n\n'
|
||||||
|
'Slixmark is written in Python'
|
||||||
|
'\n\n'
|
||||||
|
'It is utilizing buku to handle bookmarks, and slixmpp to '
|
||||||
|
'communicate in the XMPP telecommunication network.'
|
||||||
|
'\n\n'
|
||||||
|
'https://gitgud.io/sjehuda/slixmark'
|
||||||
|
'\n\n'
|
||||||
|
'Copyright 2024 Schimon Zackary'
|
||||||
|
'\n\n'
|
||||||
|
'Made in Switzerland'
|
||||||
|
'\n\n'
|
||||||
|
'🇨🇭️')
|
||||||
|
|
||||||
|
def commands():
|
||||||
|
return ("add URL [tag1,tag2,tag3,...]"
|
||||||
|
"\n"
|
||||||
|
" Bookmark URL along with comma-separated tags."
|
||||||
|
"\n\n"
|
||||||
|
"mod name <ID> <TEXT>"
|
||||||
|
"\n"
|
||||||
|
" Modify bookmark title."
|
||||||
|
"\n"
|
||||||
|
"mod note <ID> <TEXT>"
|
||||||
|
"\n"
|
||||||
|
" Modify bookmark description."
|
||||||
|
"\n"
|
||||||
|
"tag [+|-] <ID> [tag1,tag2,tag3,...]"
|
||||||
|
"\n"
|
||||||
|
" Modify bookmark tags. Appends or deletes tags, if flag tag "
|
||||||
|
"is preceded by \'+\' or \'-\' respectively."
|
||||||
|
"\n"
|
||||||
|
"del <ID> or <URL>"
|
||||||
|
"\n"
|
||||||
|
" Delete a bookmark by ID or URL."
|
||||||
|
"\n"
|
||||||
|
"\n"
|
||||||
|
"id <ID>"
|
||||||
|
"\n"
|
||||||
|
" Print a bookmark by ID."
|
||||||
|
"\n"
|
||||||
|
"last"
|
||||||
|
"\n"
|
||||||
|
" Print most recently bookmarked item."
|
||||||
|
"\n"
|
||||||
|
"tag <TEXT>"
|
||||||
|
"\n"
|
||||||
|
" Search bookmarks of given tag."
|
||||||
|
"\n"
|
||||||
|
"search <TEXT>"
|
||||||
|
"\n"
|
||||||
|
" Search bookmarks by a given search query."
|
||||||
|
"\n"
|
||||||
|
"search any <TEXT>"
|
||||||
|
"\n"
|
||||||
|
" Search bookmarks by a any given keyword."
|
||||||
|
# "\n"
|
||||||
|
# "regex"
|
||||||
|
# "\n"
|
||||||
|
# " Search bookmarks using Regular Expression."
|
||||||
|
"\n")
|
||||||
|
|
||||||
|
def notice():
|
||||||
|
return ('Copyright 2024 Schimon Zackary Jehudah'
|
||||||
|
'\n\n'
|
||||||
|
'Permission is hereby granted, free of charge, to any person '
|
||||||
|
'obtaining a copy of this software and associated '
|
||||||
|
'documentation files (the “Software”), to deal in the '
|
||||||
|
'Software without restriction, including without limitation '
|
||||||
|
'the rights to use, copy, modify, merge, publish, distribute, '
|
||||||
|
'sublicense, and/or sell copies of the Software, and to '
|
||||||
|
'permit persons to whom the Software is furnished to do so, '
|
||||||
|
'subject to the following conditions:'
|
||||||
|
'\n\n'
|
||||||
|
'The above copyright notice and this permission notice shall '
|
||||||
|
'be included in all copies or substantial portions of the '
|
||||||
|
'Software.'
|
||||||
|
'\n\n'
|
||||||
|
'THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY '
|
||||||
|
'KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE '
|
||||||
|
'WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR '
|
||||||
|
'PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR '
|
||||||
|
'COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER '
|
||||||
|
'LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR '
|
||||||
|
'OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE '
|
||||||
|
'SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.')
|
||||||
|
|
27
config.py
Normal file
27
config.py
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import buku
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
class Configuration:
|
||||||
|
|
||||||
|
def init_db(jid_bare):
|
||||||
|
filename = jid_bare + '.db'
|
||||||
|
data_dir = Configuration.get_db_directory()
|
||||||
|
pathname = data_dir + '/' + filename
|
||||||
|
bookmarks_db = buku.BukuDb(dbfile=pathname)
|
||||||
|
return bookmarks_db
|
||||||
|
|
||||||
|
def get_db_directory():
|
||||||
|
if os.environ.get('HOME'):
|
||||||
|
data_home = os.path.join(os.environ.get('HOME'), '.local', 'share')
|
||||||
|
return os.path.join(data_home, 'bukuxmpp')
|
||||||
|
elif sys.platform == 'win32':
|
||||||
|
data_home = os.environ.get('APPDATA')
|
||||||
|
if data_home is None:
|
||||||
|
return os.path.join(
|
||||||
|
os.path.dirname(__file__) + '/bukuxmpp_data')
|
||||||
|
else:
|
||||||
|
return os.path.join(os.path.dirname(__file__) + '/bukuxmpp_data')
|
47
log.py
Normal file
47
log.py
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
To use this class, first, instantiate Logger with the name of your module
|
||||||
|
or class, then call the appropriate logging methods on that instance.
|
||||||
|
|
||||||
|
logger = Logger(__name__)
|
||||||
|
logger.debug('This is a debug message')
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
class Logger:
|
||||||
|
|
||||||
|
def __init__(self, name):
|
||||||
|
self.logger = logging.getLogger(name)
|
||||||
|
self.logger.setLevel(logging.WARNING)
|
||||||
|
|
||||||
|
ch = logging.StreamHandler()
|
||||||
|
ch.setLevel(logging.WARNING)
|
||||||
|
|
||||||
|
formatter = logging.Formatter('[%(asctime)s] %(levelname)s: %(name)s: %(message)s')
|
||||||
|
ch.setFormatter(formatter)
|
||||||
|
|
||||||
|
self.logger.addHandler(ch)
|
||||||
|
|
||||||
|
def critical(self, message):
|
||||||
|
self.logger.critical(message)
|
||||||
|
|
||||||
|
def debug(self, message):
|
||||||
|
self.logger.debug(message)
|
||||||
|
|
||||||
|
def error(self, message):
|
||||||
|
self.logger.error(message)
|
||||||
|
|
||||||
|
def info(self, message):
|
||||||
|
self.logger.info(message)
|
||||||
|
|
||||||
|
def warning(self, message):
|
||||||
|
self.logger.warning(message)
|
||||||
|
|
||||||
|
# def check_difference(function_name, difference):
|
||||||
|
# if difference > 1:
|
||||||
|
# Logger.warning(message)
|
2
version.py
Normal file
2
version.py
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
__version__ = '0.0.2'
|
||||||
|
__version_info__ = (0, 0, 2)
|
182
xmpp/chat.py
Normal file
182
xmpp/chat.py
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from bukuxmpp.about import Documentation
|
||||||
|
from bukuxmpp.config import Configuration
|
||||||
|
|
||||||
|
try:
|
||||||
|
import tomllib
|
||||||
|
except:
|
||||||
|
import tomli as tomllib
|
||||||
|
|
||||||
|
|
||||||
|
class Chat:
|
||||||
|
|
||||||
|
def action(self, message):
|
||||||
|
"""
|
||||||
|
Process incoming message stanzas. Be aware that this also
|
||||||
|
includes MUC messages and error messages. It is usually
|
||||||
|
a good idea to check the messages's type before processing
|
||||||
|
or sending replies.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
message -- The received message stanza. See the documentation
|
||||||
|
for stanza objects and the Message stanza to see
|
||||||
|
how it may be used.
|
||||||
|
"""
|
||||||
|
jid_bare = message['from'].bare
|
||||||
|
bookmarks_db = Configuration.init_db(jid_bare)
|
||||||
|
if message['type'] in ('chat', 'normal'):
|
||||||
|
message_text = " ".join(message['body'].split())
|
||||||
|
message_lowercase = message_text.lower()
|
||||||
|
match message_lowercase:
|
||||||
|
case 'help':
|
||||||
|
message_body = '```\n' + Documentation.commands() + '\n```'
|
||||||
|
case _ if message_lowercase.startswith('add '):
|
||||||
|
message_lowercase_split = message_lowercase[4:].split(' ')
|
||||||
|
link = message_lowercase_split[0]
|
||||||
|
tags = ' '.join(message_lowercase_split[1:])
|
||||||
|
tags = tags.replace(' ,', ',')
|
||||||
|
tags = tags.replace(', ', ',')
|
||||||
|
idx = bookmarks_db.get_rec_id(link)
|
||||||
|
if idx:
|
||||||
|
message_body = '*URL already exists.*'
|
||||||
|
else:
|
||||||
|
idx = bookmarks_db.add_rec(url=link, tags_in=tags)
|
||||||
|
message_body = ('*New bookmark has been added as {}.*'
|
||||||
|
.format(idx))
|
||||||
|
case _ if message_lowercase.startswith('id'):
|
||||||
|
idx = message_lowercase[2:]
|
||||||
|
result = bookmarks_db.get_rec_by_id(idx)
|
||||||
|
message_body = Chat.format_message(result, extended=True)
|
||||||
|
case 'last':
|
||||||
|
idx = bookmarks_db.get_max_id()
|
||||||
|
result = bookmarks_db.get_rec_by_id(idx)
|
||||||
|
message_body = Chat.format_message(result)
|
||||||
|
case _ if message_lowercase.startswith('search any '):
|
||||||
|
query = message_lowercase[11:]
|
||||||
|
query = query.split(' ')
|
||||||
|
results = bookmarks_db.searchdb(query,
|
||||||
|
all_keywords=False,
|
||||||
|
deep=True,
|
||||||
|
regex=False)
|
||||||
|
message_body = '*Results for query: {}*\n\n'.format(query)
|
||||||
|
for result in results:
|
||||||
|
message_body += Chat.format_message(result) + '\n\n'
|
||||||
|
message_body += '*Total of {} results*'.format(len(results))
|
||||||
|
case _ if message_lowercase.startswith('search '):
|
||||||
|
query = message_lowercase[7:]
|
||||||
|
query = query.split(' ')
|
||||||
|
results = bookmarks_db.searchdb(query,
|
||||||
|
all_keywords=True,
|
||||||
|
deep=True,
|
||||||
|
regex=False)
|
||||||
|
message_body = '*Results for query: {}*\n\n'.format(query)
|
||||||
|
for result in results:
|
||||||
|
message_body += Chat.format_message(result) + '\n\n'
|
||||||
|
message_body += '*Total of {} results*\n\n'.format(len(results))
|
||||||
|
# elif message.startswith('regex'):
|
||||||
|
# message_body = bookmark_regexp(message[7:])
|
||||||
|
case _ if message_lowercase.startswith('del '):
|
||||||
|
val = message_lowercase[4:]
|
||||||
|
try:
|
||||||
|
idx = int(val)
|
||||||
|
except:
|
||||||
|
idx = bookmarks_db.get_rec_id(val)
|
||||||
|
bookmark = bookmarks_db.get_rec_by_id(idx)
|
||||||
|
message_body = Chat.format_message(bookmark, extended=True) if bookmark else ''
|
||||||
|
result = bookmarks_db.delete_rec(idx)
|
||||||
|
if result:
|
||||||
|
message_body += '\n*Bookmark has been deleted.*'
|
||||||
|
else:
|
||||||
|
message_body += '\n*No action has been taken for index {}*'.format(idx)
|
||||||
|
case _ if message_lowercase.startswith('mod '):
|
||||||
|
message_lowercase_split = message_lowercase[4:].split(' ')
|
||||||
|
if len(message_lowercase_split) > 2:
|
||||||
|
arg = message_lowercase_split[0]
|
||||||
|
val = message_lowercase_split[1]
|
||||||
|
new = ' '.join(message_lowercase_split[2:])
|
||||||
|
message_body = ''
|
||||||
|
try:
|
||||||
|
idx = int(val)
|
||||||
|
except:
|
||||||
|
idx = bookmarks_db.get_rec_id(val)
|
||||||
|
match arg:
|
||||||
|
case 'name':
|
||||||
|
result = bookmarks_db.update_rec(idx, title_in=new)
|
||||||
|
case 'note':
|
||||||
|
result = bookmarks_db.update_rec(idx, desc=new)
|
||||||
|
case _:
|
||||||
|
result = None
|
||||||
|
message_body = ('*Invalid argument. '
|
||||||
|
'Must be "name" or "note".*\n')
|
||||||
|
bookmark = bookmarks_db.get_rec_by_id(idx)
|
||||||
|
message_body += Chat.format_message(bookmark, extended=True) if bookmark else ''
|
||||||
|
if result:
|
||||||
|
message_body += '\n*Bookmark has been deleted.*'
|
||||||
|
else:
|
||||||
|
message_body += '\n*No action has been taken for index {}*'.format(idx)
|
||||||
|
else:
|
||||||
|
message_body = ('Missing argument. '
|
||||||
|
'Require three arguments: '
|
||||||
|
'(1) "name" or "note"; '
|
||||||
|
'(2) <ID> or <URL>; '
|
||||||
|
'(3) <TEXT>.')
|
||||||
|
case _ if (message_lowercase.startswith('tag +') or
|
||||||
|
message_lowercase.startswith('tag -')):
|
||||||
|
message_lowercase_split = message_lowercase[4:].split(' ')
|
||||||
|
if len(message_lowercase_split) > 2:
|
||||||
|
arg = message_lowercase_split[0]
|
||||||
|
val = message_lowercase_split[1]
|
||||||
|
try:
|
||||||
|
idx = int(val)
|
||||||
|
except:
|
||||||
|
idx = bookmarks_db.get_rec_id(val)
|
||||||
|
# tag = ',' + ' '.join(message_lowercase_split[2:]) + ','
|
||||||
|
# tag = ' '.join(message_lowercase_split[2:])
|
||||||
|
tag = arg + ',' + ' '.join(message_lowercase_split[2:])
|
||||||
|
tag = tag.replace(' ,', ',')
|
||||||
|
tag = tag.replace(', ', ',')
|
||||||
|
result = bookmarks_db.update_rec(idx, tags_in=tag)
|
||||||
|
bookmark = bookmarks_db.get_rec_by_id(idx)
|
||||||
|
if result:
|
||||||
|
message_body = Chat.format_message(bookmark, extended=True) if bookmark else ''
|
||||||
|
message_body += '\n*Bookmark has been updated.*'
|
||||||
|
else:
|
||||||
|
message_body = '\n*No action has been taken for index {}*'.format(idx)
|
||||||
|
else:
|
||||||
|
message_body = ('Missing argument. '
|
||||||
|
'Require three arguments: '
|
||||||
|
'(1) + or - sign; '
|
||||||
|
'(2) <ID> or <URL>; '
|
||||||
|
'(3) <TAGS>.')
|
||||||
|
case _ if message_lowercase.startswith('tag'):
|
||||||
|
tag = message_lowercase[4:]
|
||||||
|
results = bookmarks_db.search_by_tag(tag)
|
||||||
|
message_body = '*Results for tag: {}*\n\n'.format(tag)
|
||||||
|
for result in results:
|
||||||
|
message_body += Chat.format_message(result) + '\n\n'
|
||||||
|
message_body += '*Total of {} results*'.format(len(results))
|
||||||
|
case _:
|
||||||
|
message_body = ('Unknown command. Send "help" for list '
|
||||||
|
'of commands.')
|
||||||
|
message.reply(message_body).send()
|
||||||
|
#message.reply("Thanks for sending\n%(body)s" % message).send()
|
||||||
|
|
||||||
|
def format_message(bookmark, extended=False):
|
||||||
|
# idx = bookmark.id
|
||||||
|
# url = bookmark.url
|
||||||
|
# name = bookmark.title if bookmark.title else 'Untitled'
|
||||||
|
# desc = bookmark.desc if bookmark.desc else 'No comment'
|
||||||
|
idx = bookmark[0]
|
||||||
|
url = bookmark[1]
|
||||||
|
name = bookmark[2] if bookmark[2] else 'Untitled'
|
||||||
|
desc = bookmark[4] if bookmark[4] else None
|
||||||
|
# rec = '\n 🔖️ {} [{}]\n 🔗️ {}\n 🏷️ {}'.format(title, index, link, tags)
|
||||||
|
if extended:
|
||||||
|
tags = '' if bookmark.tags_raw == ',' else ", ".join(bookmark.tags_raw.split(","))[2:-2]
|
||||||
|
tags = tags if tags else 'No tags'
|
||||||
|
message_body = ('{}. {}\n{}\n{}\n{}'.format(idx, name, url, desc, tags))
|
||||||
|
else:
|
||||||
|
message_body = ('{}. {}\n{}'.format(idx, name, url))
|
||||||
|
return message_body
|
|
@ -1,166 +1,69 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Slixmark: The XMPP Bookmark Manager
|
|
||||||
# Copyright (C) 2024 Schimon Zackary
|
|
||||||
# This file is part of Slixmark.
|
|
||||||
# See the file LICENSE for copying permission.
|
|
||||||
|
|
||||||
import buku
|
|
||||||
from getpass import getpass
|
|
||||||
from argparse import ArgumentParser
|
|
||||||
import logging
|
|
||||||
import os
|
|
||||||
import slixmpp
|
import slixmpp
|
||||||
import sys
|
from bukuxmpp.xmpp.chat import Chat
|
||||||
|
from bukuxmpp.config import Configuration
|
||||||
|
from bukuxmpp.about import Documentation
|
||||||
|
|
||||||
# bookmarks_db = buku.BukuDb(dbfile='temp.db')
|
from slixfeed.log import Logger
|
||||||
# bookmarks_db.get_tag_all
|
from slixfeed.version import __version__
|
||||||
# bookmarks_db.search_keywords_and_filter_by_tags
|
|
||||||
# bookmarks_db.exclude_results_from_search
|
|
||||||
|
|
||||||
class Actions:
|
try:
|
||||||
|
import tomllib
|
||||||
def init_db(jid_bare):
|
except:
|
||||||
filename = jid_bare + '.db'
|
import tomli as tomllib
|
||||||
data_dir = Actions.get_db_directory()
|
|
||||||
pathname = data_dir + '/' + filename
|
|
||||||
bookmarks_db = buku.BukuDb(dbfile=pathname)
|
|
||||||
return bookmarks_db
|
|
||||||
|
|
||||||
def get_db_directory():
|
|
||||||
if os.environ.get('HOME'):
|
|
||||||
data_home = os.path.join(os.environ.get('HOME'), '.local', 'share')
|
|
||||||
return os.path.join(data_home, 'slixmark')
|
|
||||||
elif sys.platform == 'win32':
|
|
||||||
data_home = os.environ.get('APPDATA')
|
|
||||||
if data_home is None:
|
|
||||||
return os.path.join(
|
|
||||||
os.path.dirname(__file__) + '/slixmark_data')
|
|
||||||
else:
|
|
||||||
return os.path.join(os.path.dirname(__file__) + '/slixmark_data')
|
|
||||||
|
|
||||||
|
|
||||||
class Documentation:
|
# time_now = datetime.now()
|
||||||
|
# time_now = time_now.strftime("%H:%M:%S")
|
||||||
|
|
||||||
def about():
|
# def print_time():
|
||||||
return ('Slixmark'
|
# # return datetime.now().strftime("%H:%M:%S")
|
||||||
'\n'
|
# now = datetime.now()
|
||||||
'Jabber/XMPP Bookmark Manager'
|
# current_time = now.strftime("%H:%M:%S")
|
||||||
'\n\n'
|
# return current_time
|
||||||
'Slixmark is an XMPP bot that facilitates accessing and '
|
|
||||||
'managing bookmarks remotely.'
|
|
||||||
'\n\n'
|
|
||||||
'Slixmark is written in Python'
|
|
||||||
'\n\n'
|
|
||||||
'It is utilizing buku to handle bookmarks, and slixmpp to '
|
|
||||||
'communicate in the XMPP telecommunication network.'
|
|
||||||
'\n\n'
|
|
||||||
'https://gitgud.io/sjehuda/slixmark'
|
|
||||||
'\n\n'
|
|
||||||
'Copyright 2024 Schimon Zackary'
|
|
||||||
'\n\n'
|
|
||||||
'Made in Switzerland'
|
|
||||||
'\n\n'
|
|
||||||
'🇨🇭️')
|
|
||||||
|
|
||||||
def commands():
|
logger = Logger(__name__)
|
||||||
return ("add URL [tag1,tag2,tag3,...]"
|
|
||||||
"\n"
|
|
||||||
" Bookmark URL along with comma-separated tags."
|
|
||||||
"\n\n"
|
|
||||||
"mod name <ID> <TEXT>"
|
|
||||||
"\n"
|
|
||||||
" Modify bookmark title."
|
|
||||||
"\n"
|
|
||||||
"mod note <ID> <TEXT>"
|
|
||||||
"\n"
|
|
||||||
" Modify bookmark description."
|
|
||||||
"\n"
|
|
||||||
"tag [+|-] <ID> [tag1,tag2,tag3,...]"
|
|
||||||
"\n"
|
|
||||||
" Modify bookmark tags. Appends or deletes tags, if flag tag "
|
|
||||||
"is preceded by \'+\' or \'-\' respectively."
|
|
||||||
"\n"
|
|
||||||
"del <ID> or <URL>"
|
|
||||||
"\n"
|
|
||||||
" Delete a bookmark by ID or URL."
|
|
||||||
"\n"
|
|
||||||
"\n"
|
|
||||||
"id <ID>"
|
|
||||||
"\n"
|
|
||||||
" Print a bookmark by ID."
|
|
||||||
"\n"
|
|
||||||
"last"
|
|
||||||
"\n"
|
|
||||||
" Print most recently bookmarked item."
|
|
||||||
"\n"
|
|
||||||
"tag <TEXT>"
|
|
||||||
"\n"
|
|
||||||
" Search bookmarks of given tag."
|
|
||||||
"\n"
|
|
||||||
"search <TEXT>"
|
|
||||||
"\n"
|
|
||||||
" Search bookmarks by a given search query."
|
|
||||||
"\n"
|
|
||||||
"search any <TEXT>"
|
|
||||||
"\n"
|
|
||||||
" Search bookmarks by a any given keyword."
|
|
||||||
# "\n"
|
|
||||||
# "regex"
|
|
||||||
# "\n"
|
|
||||||
# " Search bookmarks using Regular Expression."
|
|
||||||
"\n")
|
|
||||||
|
|
||||||
def notice():
|
class Client(slixmpp.ClientXMPP):
|
||||||
return ('Copyright 2024 Schimon Zackary Jehudah'
|
|
||||||
'\n\n'
|
|
||||||
'Permission is hereby granted, free of charge, to any person '
|
|
||||||
'obtaining a copy of this software and associated '
|
|
||||||
'documentation files (the “Software”), to deal in the '
|
|
||||||
'Software without restriction, including without limitation '
|
|
||||||
'the rights to use, copy, modify, merge, publish, distribute, '
|
|
||||||
'sublicense, and/or sell copies of the Software, and to '
|
|
||||||
'permit persons to whom the Software is furnished to do so, '
|
|
||||||
'subject to the following conditions:'
|
|
||||||
'\n\n'
|
|
||||||
'The above copyright notice and this permission notice shall '
|
|
||||||
'be included in all copies or substantial portions of the '
|
|
||||||
'Software.'
|
|
||||||
'\n\n'
|
|
||||||
'THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY '
|
|
||||||
'KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE '
|
|
||||||
'WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR '
|
|
||||||
'PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR '
|
|
||||||
'COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER '
|
|
||||||
'LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR '
|
|
||||||
'OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE '
|
|
||||||
'SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.')
|
|
||||||
|
|
||||||
|
|
||||||
class Slixmark(slixmpp.ClientXMPP):
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Slixmark - Bookmark manager bot for Jabber/XMPP.
|
bukuxmpp - Bookmark manager bot for Jabber/XMPP.
|
||||||
Slixmark is a bookmark manager bot based on buku and slixmpp.
|
bukuxmpp is a bookmark manager bot based on buku and slixmpp.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, jid, password):
|
def __init__(self, jid, password):
|
||||||
slixmpp.ClientXMPP.__init__(self, jid, password)
|
slixmpp.ClientXMPP.__init__(self, jid, password)
|
||||||
|
|
||||||
|
print('client')
|
||||||
|
|
||||||
|
self.register_plugin('xep_0030') # Service Discovery
|
||||||
|
self.register_plugin('xep_0004') # Data Forms
|
||||||
|
self.register_plugin('xep_0060') # Publish-Subscribe
|
||||||
|
self.register_plugin('xep_0050') # Ad-Hoc Commands
|
||||||
|
self.register_plugin('xep_0115') # Entity Capabilities
|
||||||
|
self.register_plugin('xep_0122') # Data Forms Validation
|
||||||
|
self.register_plugin('xep_0199') # XMPP Ping
|
||||||
|
|
||||||
|
# Connect to the XMPP server and start processing XMPP stanzas.
|
||||||
|
# self.connect()
|
||||||
|
# self.process()
|
||||||
|
|
||||||
# The session_start event will be triggered when
|
# The session_start event will be triggered when
|
||||||
# the bot establishes its connection with the server
|
# the bot establishes its connection with the server
|
||||||
# and the XML streams are ready for use. We want to
|
# and the XML streams are ready for use. We want to
|
||||||
# listen for this event so that we we can initialize
|
# listen for this event so that we we can initialize
|
||||||
# our roster.
|
# our roster.
|
||||||
self.add_event_handler("session_start", self.start)
|
self.add_event_handler("session_start", self.process_session_start)
|
||||||
|
|
||||||
# The message event is triggered whenever a message
|
# The message event is triggered whenever a message
|
||||||
# stanza is received. Be aware that that includes
|
# stanza is received. Be aware that that includes
|
||||||
# MUC messages and error messages.
|
# MUC messages and error messages.
|
||||||
self.add_event_handler("message", self.process_message)
|
self.add_event_handler("message", self.process_message)
|
||||||
self.add_event_handler("disco_info", self.discovery)
|
self.add_event_handler("disco_info", self.process_disco_info)
|
||||||
|
|
||||||
async def start(self, event):
|
async def process_session_start(self, event):
|
||||||
"""
|
"""
|
||||||
Process the session_start event.
|
Process the session_start event.
|
||||||
|
|
||||||
|
@ -178,176 +81,14 @@ class Slixmark(slixmpp.ClientXMPP):
|
||||||
# await self.get_roster()
|
# await self.get_roster()
|
||||||
await self['xep_0115'].update_caps()
|
await self['xep_0115'].update_caps()
|
||||||
|
|
||||||
async def discovery(self, DiscoInfo):
|
async def process_disco_info(self, DiscoInfo):
|
||||||
jid = DiscoInfo['from']
|
jid = DiscoInfo['from']
|
||||||
await self['xep_0115'].update_caps(jid=jid)
|
await self['xep_0115'].update_caps(jid=jid)
|
||||||
# jid_bare = DiscoInfo['from'].bare
|
# jid_bare = DiscoInfo['from'].bare
|
||||||
# self.bookmarks_db = buku.BukuDb(dbfile=jid_bare + '.db')
|
# self.bookmarks_db = buku.BukuDb(dbfile=jid_bare + '.db')
|
||||||
|
|
||||||
def process_message(self, message):
|
def process_message(self, message):
|
||||||
"""
|
Chat.action(self, message)
|
||||||
Process incoming message stanzas. Be aware that this also
|
|
||||||
includes MUC messages and error messages. It is usually
|
|
||||||
a good idea to check the messages's type before processing
|
|
||||||
or sending replies.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
message -- The received message stanza. See the documentation
|
|
||||||
for stanza objects and the Message stanza to see
|
|
||||||
how it may be used.
|
|
||||||
"""
|
|
||||||
jid_bare = message['from'].bare
|
|
||||||
bookmarks_db = Actions.init_db(jid_bare)
|
|
||||||
if message['type'] in ('chat', 'normal'):
|
|
||||||
message_text = " ".join(message['body'].split())
|
|
||||||
message_lowercase = message_text.lower()
|
|
||||||
match message_lowercase:
|
|
||||||
case 'help':
|
|
||||||
message_body = '```\n' + Documentation.commands() + '\n```'
|
|
||||||
case _ if message_lowercase.startswith('add '):
|
|
||||||
message_lowercase_split = message_lowercase[4:].split(' ')
|
|
||||||
link = message_lowercase_split[0]
|
|
||||||
tags = ' '.join(message_lowercase_split[1:])
|
|
||||||
tags = tags.replace(' ,', ',')
|
|
||||||
tags = tags.replace(', ', ',')
|
|
||||||
idx = bookmarks_db.get_rec_id(link)
|
|
||||||
if idx:
|
|
||||||
message_body = '*URL already exists.*'
|
|
||||||
else:
|
|
||||||
idx = bookmarks_db.add_rec(url=link, tags_in=tags)
|
|
||||||
message_body = ('*New bookmark has been added as {}.*'
|
|
||||||
.format(idx))
|
|
||||||
case _ if message_lowercase.startswith('id'):
|
|
||||||
idx = message_lowercase[2:]
|
|
||||||
result = bookmarks_db.get_rec_by_id(idx)
|
|
||||||
message_body = self.format_message(result, extended=True)
|
|
||||||
case 'last':
|
|
||||||
idx = bookmarks_db.get_max_id()
|
|
||||||
result = bookmarks_db.get_rec_by_id(idx)
|
|
||||||
message_body = self.format_message(result)
|
|
||||||
case _ if message_lowercase.startswith('search any '):
|
|
||||||
query = message_lowercase[11:]
|
|
||||||
query = query.split(' ')
|
|
||||||
results = bookmarks_db.searchdb(query,
|
|
||||||
all_keywords=False,
|
|
||||||
deep=True,
|
|
||||||
regex=False)
|
|
||||||
message_body = '*Results for query: {}*\n\n'.format(query)
|
|
||||||
for result in results:
|
|
||||||
message_body += self.format_message(result) + '\n\n'
|
|
||||||
message_body += '*Total of {} results*'.format(len(results))
|
|
||||||
case _ if message_lowercase.startswith('search '):
|
|
||||||
query = message_lowercase[7:]
|
|
||||||
query = query.split(' ')
|
|
||||||
results = bookmarks_db.searchdb(query,
|
|
||||||
all_keywords=True,
|
|
||||||
deep=True,
|
|
||||||
regex=False)
|
|
||||||
message_body = '*Results for query: {}*\n\n'.format(query)
|
|
||||||
for result in results:
|
|
||||||
message_body += self.format_message(result) + '\n\n'
|
|
||||||
message_body += '*Total of {} results*\n\n'.format(len(results))
|
|
||||||
# elif message.startswith('regex'):
|
|
||||||
# message_body = bookmark_regexp(message[7:])
|
|
||||||
case _ if message_lowercase.startswith('del '):
|
|
||||||
val = message_lowercase[4:]
|
|
||||||
try:
|
|
||||||
idx = int(val)
|
|
||||||
except:
|
|
||||||
idx = bookmarks_db.get_rec_id(val)
|
|
||||||
bookmark = bookmarks_db.get_rec_by_id(idx)
|
|
||||||
message_body = self.format_message(bookmark, extended=True) if bookmark else ''
|
|
||||||
result = bookmarks_db.delete_rec(idx)
|
|
||||||
if result:
|
|
||||||
message_body += '\n*Bookmark has been deleted.*'
|
|
||||||
else:
|
|
||||||
message_body += '\n*No action has been taken for index {}*'.format(idx)
|
|
||||||
case _ if message_lowercase.startswith('mod '):
|
|
||||||
message_lowercase_split = message_lowercase[4:].split(' ')
|
|
||||||
if len(message_lowercase_split) > 2:
|
|
||||||
arg = message_lowercase_split[0]
|
|
||||||
val = message_lowercase_split[1]
|
|
||||||
new = ' '.join(message_lowercase_split[2:])
|
|
||||||
message_body = ''
|
|
||||||
try:
|
|
||||||
idx = int(val)
|
|
||||||
except:
|
|
||||||
idx = bookmarks_db.get_rec_id(val)
|
|
||||||
match arg:
|
|
||||||
case 'name':
|
|
||||||
result = bookmarks_db.update_rec(idx, title_in=new)
|
|
||||||
case 'note':
|
|
||||||
result = bookmarks_db.update_rec(idx, desc=new)
|
|
||||||
case _:
|
|
||||||
result = None
|
|
||||||
message_body = ('*Invalid argument. '
|
|
||||||
'Must be "name" or "note".*\n')
|
|
||||||
bookmark = bookmarks_db.get_rec_by_id(idx)
|
|
||||||
message_body += self.format_message(bookmark, extended=True) if bookmark else ''
|
|
||||||
if result:
|
|
||||||
message_body += '\n*Bookmark has been deleted.*'
|
|
||||||
else:
|
|
||||||
message_body += '\n*No action has been taken for index {}*'.format(idx)
|
|
||||||
else:
|
|
||||||
message_body = ('Missing argument. '
|
|
||||||
'Require three arguments: '
|
|
||||||
'(1) "name" or "note"; '
|
|
||||||
'(2) <ID> or <URL>; '
|
|
||||||
'(3) <TEXT>.')
|
|
||||||
case _ if (message_lowercase.startswith('tag +') or
|
|
||||||
message_lowercase.startswith('tag -')):
|
|
||||||
message_lowercase_split = message_lowercase[4:].split(' ')
|
|
||||||
if len(message_lowercase_split) > 2:
|
|
||||||
arg = message_lowercase_split[0]
|
|
||||||
val = message_lowercase_split[1]
|
|
||||||
try:
|
|
||||||
idx = int(val)
|
|
||||||
except:
|
|
||||||
idx = bookmarks_db.get_rec_id(val)
|
|
||||||
# tag = ',' + ' '.join(message_lowercase_split[2:]) + ','
|
|
||||||
# tag = ' '.join(message_lowercase_split[2:])
|
|
||||||
tag = arg + ',' + ' '.join(message_lowercase_split[2:])
|
|
||||||
tag = tag.replace(' ,', ',')
|
|
||||||
tag = tag.replace(', ', ',')
|
|
||||||
result = bookmarks_db.update_rec(idx, tags_in=tag)
|
|
||||||
bookmark = bookmarks_db.get_rec_by_id(idx)
|
|
||||||
if result:
|
|
||||||
message_body = self.format_message(bookmark, extended=True) if bookmark else ''
|
|
||||||
message_body += '\n*Bookmark has been updated.*'
|
|
||||||
else:
|
|
||||||
message_body = '\n*No action has been taken for index {}*'.format(idx)
|
|
||||||
else:
|
|
||||||
message_body = ('Missing argument. '
|
|
||||||
'Require three arguments: '
|
|
||||||
'(1) + or - sign; '
|
|
||||||
'(2) <ID> or <URL>; '
|
|
||||||
'(3) <TAGS>.')
|
|
||||||
case _ if message_lowercase.startswith('tag'):
|
|
||||||
tag = message_lowercase[4:]
|
|
||||||
results = bookmarks_db.search_by_tag(tag)
|
|
||||||
message_body = '*Results for tag: {}*\n\n'.format(tag)
|
|
||||||
for result in results:
|
|
||||||
message_body += self.format_message(result) + '\n\n'
|
|
||||||
message_body += '*Total of {} results*'.format(len(results))
|
|
||||||
case _:
|
|
||||||
message_body = ('Unknown command. Send "help" for list '
|
|
||||||
'of commands.')
|
|
||||||
message.reply(message_body).send()
|
|
||||||
#message.reply("Thanks for sending\n%(body)s" % message).send()
|
|
||||||
|
|
||||||
def format_message(self, bookmark, extended=False):
|
|
||||||
idx = bookmark.id
|
|
||||||
url = bookmark.url
|
|
||||||
name = bookmark.title if bookmark.title else 'Untitled'
|
|
||||||
desc = bookmark.desc if bookmark.desc else 'No comment'
|
|
||||||
# rec = '\n 🔖️ {} [{}]\n 🔗️ {}\n 🏷️ {}'.format(title, index, link, tags)
|
|
||||||
if extended:
|
|
||||||
tags = '' if bookmark.tags_raw == ',' else ", ".join(bookmark.tags_raw.split(","))[2:-2]
|
|
||||||
tags = tags if tags else 'No tags'
|
|
||||||
message_body = ('{}. {}\n{}\n{}\n{}'.format(idx, name, url, desc, tags))
|
|
||||||
else:
|
|
||||||
message_body = ('{}. {}\n{}'.format(idx, name, url))
|
|
||||||
return message_body
|
|
||||||
|
|
||||||
def command_list(self):
|
def command_list(self):
|
||||||
self['xep_0050'].add_command(node='add',
|
self['xep_0050'].add_command(node='add',
|
||||||
|
@ -412,7 +153,7 @@ class Slixmark(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
def _handle_edit_single(self, payload, session):
|
def _handle_edit_single(self, payload, session):
|
||||||
jid_bare = session['from'].bare
|
jid_bare = session['from'].bare
|
||||||
bookmarks_db = Actions.init_db(jid_bare)
|
bookmarks_db = Configuration.init_db(jid_bare)
|
||||||
form = self['xep_0004'].make_form('form', 'Edit')
|
form = self['xep_0004'].make_form('form', 'Edit')
|
||||||
form['instructions'] = 'Edit bookmark'
|
form['instructions'] = 'Edit bookmark'
|
||||||
url = payload['values']['url']
|
url = payload['values']['url']
|
||||||
|
@ -431,23 +172,23 @@ class Slixmark(slixmpp.ClientXMPP):
|
||||||
bookmark = bookmarks_db.get_rec_by_id(idx)
|
bookmark = bookmarks_db.get_rec_by_id(idx)
|
||||||
form.add_field(ftype='text-single',
|
form.add_field(ftype='text-single',
|
||||||
label='ID #',
|
label='ID #',
|
||||||
value=str(bookmark.id))
|
value=str(idx))
|
||||||
form.add_field(ftype='text-single',
|
form.add_field(ftype='text-single',
|
||||||
label='Title',
|
label='Title',
|
||||||
value=bookmark.title)
|
value=bookmark[2])
|
||||||
form.add_field(ftype='text-single',
|
form.add_field(ftype='text-single',
|
||||||
label='URL',
|
label='URL',
|
||||||
value=bookmark.url)
|
value=bookmark[1])
|
||||||
form.add_field(ftype='text-multi',
|
form.add_field(ftype='text-multi',
|
||||||
label='Note',
|
label='Note',
|
||||||
value=bookmark.desc)
|
value=bookmark[4])
|
||||||
options = form.add_field(ftype='list-multi',
|
options = form.add_field(ftype='list-multi',
|
||||||
label='Tags')
|
label='Tags')
|
||||||
for tag in bookmark.tags_raw.split(','):
|
for tag in bookmark[3].split(','):
|
||||||
options.addOption(tag, tag)
|
options.addOption(tag, tag)
|
||||||
form.add_field(ftype='boolean',
|
form.add_field(ftype='boolean',
|
||||||
label='Immutable',
|
label='Immutable',
|
||||||
value=str(bookmark.flags))
|
value=str(bookmark[5]))
|
||||||
session['allow_complete'] = True
|
session['allow_complete'] = True
|
||||||
session['has_next'] = False
|
session['has_next'] = False
|
||||||
session['next'] = None
|
session['next'] = None
|
||||||
|
@ -479,7 +220,7 @@ class Slixmark(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
def _handle_tag(self, iq, session):
|
def _handle_tag(self, iq, session):
|
||||||
jid_bare = session['from'].bare
|
jid_bare = session['from'].bare
|
||||||
bookmarks_db = Actions.init_db(jid_bare)
|
bookmarks_db = Configuration.init_db(jid_bare)
|
||||||
form = self['xep_0004'].make_form('form', 'Tags')
|
form = self['xep_0004'].make_form('form', 'Tags')
|
||||||
form['instructions'] = ('Select tags to browse')
|
form['instructions'] = ('Select tags to browse')
|
||||||
options = form.add_field(desc='Select tag to list its items.',
|
options = form.add_field(desc='Select tag to list its items.',
|
||||||
|
@ -499,7 +240,7 @@ class Slixmark(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
def _handle_browse_all(self, payload, session):
|
def _handle_browse_all(self, payload, session):
|
||||||
jid_bare = session['from'].bare
|
jid_bare = session['from'].bare
|
||||||
bookmarks_db = Actions.init_db(jid_bare)
|
bookmarks_db = Configuration.init_db(jid_bare)
|
||||||
vals = payload['values']
|
vals = payload['values']
|
||||||
if 'url' in vals and vals['url']:
|
if 'url' in vals and vals['url']:
|
||||||
act = vals['action']
|
act = vals['action']
|
||||||
|
@ -515,11 +256,11 @@ class Slixmark(slixmpp.ClientXMPP):
|
||||||
idx = bookmarks_db.get_rec_id(i)
|
idx = bookmarks_db.get_rec_id(i)
|
||||||
idxs += ',' + str(idx)
|
idxs += ',' + str(idx)
|
||||||
bookmark = bookmarks_db.get_rec_by_id(idx)
|
bookmark = bookmarks_db.get_rec_by_id(idx)
|
||||||
tags += bookmark.tags_raw
|
tags += bookmark[3]
|
||||||
form.add_field(desc='Comma-separated tags.',
|
form.add_field(desc='Comma-separated tags.',
|
||||||
ftype='text-single',
|
ftype='text-single',
|
||||||
label='Tags',
|
label='Tags',
|
||||||
value=bookmark.tags_raw,
|
value=bookmark[3],
|
||||||
var='tags_new')
|
var='tags_new')
|
||||||
form.add_field(desc='Check to disable automatic title fetch.',
|
form.add_field(desc='Check to disable automatic title fetch.',
|
||||||
ftype='boolean',
|
ftype='boolean',
|
||||||
|
@ -536,32 +277,32 @@ class Slixmark(slixmpp.ClientXMPP):
|
||||||
bookmark = bookmarks_db.get_rec_by_id(idx)
|
bookmark = bookmarks_db.get_rec_by_id(idx)
|
||||||
form.add_field(ftype='fixed',
|
form.add_field(ftype='fixed',
|
||||||
label='ID #',
|
label='ID #',
|
||||||
value=str(bookmark.id),
|
value=str(idx),
|
||||||
var='id')
|
var='id')
|
||||||
form.add_field(ftype='text-single',
|
form.add_field(ftype='text-single',
|
||||||
label='Title',
|
label='Title',
|
||||||
value=bookmark.title,
|
value=bookmark[2],
|
||||||
var='title')
|
var='title')
|
||||||
form.add_field(ftype='text-single',
|
form.add_field(ftype='text-single',
|
||||||
label='URL',
|
label='URL',
|
||||||
value=bookmark.url,
|
value=bookmark[1],
|
||||||
var='url')
|
var='url')
|
||||||
form.add_field(ftype='text-multi',
|
form.add_field(ftype='text-multi',
|
||||||
label='Note',
|
label='Note',
|
||||||
value=bookmark.desc,
|
value=bookmark[4],
|
||||||
var='description')
|
var='description')
|
||||||
form.add_field(ftype='hidden',
|
form.add_field(ftype='hidden',
|
||||||
value=bookmark.tags_raw,
|
value=bookmark[3],
|
||||||
var='tags_old')
|
var='tags_old')
|
||||||
form.add_field(desc='Comma-separated tags.',
|
form.add_field(desc='Comma-separated tags.',
|
||||||
ftype='text-single',
|
ftype='text-single',
|
||||||
label='Tags',
|
label='Tags',
|
||||||
value=bookmark.tags_raw,
|
value=bookmark[3],
|
||||||
var='tags_new')
|
var='tags_new')
|
||||||
form.add_field(desc='Check to disable automatic title fetch.',
|
form.add_field(desc='Check to disable automatic title fetch.',
|
||||||
ftype='boolean',
|
ftype='boolean',
|
||||||
label='Immutable',
|
label='Immutable',
|
||||||
value=str(bookmark.flags),
|
value=str(bookmark[5]),
|
||||||
var='immutable')
|
var='immutable')
|
||||||
case 'remove':
|
case 'remove':
|
||||||
form['instructions'] = ('The following items were deleted from '
|
form['instructions'] = ('The following items were deleted from '
|
||||||
|
@ -607,7 +348,7 @@ class Slixmark(slixmpp.ClientXMPP):
|
||||||
limiter = counter + int(limit)
|
limiter = counter + int(limit)
|
||||||
for bookmark in bookmarks[counter:limiter]:
|
for bookmark in bookmarks[counter:limiter]:
|
||||||
if counter == limiter: break
|
if counter == limiter: break
|
||||||
options.addOption(bookmark.title, bookmark.url)
|
options.addOption(bookmark[2], bookmark[1])
|
||||||
counter += 1
|
counter += 1
|
||||||
form.add_field(ftype='hidden',
|
form.add_field(ftype='hidden',
|
||||||
value=str(counter),
|
value=str(counter),
|
||||||
|
@ -622,7 +363,7 @@ class Slixmark(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
def _handle_action_result(self, payload, session):
|
def _handle_action_result(self, payload, session):
|
||||||
jid_bare = session['from'].bare
|
jid_bare = session['from'].bare
|
||||||
bookmarks_db = Actions.init_db(jid_bare)
|
bookmarks_db = Configuration.init_db(jid_bare)
|
||||||
vals = payload['values']
|
vals = payload['values']
|
||||||
if 'id' in vals:
|
if 'id' in vals:
|
||||||
idx = vals['id']
|
idx = vals['id']
|
||||||
|
@ -688,7 +429,7 @@ class Slixmark(slixmpp.ClientXMPP):
|
||||||
idx = bookmarks_db.add_rec(url=i)
|
idx = bookmarks_db.add_rec(url=i)
|
||||||
rec = bookmarks_db.get_rec_by_id(idx)
|
rec = bookmarks_db.get_rec_by_id(idx)
|
||||||
form.add_field(ftype='fixed',
|
form.add_field(ftype='fixed',
|
||||||
value=str(rec.id))
|
value=str(idx))
|
||||||
form.add_field(ftype='text-single',
|
form.add_field(ftype='text-single',
|
||||||
value=rec.title)
|
value=rec.title)
|
||||||
form.add_field(ftype='text-single',
|
form.add_field(ftype='text-single',
|
||||||
|
@ -701,36 +442,36 @@ class Slixmark(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
def _handle_random(self, iq, session):
|
def _handle_random(self, iq, session):
|
||||||
jid_bare = session['from'].bare
|
jid_bare = session['from'].bare
|
||||||
bookmarks_db = Actions.init_db(jid_bare)
|
bookmarks_db = Configuration.init_db(jid_bare)
|
||||||
bookmarks = bookmarks_db.get_rec_all()
|
bookmarks = bookmarks_db.get_rec_all()
|
||||||
if bookmarks:
|
if bookmarks:
|
||||||
import random
|
import random
|
||||||
bookmark = random.choice(bookmarks)
|
bookmark = random.choice(bookmarks)
|
||||||
form = self['xep_0004'].make_form('form', 'Random')
|
form = self['xep_0004'].make_form('form', 'Random')
|
||||||
form['instructions'] = 'Bookmark #{}'.format(bookmark.id)
|
form['instructions'] = 'Bookmark #{}'.format(bookmark[0])
|
||||||
form.add_field(ftype='fixed',
|
form.add_field(ftype='fixed',
|
||||||
# ftype='text-single',
|
# ftype='text-single',
|
||||||
label='URL',
|
label='URL',
|
||||||
# required=True,
|
# required=True,
|
||||||
value=bookmark.url,
|
value=bookmark[1],
|
||||||
var='url')
|
var='url')
|
||||||
form.add_field(ftype='text-single',
|
form.add_field(ftype='text-single',
|
||||||
label='Title',
|
label='Title',
|
||||||
value=bookmark.title,
|
value=bookmark[2],
|
||||||
var='title')
|
var='title')
|
||||||
form.add_field(ftype='text-multi',
|
form.add_field(ftype='text-multi',
|
||||||
label='Note',
|
label='Note',
|
||||||
value=bookmark.desc,
|
value=bookmark[4],
|
||||||
var='note')
|
var='note')
|
||||||
form.add_field(desc='Comma-separated tags.',
|
form.add_field(desc='Comma-separated tags.',
|
||||||
ftype='text-single',
|
ftype='text-single',
|
||||||
label='Tags',
|
label='Tags',
|
||||||
value=bookmark.tags_raw,
|
value=bookmark[3],
|
||||||
var='tag')
|
var='tag')
|
||||||
form.add_field(desc='Check to disable automatic title fetch.',
|
form.add_field(desc='Check to disable automatic title fetch.',
|
||||||
ftype='boolean',
|
ftype='boolean',
|
||||||
label='Immutable',
|
label='Immutable',
|
||||||
value=str(bookmark.flags),
|
value=str(bookmark[5]),
|
||||||
var='immutable')
|
var='immutable')
|
||||||
session['has_next'] = True
|
session['has_next'] = True
|
||||||
session['next'] = self._handle_edit_single
|
session['next'] = self._handle_edit_single
|
||||||
|
@ -773,7 +514,7 @@ class Slixmark(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
def _handle_search_result(self, payload, session):
|
def _handle_search_result(self, payload, session):
|
||||||
jid_bare = session['from'].bare
|
jid_bare = session['from'].bare
|
||||||
bookmarks_db = Actions.init_db(jid_bare)
|
bookmarks_db = Configuration.init_db(jid_bare)
|
||||||
vals = payload['values']
|
vals = payload['values']
|
||||||
if 'url' in vals and vals['url']:
|
if 'url' in vals and vals['url']:
|
||||||
act = vals['action']
|
act = vals['action']
|
||||||
|
@ -789,11 +530,11 @@ class Slixmark(slixmpp.ClientXMPP):
|
||||||
idx = bookmarks_db.get_rec_id(i)
|
idx = bookmarks_db.get_rec_id(i)
|
||||||
idxs += ',' + str(idx)
|
idxs += ',' + str(idx)
|
||||||
bookmark = bookmarks_db.get_rec_by_id(idx)
|
bookmark = bookmarks_db.get_rec_by_id(idx)
|
||||||
tags += bookmark.tags_raw
|
tags += bookmark[3]
|
||||||
form.add_field(desc='Comma-separated tags.',
|
form.add_field(desc='Comma-separated tags.',
|
||||||
ftype='text-single',
|
ftype='text-single',
|
||||||
label='Tags',
|
label='Tags',
|
||||||
value=bookmark.tags_raw,
|
value=bookmark[3],
|
||||||
var='tags_new')
|
var='tags_new')
|
||||||
form.add_field(desc='Check to disable automatic title fetch.',
|
form.add_field(desc='Check to disable automatic title fetch.',
|
||||||
ftype='boolean',
|
ftype='boolean',
|
||||||
|
@ -810,32 +551,32 @@ class Slixmark(slixmpp.ClientXMPP):
|
||||||
bookmark = bookmarks_db.get_rec_by_id(idx)
|
bookmark = bookmarks_db.get_rec_by_id(idx)
|
||||||
form.add_field(ftype='fixed',
|
form.add_field(ftype='fixed',
|
||||||
label='ID #',
|
label='ID #',
|
||||||
value=str(bookmark.id),
|
value=str(idx),
|
||||||
var='id')
|
var='id')
|
||||||
form.add_field(ftype='text-single',
|
form.add_field(ftype='text-single',
|
||||||
label='Title',
|
label='Title',
|
||||||
value=bookmark.title,
|
value=bookmark[2],
|
||||||
var='title')
|
var='title')
|
||||||
form.add_field(ftype='text-single',
|
form.add_field(ftype='text-single',
|
||||||
label='URL',
|
label='URL',
|
||||||
value=bookmark.url,
|
value=bookmark[1],
|
||||||
var='url')
|
var='url')
|
||||||
form.add_field(ftype='text-multi',
|
form.add_field(ftype='text-multi',
|
||||||
label='Note',
|
label='Note',
|
||||||
value=bookmark.desc,
|
value=bookmark[4],
|
||||||
var='description')
|
var='description')
|
||||||
form.add_field(ftype='hidden',
|
form.add_field(ftype='hidden',
|
||||||
value=bookmark.tags_raw,
|
value=bookmark[3],
|
||||||
var='tags_old')
|
var='tags_old')
|
||||||
form.add_field(desc='Comma-separated tags.',
|
form.add_field(desc='Comma-separated tags.',
|
||||||
ftype='text-single',
|
ftype='text-single',
|
||||||
label='Tags',
|
label='Tags',
|
||||||
value=bookmark.tags_raw,
|
value=bookmark[3],
|
||||||
var='tags_new')
|
var='tags_new')
|
||||||
form.add_field(desc='Check to disable automatic title fetch.',
|
form.add_field(desc='Check to disable automatic title fetch.',
|
||||||
ftype='boolean',
|
ftype='boolean',
|
||||||
label='Immutable',
|
label='Immutable',
|
||||||
value=str(bookmark.flags),
|
value=str(bookmark[5]),
|
||||||
var='immutable')
|
var='immutable')
|
||||||
case 'remove':
|
case 'remove':
|
||||||
form['instructions'] = ('The following items were deleted from '
|
form['instructions'] = ('The following items were deleted from '
|
||||||
|
@ -903,7 +644,7 @@ class Slixmark(slixmpp.ClientXMPP):
|
||||||
limiter = counter + 10
|
limiter = counter + 10
|
||||||
for bookmark in bookmarks[counter:limiter]:
|
for bookmark in bookmarks[counter:limiter]:
|
||||||
if counter == limiter: break
|
if counter == limiter: break
|
||||||
options.addOption(bookmark.title, bookmark.url)
|
options.addOption(bookmark[2], bookmark[1])
|
||||||
counter += 1
|
counter += 1
|
||||||
form.add_field(ftype='hidden',
|
form.add_field(ftype='hidden',
|
||||||
value=str(counter),
|
value=str(counter),
|
||||||
|
@ -955,47 +696,3 @@ class Slixmark(slixmpp.ClientXMPP):
|
||||||
return session
|
return session
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
# Setup the command line arguments.
|
|
||||||
parser = ArgumentParser(description=Slixmark.__doc__)
|
|
||||||
|
|
||||||
# Output verbosity options.
|
|
||||||
parser.add_argument("-q", "--quiet", help="set logging to ERROR",
|
|
||||||
action="store_const", dest="loglevel",
|
|
||||||
const=logging.ERROR, default=logging.INFO)
|
|
||||||
parser.add_argument("-d", "--debug", help="set logging to DEBUG",
|
|
||||||
action="store_const", dest="loglevel",
|
|
||||||
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()
|
|
||||||
|
|
||||||
# Setup logging.
|
|
||||||
logging.basicConfig(level=args.loglevel,
|
|
||||||
format='%(levelname)-8s %(message)s')
|
|
||||||
|
|
||||||
if args.jid is None:
|
|
||||||
args.jid = input("Username: ")
|
|
||||||
if args.password is None:
|
|
||||||
args.password = getpass("Password: ")
|
|
||||||
|
|
||||||
# Setup the bot and register plugins. Note that while plugins may
|
|
||||||
# have interdependencies, the order in which you register them does
|
|
||||||
# not matter.
|
|
||||||
xmpp = Slixmark(args.jid, args.password)
|
|
||||||
xmpp.register_plugin('xep_0030') # Service Discovery
|
|
||||||
xmpp.register_plugin('xep_0004') # Data Forms
|
|
||||||
xmpp.register_plugin('xep_0060') # Publish-Subscribe
|
|
||||||
xmpp.register_plugin('xep_0050') # Ad-Hoc Commands
|
|
||||||
xmpp.register_plugin('xep_0115') # Entity Capabilities
|
|
||||||
xmpp.register_plugin('xep_0122') # Data Forms Validation
|
|
||||||
xmpp.register_plugin('xep_0199') # XMPP Ping
|
|
||||||
|
|
||||||
# Connect to the XMPP server and start processing XMPP stanzas.
|
|
||||||
xmpp.connect()
|
|
||||||
xmpp.process()
|
|
Loading…
Reference in a new issue