massive refactoring to switch from camelCase to snake_case:

historically, Libervia (SàT before) was using camelCase as allowed by PEP8 when using a
pre-PEP8 code, to use the same coding style as in Twisted.

However, snake_case is more readable and it's better to follow PEP8 best practices, so it
has been decided to move on full snake_case. Because Libervia has a huge codebase, this
ended with a ugly mix of camelCase and snake_case.

To fix that, this patch does a big refactoring by renaming every function and method
(including bridge) that are not coming from Twisted or Wokkel, to use fully snake_case.

This is a massive change, and may result in some bugs.
This commit is contained in:
Goffi 2023-04-08 13:54:42 +02:00
commit 6a6f15707a
131 changed files with 9945 additions and 9945 deletions

View file

@ -98,39 +98,39 @@ class AdHocDBus(object):
log.info(_("plugin Ad-Hoc D-Bus initialization"))
self.host = host
if etree is not None:
host.bridge.addMethod(
"adHocDBusAddAuto",
host.bridge.add_method(
"ad_hoc_dbus_add_auto",
".plugin",
in_sign="sasasasasasass",
out_sign="(sa(sss))",
method=self._adHocDBusAddAuto,
method=self._ad_hoc_dbus_add_auto,
async_=True,
)
host.bridge.addMethod(
"adHocRemotesGet",
host.bridge.add_method(
"ad_hoc_remotes_get",
".plugin",
in_sign="s",
out_sign="a(sss)",
method=self._adHocRemotesGet,
method=self._ad_hoc_remotes_get,
async_=True,
)
self._c = host.plugins["XEP-0050"]
host.registerNamespace("mediaplayer", NS_MEDIA_PLAYER)
host.register_namespace("mediaplayer", NS_MEDIA_PLAYER)
if dbus is not None:
self.session_bus = dbus.SessionBus()
self.fd_object = self.session_bus.get_object(
FD_NAME, FD_PATH, introspect=False)
def profileConnected(self, client):
def profile_connected(self, client):
if dbus is not None:
self._c.addAdHocCommand(
client, self.localMediaCb, D_("Media Players"),
self._c.add_ad_hoc_command(
client, self.local_media_cb, D_("Media Players"),
node=NS_MEDIA_PLAYER,
timeout=60*60*6 # 6 hours timeout, to avoid breaking remote
# in the middle of a movie
)
def _DBusAsyncCall(self, proxy, method, *args, **kwargs):
def _dbus_async_call(self, proxy, method, *args, **kwargs):
""" Call a DBus method asynchronously and return a deferred
@param proxy: DBus object proxy, as returner by get_object
@ -149,18 +149,18 @@ class AdHocDBus(object):
proxy.get_dbus_method(method, dbus_interface=interface)(*args, **kwargs)
return d
def _DBusGetProperty(self, proxy, interface, name):
return self._DBusAsyncCall(
def _dbus_get_property(self, proxy, interface, name):
return self._dbus_async_call(
proxy, "Get", interface, name, interface="org.freedesktop.DBus.Properties")
def _DBusListNames(self):
return self._DBusAsyncCall(self.fd_object, "ListNames")
def _dbus_list_names(self):
return self._dbus_async_call(self.fd_object, "ListNames")
def _DBusIntrospect(self, proxy):
return self._DBusAsyncCall(proxy, INTROSPECT_METHOD, interface=INTROSPECT_IFACE)
def _dbus_introspect(self, proxy):
return self._dbus_async_call(proxy, INTROSPECT_METHOD, interface=INTROSPECT_IFACE)
def _acceptMethod(self, method):
def _accept_method(self, method):
""" Return True if we accept the method for a command
@param method: etree.Element
@return: True if the method is acceptable
@ -175,7 +175,7 @@ class AdHocDBus(object):
@defer.inlineCallbacks
def _introspect(self, methods, bus_name, proxy):
log.debug("introspecting path [%s]" % proxy.object_path)
introspect_xml = yield self._DBusIntrospect(proxy)
introspect_xml = yield self._dbus_introspect(proxy)
el = etree.fromstring(introspect_xml)
for node in el.iterchildren("node", "interface"):
if node.tag == "node":
@ -191,23 +191,23 @@ class AdHocDBus(object):
continue
log.debug("introspecting interface [%s]" % name)
for method in node.iterchildren("method"):
if self._acceptMethod(method):
if self._accept_method(method):
method_name = method.get("name")
log.debug("method accepted: [%s]" % method_name)
methods.add((proxy.object_path, name, method_name))
def _adHocDBusAddAuto(self, prog_name, allowed_jids, allowed_groups, allowed_magics,
def _ad_hoc_dbus_add_auto(self, prog_name, allowed_jids, allowed_groups, allowed_magics,
forbidden_jids, forbidden_groups, flags, profile_key):
client = self.host.getClient(profile_key)
return self.adHocDBusAddAuto(
client = self.host.get_client(profile_key)
return self.ad_hoc_dbus_add_auto(
client, prog_name, allowed_jids, allowed_groups, allowed_magics,
forbidden_jids, forbidden_groups, flags)
@defer.inlineCallbacks
def adHocDBusAddAuto(self, client, prog_name, allowed_jids=None, allowed_groups=None,
def ad_hoc_dbus_add_auto(self, client, prog_name, allowed_jids=None, allowed_groups=None,
allowed_magics=None, forbidden_jids=None, forbidden_groups=None,
flags=None):
bus_names = yield self._DBusListNames()
bus_names = yield self._dbus_list_names()
bus_names = [bus_name for bus_name in bus_names if "." + prog_name in bus_name]
if not bus_names:
log.info("Can't find any bus for [%s]" % prog_name)
@ -223,7 +223,7 @@ class AdHocDBus(object):
yield self._introspect(methods, bus_name, proxy)
if methods:
self._addCommand(
self._add_command(
client,
prog_name,
bus_name,
@ -238,13 +238,13 @@ class AdHocDBus(object):
defer.returnValue((str(bus_name), methods))
def _addCommand(self, client, adhoc_name, bus_name, methods, allowed_jids=None,
def _add_command(self, client, adhoc_name, bus_name, methods, allowed_jids=None,
allowed_groups=None, allowed_magics=None, forbidden_jids=None,
forbidden_groups=None, flags=None):
if flags is None:
flags = set()
def DBusCallback(client, command_elt, session_data, action, node):
def d_bus_callback(client, command_elt, session_data, action, node):
actions = session_data.setdefault("actions", [])
names_map = session_data.setdefault("names_map", {})
actions.append(action)
@ -283,7 +283,7 @@ class AdHocDBus(object):
path, iface, command = names_map[command]
proxy = self.session_bus.get_object(bus_name, path)
self._DBusAsyncCall(proxy, command, interface=iface)
self._dbus_async_call(proxy, command, interface=iface)
# job done, we can end the session, except if we have FLAG_LOOP
if FLAG_LOOP in flags:
@ -292,7 +292,7 @@ class AdHocDBus(object):
# is OK)
del actions[:]
names_map.clear()
return DBusCallback(
return d_bus_callback(
client, None, session_data, self._c.ACTION.EXECUTE, node
)
form = data_form.Form("form", title=_("Updated"))
@ -305,9 +305,9 @@ class AdHocDBus(object):
return (payload, status, None, note)
self._c.addAdHocCommand(
self._c.add_ad_hoc_command(
client,
DBusCallback,
d_bus_callback,
adhoc_name,
allowed_jids=allowed_jids,
allowed_groups=allowed_groups,
@ -318,18 +318,18 @@ class AdHocDBus(object):
## Local media ##
def _adHocRemotesGet(self, profile):
return self.adHocRemotesGet(self.host.getClient(profile))
def _ad_hoc_remotes_get(self, profile):
return self.ad_hoc_remotes_get(self.host.get_client(profile))
@defer.inlineCallbacks
def adHocRemotesGet(self, client):
def ad_hoc_remotes_get(self, client):
"""Retrieve available remote media controlers in our devices
@return (list[tuple[unicode, unicode, unicode]]): list of devices with:
- entity full jid
- device name
- device label
"""
found_data = yield defer.ensureDeferred(self.host.findByFeatures(
found_data = yield defer.ensureDeferred(self.host.find_by_features(
client, [self.host.ns_map['commands']], service=False, roster=False,
own_jid=True, local_device=True))
@ -344,7 +344,7 @@ class AdHocDBus(object):
try:
result_elt = yield self._c.do(client, device_jid,
NS_MEDIA_PLAYER, timeout=5)
command_elt = self._c.getCommandElt(result_elt)
command_elt = self._c.get_command_elt(result_elt)
form = data_form.findForm(command_elt, NS_MEDIA_PLAYER)
if form is None:
continue
@ -368,7 +368,7 @@ class AdHocDBus(object):
break
defer.returnValue(remotes)
def doMPRISCommand(self, proxy, command):
def do_mpris_command(self, proxy, command):
iface, command = command.rsplit(".", 1)
if command == CMD_GO_BACK:
command = 'Seek'
@ -378,9 +378,9 @@ class AdHocDBus(object):
args = [SEEK_OFFSET]
else:
args = []
return self._DBusAsyncCall(proxy, command, *args, interface=iface)
return self._dbus_async_call(proxy, command, *args, interface=iface)
def addMPRISMetadata(self, form, metadata):
def add_mpris_metadata(self, form, metadata):
"""Serialise MRPIS Metadata according to MPRIS_METADATA_MAP"""
for mpris_key, name in MPRIS_METADATA_MAP.items():
if mpris_key in metadata:
@ -390,7 +390,7 @@ class AdHocDBus(object):
value=value))
@defer.inlineCallbacks
def localMediaCb(self, client, command_elt, session_data, action, node):
def local_media_cb(self, client, command_elt, session_data, action, node):
try:
x_elt = next(command_elt.elements(data_form.NS_X_DATA, "x"))
command_form = data_form.Form.fromElement(x_elt)
@ -399,7 +399,7 @@ class AdHocDBus(object):
if command_form is None or len(command_form.fields) == 0:
# root request, we looks for media players
bus_names = yield self._DBusListNames()
bus_names = yield self._dbus_list_names()
bus_names = [b for b in bus_names if b.startswith(MPRIS_PREFIX)]
if len(bus_names) == 0:
note = (self._c.NOTE.INFO, D_("No media player found."))
@ -445,7 +445,7 @@ class AdHocDBus(object):
except KeyError:
pass
else:
yield self.doMPRISCommand(proxy, command)
yield self.do_mpris_command(proxy, command)
# we construct the remote control form
form = data_form.Form("form", title=D_("Media Player Selection"))
@ -455,13 +455,13 @@ class AdHocDBus(object):
for iface, properties_names in MPRIS_PROPERTIES.items():
for name in properties_names:
try:
value = yield self._DBusGetProperty(proxy, iface, name)
value = yield self._dbus_get_property(proxy, iface, name)
except Exception as e:
log.warning(_("Can't retrieve attribute {name}: {reason}")
.format(name=name, reason=e))
continue
if name == MPRIS_METADATA_KEY:
self.addMPRISMetadata(form, value)
self.add_mpris_metadata(form, value)
else:
form.addField(data_form.Field(fieldType="fixed",
var=name,

View file

@ -61,7 +61,7 @@ class BlogImportPlugin(object):
OPT_DEFAULTS = {OPT_UPLOAD_IMAGES: True, OPT_IGNORE_TLS: False}
def __init__(self, host):
log.info(_("plugin Blog Import initialization"))
log.info(_("plugin Blog import initialization"))
self.host = host
self._u = host.plugins["UPLOAD"]
self._p = host.plugins["XEP-0060"]
@ -69,10 +69,10 @@ class BlogImportPlugin(object):
self._s = self.host.plugins["TEXT_SYNTAXES"]
host.plugins["IMPORT"].initialize(self, "blog")
def importItem(
def import_item(
self, client, item_import_data, session, options, return_data, service, node
):
"""importItem specialized for blog import
"""import_item specialized for blog import
@param item_import_data(dict):
* mandatory keys:
@ -116,7 +116,7 @@ class BlogImportPlugin(object):
except KeyError:
pass
else:
new_uri = return_data[URL_REDIRECT_PREFIX + old_uri] = self._p.getNodeURI(
new_uri = return_data[URL_REDIRECT_PREFIX + old_uri] = self._p.get_node_uri(
service if service is not None else client.jid.userhostJID(),
node or self._m.namespace,
item_id,
@ -126,14 +126,14 @@ class BlogImportPlugin(object):
return mb_data
@defer.inlineCallbacks
def importSubItems(self, client, item_import_data, mb_data, session, options):
def import_sub_items(self, client, item_import_data, mb_data, session, options):
# comments data
if len(item_import_data["comments"]) != 1:
raise NotImplementedError("can't manage multiple comment links")
allow_comments = C.bool(mb_data.get("allow_comments", C.BOOL_FALSE))
if allow_comments:
comments_service = yield self._m.getCommentsService(client)
comments_node = self._m.getCommentsNode(mb_data["id"])
comments_service = yield self._m.get_comments_service(client)
comments_node = self._m.get_comments_node(mb_data["id"])
mb_data["comments_service"] = comments_service.full()
mb_data["comments_node"] = comments_node
recurse_kwargs = {
@ -149,7 +149,7 @@ class BlogImportPlugin(object):
)
defer.returnValue(None)
def publishItem(self, client, mb_data, service, node, session):
def publish_item(self, client, mb_data, service, node, session):
log.debug(
"uploading item [{id}]: {title}".format(
id=mb_data["id"], title=mb_data.get("title", "")
@ -158,7 +158,7 @@ class BlogImportPlugin(object):
return self._m.send(client, mb_data, service, node)
@defer.inlineCallbacks
def itemFilters(self, client, mb_data, session, options):
def item_filters(self, client, mb_data, session, options):
"""Apply filters according to options
modify mb_data in place
@ -188,7 +188,7 @@ class BlogImportPlugin(object):
)
# we convert rich syntax to XHTML here, so we can handle filters easily
converted = yield self._s.convert(
rich, self._s.getCurrentSyntax(client.profile), safe=False
rich, self._s.get_current_syntax(client.profile), safe=False
)
mb_data["{}_xhtml".format(prefix)] = converted
del mb_data["{}_rich".format(prefix)]
@ -220,7 +220,7 @@ class BlogImportPlugin(object):
)
except domish.ParserError:
# we clean the xml and try again our luck
cleaned = yield self._s.cleanXHTML(mb_data["content_xhtml"])
cleaned = yield self._s.clean_xhtml(mb_data["content_xhtml"])
top_elt = xml_tools.ElementParser()(cleaned, namespace=C.NS_XHTML)
opt_host = options.get(OPT_HOST)
if opt_host:
@ -239,8 +239,8 @@ class BlogImportPlugin(object):
tmp_dir = tempfile.mkdtemp()
try:
# TODO: would be nice to also update the hyperlinks to these images, e.g. when you have <a href="{url}"><img src="{url}"></a>
for img_elt in xml_tools.findAll(top_elt, names=["img"]):
yield self.imgFilters(client, img_elt, options, opt_host, tmp_dir)
for img_elt in xml_tools.find_all(top_elt, names=["img"]):
yield self.img_filters(client, img_elt, options, opt_host, tmp_dir)
finally:
os.rmdir(tmp_dir) # XXX: tmp_dir should be empty, or something went wrong
@ -248,7 +248,7 @@ class BlogImportPlugin(object):
mb_data["content_xhtml"] = top_elt.toXml()
@defer.inlineCallbacks
def imgFilters(self, client, img_elt, options, opt_host, tmp_dir):
def img_filters(self, client, img_elt, options, opt_host, tmp_dir):
"""Filters handling images
url without host are fixed (if possible)

View file

@ -123,7 +123,7 @@ class Importer(DokuWiki):
self.limit = limit
self.posts_data = OrderedDict()
def getPostId(self, post):
def get_post_id(self, post):
"""Return a unique and constant post id
@param post(dict): parsed post data
@ -131,7 +131,7 @@ class Importer(DokuWiki):
"""
return str(post["id"])
def getPostUpdated(self, post):
def get_post_updated(self, post):
"""Return the update date.
@param post(dict): parsed post data
@ -139,7 +139,7 @@ class Importer(DokuWiki):
"""
return str(post["mtime"])
def getPostPublished(self, post):
def get_post_published(self, post):
"""Try to parse the date from the message ID, else use "mtime".
The date can be extracted if the message ID looks like one of:
@ -162,16 +162,16 @@ class Importer(DokuWiki):
return default
return str(calendar.timegm(time_struct))
def processPost(self, post, profile_jid):
def process_post(self, post, profile_jid):
"""Process a single page.
@param post (dict): parsed post data
@param profile_jid
"""
# get main information
id_ = self.getPostId(post)
updated = self.getPostUpdated(post)
published = self.getPostPublished(post)
id_ = self.get_post_id(post)
updated = self.get_post_updated(post)
published = self.get_post_published(post)
# manage links
backlinks = self.pages.backlinks(id_)
@ -182,7 +182,7 @@ class Importer(DokuWiki):
backlinks.append(page[1:] if page.startswith(":") else page)
self.pages.get(id_)
content_xhtml = self.processContent(self.pages.html(id_), backlinks, profile_jid)
content_xhtml = self.process_content(self.pages.html(id_), backlinks, profile_jid)
# XXX: title is already in content_xhtml and difficult to remove, so leave it
# title = content.split("\n")[0].strip(u"\ufeff= ")
@ -230,14 +230,14 @@ class Importer(DokuWiki):
count = 0
for page in pages_list:
self.processPost(page, profile_jid)
self.process_post(page, profile_jid)
count += 1
if count >= self.limit:
break
return (iter(self.posts_data.values()), len(self.posts_data))
def processContent(self, text, backlinks, profile_jid):
def process_content(self, text, backlinks, profile_jid):
"""Do text substitutions and file copy.
@param text (unicode): message content
@ -259,7 +259,7 @@ class Importer(DokuWiki):
if re.match(r"^\w*://", link): # absolute URL to link directly
continue
if self.media_repo:
self.moveMedia(link, subs)
self.move_media(link, subs)
elif link not in subs:
subs[link] = urllib.parse.urljoin(self.url, link)
@ -267,7 +267,7 @@ class Importer(DokuWiki):
text = text.replace(url, new_url)
return text
def moveMedia(self, link, subs):
def move_media(self, link, subs):
"""Move a media from the DokuWiki host to the new repository.
This also updates the hyperlinks to internal media files.
@ -304,17 +304,17 @@ class Importer(DokuWiki):
return
filepath = os.path.join(self.temp_dir, filename)
self.downloadMedia(url, filepath)
self.download_media(url, filepath)
if thumb_width:
filename = os.path.join("thumbs", thumb_width, filename)
thumbnail = os.path.join(self.temp_dir, filename)
self.createThumbnail(filepath, thumbnail, thumb_width)
self.create_thumbnail(filepath, thumbnail, thumb_width)
new_url = os.path.join(self.media_repo, filename)
subs[link] = new_url
def downloadMedia(self, source, dest):
def download_media(self, source, dest):
"""Copy media to localhost.
@param source (unicode): source url
@ -327,7 +327,7 @@ class Importer(DokuWiki):
urllib.request.urlretrieve(source, dest)
log.debug("DokuWiki media file copied to %s" % dest)
def createThumbnail(self, source, dest, width):
def create_thumbnail(self, source, dest, width):
"""Create a thumbnail.
@param source (unicode): source file path
@ -348,13 +348,13 @@ class Importer(DokuWiki):
class DokuwikiImport(object):
def __init__(self, host):
log.info(_("plugin Dokuwiki Import initialization"))
log.info(_("plugin Dokuwiki import initialization"))
self.host = host
self._blog_import = host.plugins["BLOG_IMPORT"]
self._blog_import.register("dokuwiki", self.DkImport, SHORT_DESC, LONG_DESC)
self._blog_import.register("dokuwiki", self.dk_import, SHORT_DESC, LONG_DESC)
def DkImport(self, client, location, options=None):
"""Import from DokuWiki to PubSub
def dk_import(self, client, location, options=None):
"""import from DokuWiki to PubSub
@param location (unicode): DokuWiki site URL
@param options (dict, None): DokuWiki import parameters
@ -407,7 +407,7 @@ class DokuwikiImport(object):
info_msg = info_msg.format(
temp_dir=dk_importer.temp_dir, media_repo=media_repo, location=location
)
self.host.actionNew(
self.host.action_new(
{"xmlui": xml_tools.note(info_msg).toXml()}, profile=client.profile
)
d = threads.deferToThread(dk_importer.process, client, namespace)

View file

@ -50,7 +50,7 @@ LONG_DESC = D_(
To use it, you'll need to export your blog to a flat file.
You must go in your admin interface and select Plugins/Maintenance then Backup.
Export only one blog if you have many, i.e. select "Download database of current blog"
Depending on your configuration, your may need to use Import/Export plugin and export as a flat file.
Depending on your configuration, your may need to use import/Export plugin and export as a flat file.
location: you must use the absolute path to your backup for the location parameter
"""
@ -77,7 +77,7 @@ class DotclearParser(object):
self.posts_data = OrderedDict()
self.tags = {}
def getPostId(self, post):
def get_post_id(self, post):
"""Return a unique and constant post id
@param post(dict): parsed post data
@ -91,7 +91,7 @@ class DotclearParser(object):
post["post_url"],
)
def getCommentId(self, comment):
def get_comment_id(self, comment):
"""Return a unique and constant comment id
@param comment(dict): parsed comment
@ -110,7 +110,7 @@ class DotclearParser(object):
"""
return time.mktime(time.strptime(data[key], "%Y-%m-%d %H:%M:%S"))
def readFields(self, fields_data):
def read_fields(self, fields_data):
buf = []
idx = 0
while True:
@ -148,13 +148,13 @@ class DotclearParser(object):
buf.append(char)
def parseFields(self, headers, data):
return dict(zip(headers, self.readFields(data)))
return dict(zip(headers, self.read_fields(data)))
def postHandler(self, headers, data, index):
def post_handler(self, headers, data, index):
post = self.parseFields(headers, data)
log.debug("({}) post found: {}".format(index, post["post_title"]))
mb_data = {
"id": self.getPostId(post),
"id": self.get_post_id(post),
"published": self.getTime(post, "post_creadt"),
"updated": self.getTime(post, "post_upddt"),
"author": post["user_id"], # there use info are not in the archive
@ -163,7 +163,7 @@ class DotclearParser(object):
post["post_content_xhtml"], post["post_excerpt_xhtml"]
),
"title": post["post_title"],
"allow_comments": C.boolConst(bool(int(post["post_open_comment"]))),
"allow_comments": C.bool_const(bool(int(post["post_open_comment"]))),
}
self.posts_data[post["post_id"]] = {
"blog": mb_data,
@ -171,18 +171,18 @@ class DotclearParser(object):
"url": "/post/{}".format(post["post_url"]),
}
def metaHandler(self, headers, data, index):
def meta_handler(self, headers, data, index):
meta = self.parseFields(headers, data)
if meta["meta_type"] == "tag":
tags = self.tags.setdefault(meta["post_id"], set())
tags.add(meta["meta_id"])
def metaFinishedHandler(self):
def meta_finished_handler(self):
for post_id, tags in self.tags.items():
data_format.iter2dict("tag", tags, self.posts_data[post_id]["blog"])
del self.tags
def commentHandler(self, headers, data, index):
def comment_handler(self, headers, data, index):
comment = self.parseFields(headers, data)
if comment["comment_site"]:
# we don't use atom:uri because it's used for jid in XMPP
@ -193,7 +193,7 @@ class DotclearParser(object):
else:
content = comment["comment_content"]
mb_data = {
"id": self.getCommentId(comment),
"id": self.get_comment_id(comment),
"published": self.getTime(comment, "comment_dt"),
"updated": self.getTime(comment, "comment_upddt"),
"author": comment["comment_author"],
@ -263,13 +263,13 @@ class DotclearParser(object):
class DotclearImport(object):
def __init__(self, host):
log.info(_("plugin Dotclear Import initialization"))
log.info(_("plugin Dotclear import initialization"))
self.host = host
host.plugins["BLOG_IMPORT"].register(
"dotclear", self.DcImport, SHORT_DESC, LONG_DESC
"dotclear", self.dc_import, SHORT_DESC, LONG_DESC
)
def DcImport(self, client, location, options=None):
def dc_import(self, client, location, options=None):
if not os.path.isabs(location):
raise exceptions.DataError(
"An absolute path to backup data need to be given as location"

File diff suppressed because it is too large Load diff

View file

@ -38,7 +38,7 @@ class APAdHocService:
self._c = self.host.plugins["XEP-0050"]
def init(self, client: SatXMPPEntity) -> None:
self._c.addAdHocCommand(
self._c.add_ad_hoc_command(
client,
self.xmpp_jid_node_2_ap_actor,
"Convert XMPP JID/Node to AP actor",
@ -82,7 +82,7 @@ class APAdHocService:
else:
xmpp_jid = jid.JID(command_form["jid"])
xmpp_node = command_form.get("node")
actor = await self.apg.getAPAccountFromJidAndNode(xmpp_jid, xmpp_node)
actor = await self.apg.get_ap_account_from_jid_and_node(xmpp_jid, xmpp_node)
note = (self._c.NOTE.INFO, actor)
status = self._c.STATUS.COMPLETED
payload = None

View file

@ -113,12 +113,12 @@ class APEvents:
"""
if not event_data.get("id"):
event_data["id"] = shortuuid.uuid()
ap_account = await self.apg.getAPAccountFromJidAndNode(
ap_account = await self.apg.get_ap_account_from_jid_and_node(
author_jid,
self._events.namespace
)
url_actor = self.apg.buildAPURL(TYPE_ACTOR, ap_account)
url_item = self.apg.buildAPURL(TYPE_ITEM, ap_account, event_data["id"])
url_actor = self.apg.build_apurl(TYPE_ACTOR, ap_account)
url_item = self.apg.build_apurl(TYPE_ITEM, ap_account, event_data["id"])
ap_object = {
"actor": url_actor,
"attributedTo": url_actor,
@ -246,7 +246,7 @@ class APEvents:
"""
is_activity = self.apg.is_activity(ap_item)
if is_activity:
ap_object = await self.apg.apGetObject(ap_item, "object")
ap_object = await self.apg.ap_get_object(ap_item, "object")
if not ap_object:
log.warning(f'No "object" found in AP item {ap_item!r}')
raise exceptions.DataError
@ -257,7 +257,7 @@ class APEvents:
if "_repeated" in ap_item:
# if the event is repeated, we use the original one ID
repeated_uri = ap_item["_repeated"]["uri"]
parsed_uri = uri.parseXMPPUri(repeated_uri)
parsed_uri = uri.parse_xmpp_uri(repeated_uri)
object_id = parsed_uri["item"]
else:
object_id = ap_object.get("id")
@ -268,10 +268,10 @@ class APEvents:
raise exceptions.DataError("AP Object is not an event")
# author
actor = await self.apg.apGetSenderActor(ap_object)
actor = await self.apg.ap_get_sender_actor(ap_object)
account = await self.apg.getAPAccountFromId(actor)
author_jid = self.apg.getLocalJIDFromAccount(account).full()
account = await self.apg.get_ap_account_from_id(actor)
author_jid = self.apg.get_local_jid_from_account(account).full()
# name, start, end
event_data = {
@ -370,7 +370,7 @@ class APEvents:
# comments
if ap_object.get("commentsEnabled"):
__, comments_node = await self.apg.getCommentsNodes(object_id, None)
__, comments_node = await self.apg.get_comments_nodes(object_id, None)
event_data["comments"] = {
"service": author_jid,
"node": comments_node,

View file

@ -66,7 +66,7 @@ class HTTPAPGServer(web_resource.Resource):
self._seen_digest = deque(maxlen=50)
super().__init__()
def responseCode(
def response_code(
self,
request: "HTTPRequest",
http_code: int,
@ -77,17 +77,17 @@ class HTTPAPGServer(web_resource.Resource):
log.warning(msg)
request.setResponseCode(http_code, None if msg is None else msg.encode())
def _onRequestError(self, failure_: failure.Failure, request: "HTTPRequest") -> None:
def _on_request_error(self, failure_: failure.Failure, request: "HTTPRequest") -> None:
exc = failure_.value
if isinstance(exc, exceptions.NotFound):
self.responseCode(
self.response_code(
request,
http.NOT_FOUND,
str(exc)
)
else:
log.exception(f"Internal error: {failure_.value}")
self.responseCode(
self.response_code(
request,
http.INTERNAL_SERVER_ERROR,
f"internal error: {failure_.value}"
@ -107,7 +107,7 @@ class HTTPAPGServer(web_resource.Resource):
http.BAD_REQUEST, "Bad Request" , "Invalid webfinger resource"
).render(request)
actor_url = self.apg.buildAPURL(TYPE_ACTOR, account)
actor_url = self.apg.build_apurl(TYPE_ACTOR, account)
resp = {
"aliases": [actor_url],
@ -124,7 +124,7 @@ class HTTPAPGServer(web_resource.Resource):
request.write(json.dumps(resp).encode())
request.finish()
async def handleUndoActivity(
async def handle_undo_activity(
self,
request: "HTTPRequest",
data: dict,
@ -136,7 +136,7 @@ class HTTPAPGServer(web_resource.Resource):
) -> None:
if node is None:
node = self.apg._m.namespace
client = await self.apg.getVirtualClient(signing_actor)
client = await self.apg.get_virtual_client(signing_actor)
object_ = data.get("object")
if isinstance(object_, str):
# we check first if it's not a cached object
@ -149,10 +149,10 @@ class HTTPAPGServer(web_resource.Resource):
# because we'll undo the activity, we can remove it from cache
await self.apg.client._ap_storage.remove(ap_cache_key)
else:
objects = await self.apg.apGetList(data, "object")
objects = await self.apg.ap_get_list(data, "object")
for obj in objects:
type_ = obj.get("type")
actor = await self.apg.apGetSenderActor(obj)
actor = await self.apg.ap_get_sender_actor(obj)
if actor != signing_actor:
log.warning(f"ignoring object not attributed to signing actor: {data}")
continue
@ -163,7 +163,7 @@ class HTTPAPGServer(web_resource.Resource):
except KeyError:
log.warning(f'ignoring invalid object, missing "object" key: {data}')
continue
if not self.apg.isLocalURL(target_account):
if not self.apg.is_local_url(target_account):
log.warning(f"ignoring unfollow request to non local actor: {data}")
continue
await self.apg._p.unsubscribe(
@ -175,17 +175,17 @@ class HTTPAPGServer(web_resource.Resource):
elif type_ == "Announce":
# we can use directly the Announce object, as only the "id" field is
# needed
await self.apg.newAPDeleteItem(client, None, node, obj)
await self.apg.new_ap_delete_item(client, None, node, obj)
elif type_ == TYPE_LIKE:
await self.handleAttachmentItem(client, obj, {"noticed": False})
await self.handle_attachment_item(client, obj, {"noticed": False})
elif type_ == TYPE_REACTION:
await self.handleAttachmentItem(client, obj, {
await self.handle_attachment_item(client, obj, {
"reactions": {"operation": "update", "remove": [obj["content"]]}
})
else:
log.warning(f"Unmanaged undo type: {type_!r}")
async def handleFollowActivity(
async def handle_follow_activity(
self,
request: "HTTPRequest",
data: dict,
@ -197,14 +197,14 @@ class HTTPAPGServer(web_resource.Resource):
) -> None:
if node is None:
node = self.apg._m.namespace
client = await self.apg.getVirtualClient(signing_actor)
client = await self.apg.get_virtual_client(signing_actor)
try:
subscription = await self.apg._p.subscribe(
client,
account_jid,
node,
# subscriptions from AP are always public
options=self.apg._pps.setPublicOpt()
options=self.apg._pps.set_public_opt()
)
except pubsub.SubscriptionPending:
log.info(f"subscription to node {node!r} of {account_jid} is pending")
@ -213,15 +213,15 @@ class HTTPAPGServer(web_resource.Resource):
if subscription.state != "subscribed":
# other states should raise an Exception
raise exceptions.InternalError('"subscribed" state was expected')
inbox = await self.apg.getAPInboxFromId(signing_actor, use_shared=False)
actor_id = self.apg.buildAPURL(TYPE_ACTOR, ap_account)
inbox = await self.apg.get_ap_inbox_from_id(signing_actor, use_shared=False)
actor_id = self.apg.build_apurl(TYPE_ACTOR, ap_account)
accept_data = self.apg.create_activity(
"Accept", actor_id, object_=data
)
await self.apg.signAndPost(inbox, actor_id, accept_data)
await self.apg.sign_and_post(inbox, actor_id, accept_data)
await self.apg._c.synchronise(client, account_jid, node, resync=False)
async def handleAcceptActivity(
async def handle_accept_activity(
self,
request: "HTTPRequest",
data: dict,
@ -233,12 +233,12 @@ class HTTPAPGServer(web_resource.Resource):
) -> None:
if node is None:
node = self.apg._m.namespace
client = await self.apg.getVirtualClient(signing_actor)
objects = await self.apg.apGetList(data, "object")
client = await self.apg.get_virtual_client(signing_actor)
objects = await self.apg.ap_get_list(data, "object")
for obj in objects:
type_ = obj.get("type")
if type_ == "Follow":
follow_node = await self.apg.host.memory.storage.getPubsubNode(
follow_node = await self.apg.host.memory.storage.get_pubsub_node(
client, client.jid, node, with_subscriptions=True
)
if follow_node is None:
@ -270,7 +270,7 @@ class HTTPAPGServer(web_resource.Resource):
else:
log.warning(f"Unmanaged accept type: {type_!r}")
async def handleDeleteActivity(
async def handle_delete_activity(
self,
request: "HTTPRequest",
data: dict,
@ -282,12 +282,12 @@ class HTTPAPGServer(web_resource.Resource):
):
if node is None:
node = self.apg._m.namespace
client = await self.apg.getVirtualClient(signing_actor)
objects = await self.apg.apGetList(data, "object")
client = await self.apg.get_virtual_client(signing_actor)
objects = await self.apg.ap_get_list(data, "object")
for obj in objects:
await self.apg.newAPDeleteItem(client, account_jid, node, obj)
await self.apg.new_ap_delete_item(client, account_jid, node, obj)
async def handleNewAPItems(
async def handle_new_ap_items(
self,
request: "HTTPRequest",
data: dict,
@ -298,7 +298,7 @@ class HTTPAPGServer(web_resource.Resource):
):
"""Helper method to handle workflow for new AP items
accept globally the same parameter as for handleCreateActivity
accept globally the same parameter as for handle_create_activity
@param repeated: if True, the item is an item republished from somewhere else
"""
if "_repeated" in data:
@ -307,25 +307,25 @@ class HTTPAPGServer(web_resource.Resource):
f"happen. Ignoring object from {signing_actor}\n{data}"
)
raise exceptions.DataError("unexpected field in item")
client = await self.apg.getVirtualClient(signing_actor)
objects = await self.apg.apGetList(data, "object")
client = await self.apg.get_virtual_client(signing_actor)
objects = await self.apg.ap_get_list(data, "object")
for obj in objects:
if node is None:
if obj.get("type") == TYPE_EVENT:
node = self.apg._events.namespace
else:
node = self.apg._m.namespace
sender = await self.apg.apGetSenderActor(obj)
sender = await self.apg.ap_get_sender_actor(obj)
if repeated:
# we don't check sender when item is repeated, as it should be different
# from post author in this case
sender_jid = await self.apg.getJIDFromId(sender)
repeater_jid = await self.apg.getJIDFromId(signing_actor)
sender_jid = await self.apg.get_jid_from_id(sender)
repeater_jid = await self.apg.get_jid_from_id(signing_actor)
repeated_item_id = obj["id"]
if self.apg.isLocalURL(repeated_item_id):
if self.apg.is_local_url(repeated_item_id):
# the repeated object is from XMPP, we need to parse the URL to find
# the right ID
url_type, url_args = self.apg.parseAPURL(repeated_item_id)
url_type, url_args = self.apg.parse_apurl(repeated_item_id)
if url_type != "item":
raise exceptions.DataError(
"local URI is not an item: {repeated_id}"
@ -339,7 +339,7 @@ class HTTPAPGServer(web_resource.Resource):
"local URI is invalid: {repeated_id}"
)
else:
url_jid, url_node = await self.apg.getJIDAndNode(url_account)
url_jid, url_node = await self.apg.get_jid_and_node(url_account)
if ((url_jid != sender_jid
or url_node and url_node != self.apg._m.namespace)):
raise exceptions.DataError(
@ -352,7 +352,7 @@ class HTTPAPGServer(web_resource.Resource):
obj["_repeated"] = {
"by": repeater_jid.full(),
"at": data.get("published"),
"uri": uri.buildXMPPUri(
"uri": uri.build_xmpp_uri(
"pubsub",
path=sender_jid.full(),
node=self.apg._m.namespace,
@ -369,9 +369,9 @@ class HTTPAPGServer(web_resource.Resource):
)
continue
await self.apg.newAPItem(client, account_jid, node, obj)
await self.apg.new_ap_item(client, account_jid, node, obj)
async def handleCreateActivity(
async def handle_create_activity(
self,
request: "HTTPRequest",
data: dict,
@ -381,9 +381,9 @@ class HTTPAPGServer(web_resource.Resource):
ap_url: str,
signing_actor: str
):
await self.handleNewAPItems(request, data, account_jid, node, signing_actor)
await self.handle_new_ap_items(request, data, account_jid, node, signing_actor)
async def handleUpdateActivity(
async def handle_update_activity(
self,
request: "HTTPRequest",
data: dict,
@ -395,9 +395,9 @@ class HTTPAPGServer(web_resource.Resource):
):
# Update is the same as create: the item ID stays the same, thus the item will be
# overwritten
await self.handleNewAPItems(request, data, account_jid, node, signing_actor)
await self.handle_new_ap_items(request, data, account_jid, node, signing_actor)
async def handleAnnounceActivity(
async def handle_announce_activity(
self,
request: "HTTPRequest",
data: dict,
@ -408,7 +408,7 @@ class HTTPAPGServer(web_resource.Resource):
signing_actor: str
):
# we create a new item
await self.handleNewAPItems(
await self.handle_new_ap_items(
request,
data,
account_jid,
@ -417,7 +417,7 @@ class HTTPAPGServer(web_resource.Resource):
repeated=True
)
async def handleAttachmentItem(
async def handle_attachment_item(
self,
client: SatXMPPEntity,
data: dict,
@ -447,10 +447,10 @@ class HTTPAPGServer(web_resource.Resource):
await client._ap_storage.aset(f"{ST_AP_CACHE}{data['id']}", data)
for target_id in target_ids:
if not self.apg.isLocalURL(target_id):
if not self.apg.is_local_url(target_id):
log.debug(f"ignoring non local target ID: {target_id}")
continue
url_type, url_args = self.apg.parseAPURL(target_id)
url_type, url_args = self.apg.parse_apurl(target_id)
if url_type != TYPE_ITEM:
log.warning(f"unexpected local URL for attachment on item {target_id}")
continue
@ -458,20 +458,20 @@ class HTTPAPGServer(web_resource.Resource):
account, item_id = url_args
except ValueError:
raise ValueError(f"invalid URL: {target_id}")
author_jid, item_node = await self.apg.getJIDAndNode(account)
author_jid, item_node = await self.apg.get_jid_and_node(account)
if item_node is None:
item_node = self.apg._m.namespace
attachment_node = self.apg._pa.getAttachmentNodeName(
attachment_node = self.apg._pa.get_attachment_node_name(
author_jid, item_node, item_id
)
cached_node = await self.apg.host.memory.storage.getPubsubNode(
cached_node = await self.apg.host.memory.storage.get_pubsub_node(
client,
author_jid,
attachment_node,
with_subscriptions=True,
create=True
)
found_items, __ = await self.apg.host.memory.storage.getItems(
found_items, __ = await self.apg.host.memory.storage.get_items(
cached_node, item_ids=[client.jid.userhost()]
)
if not found_items:
@ -487,16 +487,16 @@ class HTTPAPGServer(web_resource.Resource):
None
)
# we reparse the element, as there can be other attachments
attachments_data = self.apg._pa.items2attachmentData(client, [item_elt])
attachments_data = self.apg._pa.items_2_attachment_data(client, [item_elt])
# and we update the cache
await self.apg.host.memory.storage.cachePubsubItems(
await self.apg.host.memory.storage.cache_pubsub_items(
client,
cached_node,
[item_elt],
attachments_data or [{}]
)
if self.apg.isVirtualJID(author_jid):
if self.apg.is_virtual_jid(author_jid):
# the attachment is on t a virtual pubsub service (linking to an AP item),
# we notify all subscribers
for subscription in cached_node.subscriptions:
@ -509,11 +509,11 @@ class HTTPAPGServer(web_resource.Resource):
)
else:
# the attachment is on an XMPP item, we publish it to the attachment node
await self.apg._p.sendItems(
await self.apg._p.send_items(
client, author_jid, attachment_node, [item_elt]
)
async def handleLikeActivity(
async def handle_like_activity(
self,
request: "HTTPRequest",
data: dict,
@ -523,10 +523,10 @@ class HTTPAPGServer(web_resource.Resource):
ap_url: str,
signing_actor: str
) -> None:
client = await self.apg.getVirtualClient(signing_actor)
await self.handleAttachmentItem(client, data, {"noticed": True})
client = await self.apg.get_virtual_client(signing_actor)
await self.handle_attachment_item(client, data, {"noticed": True})
async def handleEmojireactActivity(
async def handle_emojireact_activity(
self,
request: "HTTPRequest",
data: dict,
@ -536,12 +536,12 @@ class HTTPAPGServer(web_resource.Resource):
ap_url: str,
signing_actor: str
) -> None:
client = await self.apg.getVirtualClient(signing_actor)
await self.handleAttachmentItem(client, data, {
client = await self.apg.get_virtual_client(signing_actor)
await self.handle_attachment_item(client, data, {
"reactions": {"operation": "update", "add": [data["content"]]}
})
async def handleJoinActivity(
async def handle_join_activity(
self,
request: "HTTPRequest",
data: dict,
@ -551,10 +551,10 @@ class HTTPAPGServer(web_resource.Resource):
ap_url: str,
signing_actor: str
) -> None:
client = await self.apg.getVirtualClient(signing_actor)
await self.handleAttachmentItem(client, data, {"rsvp": {"attending": "yes"}})
client = await self.apg.get_virtual_client(signing_actor)
await self.handle_attachment_item(client, data, {"rsvp": {"attending": "yes"}})
async def handleLeaveActivity(
async def handle_leave_activity(
self,
request: "HTTPRequest",
data: dict,
@ -564,10 +564,10 @@ class HTTPAPGServer(web_resource.Resource):
ap_url: str,
signing_actor: str
) -> None:
client = await self.apg.getVirtualClient(signing_actor)
await self.handleAttachmentItem(client, data, {"rsvp": {"attending": "no"}})
client = await self.apg.get_virtual_client(signing_actor)
await self.handle_attachment_item(client, data, {"rsvp": {"attending": "no"}})
async def APActorRequest(
async def ap_actor_request(
self,
request: "HTTPRequest",
data: Optional[dict],
@ -577,24 +577,24 @@ class HTTPAPGServer(web_resource.Resource):
ap_url: str,
signing_actor: Optional[str]
) -> dict:
inbox = self.apg.buildAPURL(TYPE_INBOX, ap_account)
shared_inbox = self.apg.buildAPURL(TYPE_SHARED_INBOX)
outbox = self.apg.buildAPURL(TYPE_OUTBOX, ap_account)
followers = self.apg.buildAPURL(TYPE_FOLLOWERS, ap_account)
following = self.apg.buildAPURL(TYPE_FOLLOWING, ap_account)
inbox = self.apg.build_apurl(TYPE_INBOX, ap_account)
shared_inbox = self.apg.build_apurl(TYPE_SHARED_INBOX)
outbox = self.apg.build_apurl(TYPE_OUTBOX, ap_account)
followers = self.apg.build_apurl(TYPE_FOLLOWERS, ap_account)
following = self.apg.build_apurl(TYPE_FOLLOWING, ap_account)
# we have to use AP account as preferredUsername because it is used to retrieve
# actor handle (see https://socialhub.activitypub.rocks/t/how-to-retrieve-user-server-tld-handle-from-actors-url/2196)
preferred_username = ap_account.split("@", 1)[0]
identity_data = await self.apg._i.getIdentity(self.apg.client, account_jid)
identity_data = await self.apg._i.get_identity(self.apg.client, account_jid)
if node and node.startswith(self.apg._events.namespace):
events = outbox
else:
events_account = await self.apg.getAPAccountFromJidAndNode(
events_account = await self.apg.get_ap_account_from_jid_and_node(
account_jid, self.apg._events.namespace
)
events = self.apg.buildAPURL(TYPE_OUTBOX, events_account)
events = self.apg.build_apurl(TYPE_OUTBOX, events_account)
actor_data = {
"@context": [
@ -636,7 +636,7 @@ class HTTPAPGServer(web_resource.Resource):
except KeyError:
log.error(f"incomplete avatar data: {identity_data!r}")
else:
avatar_url = self.apg.buildAPURL("avatar", filename)
avatar_url = self.apg.build_apurl("avatar", filename)
actor_data["icon"] = {
"type": "Image",
"url": avatar_url,
@ -645,14 +645,14 @@ class HTTPAPGServer(web_resource.Resource):
return actor_data
def getCanonicalURL(self, request: "HTTPRequest") -> str:
def get_canonical_url(self, request: "HTTPRequest") -> str:
return parse.urljoin(
f"https://{self.apg.public_url}",
request.path.decode().rstrip("/")
# we unescape "@" for the same reason as in [APActorRequest]
# we unescape "@" for the same reason as in [ap_actor_request]
).replace("%40", "@")
def queryData2RSMRequest(
def query_data_2_rsm_request(
self,
query_data: Dict[str, List[str]]
) -> rsm.RSMRequest:
@ -673,7 +673,7 @@ class HTTPAPGServer(web_resource.Resource):
return rsm.RSMRequest(**kwargs)
raise ValueError(f"Invalid query data: {query_data!r}")
async def APOutboxPageRequest(
async def ap_outbox_page_request(
self,
request: "HTTPRequest",
data: Optional[dict],
@ -690,18 +690,18 @@ class HTTPAPGServer(web_resource.Resource):
url_keys = sorted(set(query_data) & {"page", "index", "before", "after"})
query_data = {k: query_data[k] for k in url_keys}
try:
items, metadata = await self.apg._p.getItems(
items, metadata = await self.apg._p.get_items(
client=self.apg.client,
service=account_jid,
node=node,
rsm_request=self.queryData2RSMRequest(query_data),
rsm_request=self.query_data_2_rsm_request(query_data),
extra = {C.KEY_USE_CACHE: False}
)
except error.StanzaError as e:
log.warning(f"Can't get data from pubsub node {node} at {account_jid}: {e}")
return {}
base_url = self.getCanonicalURL(request)
base_url = self.get_canonical_url(request)
url = f"{base_url}?{parse.urlencode(query_data, True)}"
if node and node.startswith(self.apg._events.namespace):
ordered_items = [
@ -753,7 +753,7 @@ class HTTPAPGServer(web_resource.Resource):
return ret_data
async def APOutboxRequest(
async def ap_outbox_request(
self,
request: "HTTPRequest",
data: Optional[dict],
@ -769,7 +769,7 @@ class HTTPAPGServer(web_resource.Resource):
parsed_url = parse.urlparse(request.uri.decode())
query_data = parse.parse_qs(parsed_url.query)
if query_data:
return await self.APOutboxPageRequest(
return await self.ap_outbox_page_request(
request, data, account_jid, node, ap_account, ap_url, query_data
)
@ -779,7 +779,7 @@ class HTTPAPGServer(web_resource.Resource):
# The current workaround is to do a request as if RSM was available, and actually
# check its availability according to result.
try:
__, metadata = await self.apg._p.getItems(
__, metadata = await self.apg._p.get_items(
client=self.apg.client,
service=account_jid,
node=node,
@ -799,7 +799,7 @@ class HTTPAPGServer(web_resource.Resource):
)
items_count = 20
url = self.getCanonicalURL(request)
url = self.get_canonical_url(request)
url_first_page = f"{url}?{parse.urlencode({'page': 'first'})}"
url_last_page = f"{url}?{parse.urlencode({'page': 'last'})}"
return {
@ -811,7 +811,7 @@ class HTTPAPGServer(web_resource.Resource):
"last": url_last_page,
}
async def APInboxRequest(
async def ap_inbox_request(
self,
request: "HTTPRequest",
data: Optional[dict],
@ -824,26 +824,26 @@ class HTTPAPGServer(web_resource.Resource):
assert data is not None
if signing_actor is None:
raise exceptions.InternalError("signing_actor must be set for inbox requests")
await self.checkSigningActor(data, signing_actor)
await self.check_signing_actor(data, signing_actor)
activity_type = (data.get("type") or "").lower()
if not activity_type in ACTIVITY_TYPES_LOWER:
return self.responseCode(
return self.response_code(
request,
http.UNSUPPORTED_MEDIA_TYPE,
f"request is not an activity, ignoring"
)
if account_jid is None and activity_type not in ACTIVIY_NO_ACCOUNT_ALLOWED:
return self.responseCode(
return self.response_code(
request,
http.UNSUPPORTED_MEDIA_TYPE,
f"{activity_type.title()!r} activity must target an account"
)
try:
method = getattr(self, f"handle{activity_type.title()}Activity")
method = getattr(self, f"handle_{activity_type}_activity")
except AttributeError:
return self.responseCode(
return self.response_code(
request,
http.UNSUPPORTED_MEDIA_TYPE,
f"{activity_type.title()} activity is not yet supported"
@ -853,7 +853,7 @@ class HTTPAPGServer(web_resource.Resource):
request, data, account_jid, node, ap_account, ap_url, signing_actor
)
async def APFollowersRequest(
async def ap_followers_request(
self,
request: "HTTPRequest",
data: Optional[dict],
@ -866,20 +866,20 @@ class HTTPAPGServer(web_resource.Resource):
if node is None:
node = self.apg._m.namespace
client = self.apg.client
subscribers = await self.apg._pps.getPublicNodeSubscriptions(
subscribers = await self.apg._pps.get_public_node_subscriptions(
client, account_jid, node
)
followers = []
for subscriber in subscribers.keys():
if self.apg.isVirtualJID(subscriber):
if self.apg.is_virtual_jid(subscriber):
# the subscriber is an AP user subscribed with this gateway
ap_account = self.apg._e.unescape(subscriber.user)
else:
# regular XMPP user
ap_account = await self.apg.getAPAccountFromJidAndNode(subscriber, node)
ap_account = await self.apg.get_ap_account_from_jid_and_node(subscriber, node)
followers.append(ap_account)
url = self.getCanonicalURL(request)
url = self.get_canonical_url(request)
return {
"@context": ["https://www.w3.org/ns/activitystreams"],
"type": "OrderedCollection",
@ -892,7 +892,7 @@ class HTTPAPGServer(web_resource.Resource):
}
}
async def APFollowingRequest(
async def ap_following_request(
self,
request: "HTTPRequest",
data: Optional[dict],
@ -909,17 +909,17 @@ class HTTPAPGServer(web_resource.Resource):
following = []
for sub_dict in subscriptions:
service = jid.JID(sub_dict["service"])
if self.apg.isVirtualJID(service):
if self.apg.is_virtual_jid(service):
# the subscription is to an AP actor with this gateway
ap_account = self.apg._e.unescape(service.user)
else:
# regular XMPP user
ap_account = await self.apg.getAPAccountFromJidAndNode(
ap_account = await self.apg.get_ap_account_from_jid_and_node(
service, sub_dict["node"]
)
following.append(ap_account)
url = self.getCanonicalURL(request)
url = self.get_canonical_url(request)
return {
"@context": ["https://www.w3.org/ns/activitystreams"],
"type": "OrderedCollection",
@ -953,7 +953,7 @@ class HTTPAPGServer(web_resource.Resource):
to_log.append(f" headers:\n{headers}")
return to_log
async def APRequest(
async def ap_request(
self,
request: "HTTPRequest",
data: Optional[dict] = None,
@ -967,13 +967,13 @@ class HTTPAPGServer(web_resource.Resource):
f"https://{self.apg.public_url}",
path
)
request_type, extra_args = self.apg.parseAPURL(ap_url)
request_type, extra_args = self.apg.parse_apurl(ap_url)
if ((MEDIA_TYPE_AP not in (request.getHeader("accept") or "")
and request_type in self.apg.html_redirect)):
# this is not a AP request, and we have a redirections for it
kw = {}
if extra_args:
kw["jid"], kw["node"] = await self.apg.getJIDAndNode(extra_args[0])
kw["jid"], kw["node"] = await self.apg.get_jid_and_node(extra_args[0])
kw["jid_user"] = kw["jid"].user
if kw["node"] is None:
kw["node"] = self.apg._m.namespace
@ -1007,7 +1007,7 @@ class HTTPAPGServer(web_resource.Resource):
if len(extra_args) == 0:
if request_type != "shared_inbox":
raise exceptions.DataError(f"Invalid request type: {request_type!r}")
ret_data = await self.APInboxRequest(
ret_data = await self.ap_inbox_request(
request, data, None, None, None, ap_url, signing_actor
)
elif request_type == "avatar":
@ -1017,14 +1017,14 @@ class HTTPAPGServer(web_resource.Resource):
avatar_path = self.apg.host.common_cache.getPath(avatar_filename)
return static.File(str(avatar_path)).render(request)
elif request_type == "item":
ret_data = await self.apg.apGetLocalObject(ap_url)
ret_data = await self.apg.ap_get_local_object(ap_url)
if "@context" not in ret_data:
ret_data["@context"] = [NS_AP]
else:
if len(extra_args) > 1:
log.warning(f"unexpected extra arguments: {extra_args!r}")
ap_account = extra_args[0]
account_jid, node = await self.apg.getJIDAndNode(ap_account)
account_jid, node = await self.apg.get_jid_and_node(ap_account)
if request_type not in AP_REQUEST_TYPES.get(
request.method.decode().upper(), []
):
@ -1046,12 +1046,12 @@ class HTTPAPGServer(web_resource.Resource):
log.info("\n".join(to_log))
request.finish()
async def APPostRequest(self, request: "HTTPRequest") -> None:
async def ap_post_request(self, request: "HTTPRequest") -> None:
try:
data = json.load(request.content)
if not isinstance(data, dict):
log.warning(f"JSON data should be an object (uri={request.uri.decode()})")
self.responseCode(
self.response_code(
request,
http.BAD_REQUEST,
f"invalid body, was expecting a JSON object"
@ -1059,7 +1059,7 @@ class HTTPAPGServer(web_resource.Resource):
request.finish()
return
except (json.JSONDecodeError, ValueError) as e:
self.responseCode(
self.response_code(
request,
http.BAD_REQUEST,
f"invalid json in inbox request: {e}"
@ -1081,14 +1081,14 @@ class HTTPAPGServer(web_resource.Resource):
pass
try:
signing_actor = await self.checkSignature(request)
signing_actor = await self.check_signature(request)
except exceptions.EncryptionError as e:
if self.apg.verbose:
to_log = self._get_to_log(request)
to_log.append(f" body: {request.content.read()!r}")
request.content.seek(0)
log.info("\n".join(to_log))
self.responseCode(
self.response_code(
request,
http.FORBIDDEN,
f"invalid signature: {e}"
@ -1096,7 +1096,7 @@ class HTTPAPGServer(web_resource.Resource):
request.finish()
return
except Exception as e:
self.responseCode(
self.response_code(
request,
http.INTERNAL_SERVER_ERROR,
f"Can't check signature: {e}"
@ -1115,27 +1115,27 @@ class HTTPAPGServer(web_resource.Resource):
# default response code, may be changed, e.g. in case of exception
try:
return await self.APRequest(request, data, signing_actor)
return await self.ap_request(request, data, signing_actor)
except Exception as e:
self._onRequestError(failure.Failure(e), request)
self._on_request_error(failure.Failure(e), request)
async def checkSigningActor(self, data: dict, signing_actor: str) -> None:
async def check_signing_actor(self, data: dict, signing_actor: str) -> None:
"""That that signing actor correspond to actor declared in data
@param data: request payload
@param signing_actor: actor ID of the signing entity, as returned by
checkSignature
check_signature
@raise exceptions.NotFound: no actor found in data
@raise exceptions.EncryptionError: signing actor doesn't match actor in data
"""
actor = await self.apg.apGetSenderActor(data)
actor = await self.apg.ap_get_sender_actor(data)
if signing_actor != actor:
raise exceptions.EncryptionError(
f"signing actor ({signing_actor}) doesn't match actor in data ({actor})"
)
async def checkSignature(self, request: "HTTPRequest") -> str:
async def check_signature(self, request: "HTTPRequest") -> str:
"""Check and validate HTTP signature
@return: id of the signing actor
@ -1242,7 +1242,7 @@ class HTTPAPGServer(web_resource.Resource):
raise exceptions.EncryptionError(
"Only SHA-256 algorithm is currently supported for digest"
)
__, computed_digest = self.apg.getDigest(body)
__, computed_digest = self.apg.get_digest(body)
if given_digest != computed_digest:
raise exceptions.EncryptionError(
f"SHA-256 given and computed digest differ:\n"
@ -1275,7 +1275,7 @@ class HTTPAPGServer(web_resource.Resource):
raise exceptions.EncryptionError("Signature has expired")
try:
return await self.apg.checkSignature(
return await self.apg.check_signature(
sign_data["signature"],
key_id,
headers
@ -1287,7 +1287,7 @@ class HTTPAPGServer(web_resource.Resource):
"Using workaround for (request-target) encoding bug in signature, "
"see https://github.com/mastodon/mastodon/issues/18871"
)
return await self.apg.checkSignature(
return await self.apg.check_signature(
sign_data["signature"],
key_id,
headers
@ -1303,8 +1303,8 @@ class HTTPAPGServer(web_resource.Resource):
defer.ensureDeferred(self.webfinger(request))
return server.NOT_DONE_YET
elif path.startswith(self.apg.ap_path):
d = defer.ensureDeferred(self.APRequest(request))
d.addErrback(self._onRequestError, request)
d = defer.ensureDeferred(self.ap_request(request))
d.addErrback(self._on_request_error, request)
return server.NOT_DONE_YET
return web_resource.NoResource().render(request)
@ -1313,7 +1313,7 @@ class HTTPAPGServer(web_resource.Resource):
path = request.path.decode().lstrip("/")
if not path.startswith(self.apg.ap_path):
return web_resource.NoResource().render(request)
defer.ensureDeferred(self.APPostRequest(request))
defer.ensureDeferred(self.ap_post_request(request))
return server.NOT_DONE_YET

View file

@ -34,7 +34,7 @@ from sat.core.log import getLogger
from sat.core.constants import Const as C
from sat.tools import image
from sat.tools.utils import ensure_deferred
from sat.tools.web import downloadFile
from sat.tools.web import download_file
from sat.memory.sqla_mapping import PubsubSub, SubscriptionState
from .constants import (
@ -74,7 +74,7 @@ class APPubsubService(rsm.PubSubService):
"name": "Libervia ActivityPub Gateway",
}
async def getAPActorIdsAndInbox(
async def get_ap_actor_ids_and_inbox(
self,
requestor: jid.JID,
recipient: jid.JID,
@ -92,16 +92,16 @@ class APPubsubService(rsm.PubSubService):
"item-not-found",
text="No user part specified"
)
requestor_actor_id = self.apg.buildAPURL(TYPE_ACTOR, requestor.userhost())
requestor_actor_id = self.apg.build_apurl(TYPE_ACTOR, requestor.userhost())
recipient_account = self.apg._e.unescape(recipient.user)
recipient_actor_id = await self.apg.getAPActorIdFromAccount(recipient_account)
inbox = await self.apg.getAPInboxFromId(recipient_actor_id, use_shared=False)
recipient_actor_id = await self.apg.get_ap_actor_id_from_account(recipient_account)
inbox = await self.apg.get_ap_inbox_from_id(recipient_actor_id, use_shared=False)
return requestor_actor_id, recipient_actor_id, inbox
@ensure_deferred
async def publish(self, requestor, service, nodeIdentifier, items):
if self.apg.local_only and not self.apg.isLocal(requestor):
if self.apg.local_only and not self.apg.is_local(requestor):
raise error.StanzaError(
"forbidden",
"Only local users can publish on this gateway."
@ -118,19 +118,19 @@ class APPubsubService(rsm.PubSubService):
f"{ap_account!r} is not a valid ActivityPub actor account."
)
client = self.apg.client.getVirtualClient(requestor)
if self.apg._pa.isAttachmentNode(nodeIdentifier):
await self.apg.convertAndPostAttachments(
client = self.apg.client.get_virtual_client(requestor)
if self.apg._pa.is_attachment_node(nodeIdentifier):
await self.apg.convert_and_post_attachments(
client, ap_account, service, nodeIdentifier, items, publisher=requestor
)
else:
await self.apg.convertAndPostItems(
await self.apg.convert_and_post_items(
client, ap_account, service, nodeIdentifier, items
)
cached_node = await self.host.memory.storage.getPubsubNode(
cached_node = await self.host.memory.storage.get_pubsub_node(
client, service, nodeIdentifier, with_subscriptions=True, create=True
)
await self.host.memory.storage.cachePubsubItems(
await self.host.memory.storage.cache_pubsub_items(
client,
cached_node,
items
@ -144,27 +144,27 @@ class APPubsubService(rsm.PubSubService):
[(subscription.subscriber, None, items)]
)
async def apFollowing2Elt(self, ap_item: dict) -> domish.Element:
async def ap_following_2_elt(self, ap_item: dict) -> domish.Element:
"""Convert actor ID from following collection to XMPP item"""
actor_id = ap_item["id"]
actor_jid = await self.apg.getJIDFromId(actor_id)
subscription_elt = self.apg._pps.buildSubscriptionElt(
actor_jid = await self.apg.get_jid_from_id(actor_id)
subscription_elt = self.apg._pps.build_subscription_elt(
self.apg._m.namespace, actor_jid
)
item_elt = pubsub.Item(id=actor_id, payload=subscription_elt)
return item_elt
async def apFollower2Elt(self, ap_item: dict) -> domish.Element:
async def ap_follower_2_elt(self, ap_item: dict) -> domish.Element:
"""Convert actor ID from followers collection to XMPP item"""
actor_id = ap_item["id"]
actor_jid = await self.apg.getJIDFromId(actor_id)
subscriber_elt = self.apg._pps.buildSubscriberElt(actor_jid)
actor_jid = await self.apg.get_jid_from_id(actor_id)
subscriber_elt = self.apg._pps.build_subscriber_elt(actor_jid)
item_elt = pubsub.Item(id=actor_id, payload=subscriber_elt)
return item_elt
async def generateVCard(self, ap_account: str) -> domish.Element:
async def generate_v_card(self, ap_account: str) -> domish.Element:
"""Generate vCard4 (XEP-0292) item element from ap_account's metadata"""
actor_data = await self.apg.getAPActorDataFromAccount(ap_account)
actor_data = await self.apg.get_ap_actor_data_from_account(ap_account)
identity_data = {}
summary = actor_data.get("summary")
@ -181,13 +181,13 @@ class APPubsubService(rsm.PubSubService):
value = actor_data.get(field)
if value:
identity_data.setdefault("nicknames", []).append(value)
vcard_elt = self.apg._v.dict2VCard(identity_data)
vcard_elt = self.apg._v.dict_2_v_card(identity_data)
item_elt = domish.Element((pubsub.NS_PUBSUB, "item"))
item_elt.addChild(vcard_elt)
item_elt["id"] = self.apg._p.ID_SINGLETON
return item_elt
async def getAvatarData(
async def get_avatar_data(
self,
client: SatXMPPEntity,
ap_account: str
@ -197,9 +197,9 @@ class APPubsubService(rsm.PubSubService):
``cache_uid``, `path``` and ``media_type`` keys are always files
``base64`` key is only filled if the file was not already in cache
"""
actor_data = await self.apg.getAPActorDataFromAccount(ap_account)
actor_data = await self.apg.get_ap_actor_data_from_account(ap_account)
for icon in await self.apg.apGetList(actor_data, "icon"):
for icon in await self.apg.ap_get_list(actor_data, "icon"):
url = icon.get("url")
if icon["type"] != "Image" or not url:
continue
@ -221,19 +221,19 @@ class APPubsubService(rsm.PubSubService):
if cache_uid is None:
cache = None
else:
cache = self.apg.host.common_cache.getMetadata(cache_uid)
cache = self.apg.host.common_cache.get_metadata(cache_uid)
if cache is None:
with tempfile.TemporaryDirectory() as dir_name:
dest_path = Path(dir_name, filename)
await downloadFile(url, dest_path, max_size=MAX_AVATAR_SIZE)
await download_file(url, dest_path, max_size=MAX_AVATAR_SIZE)
avatar_data = {
"path": dest_path,
"filename": filename,
'media_type': image.guess_type(dest_path),
}
await self.apg._i.cacheAvatar(
await self.apg._i.cache_avatar(
self.apg.IMPORT_NAME,
avatar_data
)
@ -246,7 +246,7 @@ class APPubsubService(rsm.PubSubService):
return avatar_data
async def generateAvatarMetadata(
async def generate_avatar_metadata(
self,
client: SatXMPPEntity,
ap_account: str
@ -256,14 +256,14 @@ class APPubsubService(rsm.PubSubService):
@raise StanzaError("item-not-found"): no avatar is present in actor data (in
``icon`` field)
"""
avatar_data = await self.getAvatarData(client, ap_account)
return self.apg._a.buildItemMetadataElt(avatar_data)
avatar_data = await self.get_avatar_data(client, ap_account)
return self.apg._a.build_item_metadata_elt(avatar_data)
def _blockingB64EncodeAvatar(self, avatar_data: Dict[str, Any]) -> None:
def _blocking_b_6_4_encode_avatar(self, avatar_data: Dict[str, Any]) -> None:
with avatar_data["path"].open("rb") as f:
avatar_data["base64"] = b64encode(f.read()).decode()
async def generateAvatarData(
async def generate_avatar_data(
self,
client: SatXMPPEntity,
ap_account: str,
@ -274,9 +274,9 @@ class APPubsubService(rsm.PubSubService):
@raise StanzaError("item-not-found"): no avatar cached with requested ID
"""
if not itemIdentifiers:
avatar_data = await self.getAvatarData(client, ap_account)
avatar_data = await self.get_avatar_data(client, ap_account)
if "base64" not in avatar_data:
await threads.deferToThread(self._blockingB64EncodeAvatar, avatar_data)
await threads.deferToThread(self._blocking_b_6_4_encode_avatar, avatar_data)
else:
if len(itemIdentifiers) > 1:
# only a single item ID is supported
@ -284,16 +284,16 @@ class APPubsubService(rsm.PubSubService):
item_id = itemIdentifiers[0]
# just to be sure that that we don't have an empty string
assert item_id
cache_data = self.apg.host.common_cache.getMetadata(item_id)
cache_data = self.apg.host.common_cache.get_metadata(item_id)
if cache_data is None:
raise error.StanzaError("item-not-found")
avatar_data = {
"cache_uid": item_id,
"path": cache_data["path"]
}
await threads.deferToThread(self._blockingB64EncodeAvatar, avatar_data)
await threads.deferToThread(self._blocking_b_6_4_encode_avatar, avatar_data)
return self.apg._a.buildItemDataElt(avatar_data)
return self.apg._a.build_item_data_elt(avatar_data)
@ensure_deferred
async def items(
@ -320,31 +320,31 @@ class APPubsubService(rsm.PubSubService):
if node == self.apg._pps.subscriptions_node:
collection_name = "following"
parser = self.apFollowing2Elt
parser = self.ap_following_2_elt
kwargs["only_ids"] = True
use_cache = False
elif node.startswith(self.apg._pps.subscribers_node_prefix):
collection_name = "followers"
parser = self.apFollower2Elt
parser = self.ap_follower_2_elt
kwargs["only_ids"] = True
use_cache = False
elif node == self.apg._v.node:
# vCard4 request
item_elt = await self.generateVCard(ap_account)
item_elt = await self.generate_v_card(ap_account)
return [item_elt], None
elif node == self.apg._a.namespace_metadata:
item_elt = await self.generateAvatarMetadata(self.apg.client, ap_account)
item_elt = await self.generate_avatar_metadata(self.apg.client, ap_account)
return [item_elt], None
elif node == self.apg._a.namespace_data:
item_elt = await self.generateAvatarData(
item_elt = await self.generate_avatar_data(
self.apg.client, ap_account, itemIdentifiers
)
return [item_elt], None
elif self.apg._pa.isAttachmentNode(node):
elif self.apg._pa.is_attachment_node(node):
use_cache = True
# we check cache here because we emit an item-not-found error if the node is
# not in cache, as we are not dealing with real AP items
cached_node = await self.host.memory.storage.getPubsubNode(
cached_node = await self.host.memory.storage.get_pubsub_node(
client, service, node
)
if cached_node is None:
@ -365,14 +365,14 @@ class APPubsubService(rsm.PubSubService):
if use_cache:
if cached_node is None:
cached_node = await self.host.memory.storage.getPubsubNode(
cached_node = await self.host.memory.storage.get_pubsub_node(
client, service, node
)
# TODO: check if node is synchronised
if cached_node is not None:
# the node is cached, we return items from cache
log.debug(f"node {node!r} from {service} is in cache")
pubsub_items, metadata = await self.apg._c.getItemsFromCache(
pubsub_items, metadata = await self.apg._c.get_items_from_cache(
client, cached_node, maxItems, itemIdentifiers, rsm_request=rsm_req
)
try:
@ -384,7 +384,7 @@ class APPubsubService(rsm.PubSubService):
if itemIdentifiers:
items = []
for item_id in itemIdentifiers:
item_data = await self.apg.apGet(item_id)
item_data = await self.apg.ap_get(item_id)
item_elt = await parser(item_data)
items.append(item_elt)
return items, None
@ -419,11 +419,11 @@ class APPubsubService(rsm.PubSubService):
f"No cache found for node {node} at {service} (AP account {ap_account}), "
"using Collection Paging to RSM translation"
)
if self.apg._m.isCommentNode(node):
parent_item = self.apg._m.getParentItem(node)
if self.apg._m.is_comment_node(node):
parent_item = self.apg._m.get_parent_item(node)
try:
parent_data = await self.apg.apGet(parent_item)
collection = await self.apg.apGetObject(
parent_data = await self.apg.ap_get(parent_item)
collection = await self.apg.ap_get_object(
parent_data.get("object", {}),
"replies"
)
@ -433,8 +433,8 @@ class APPubsubService(rsm.PubSubService):
text=e
)
else:
actor_data = await self.apg.getAPActorDataFromAccount(ap_account)
collection = await self.apg.apGetObject(actor_data, collection_name)
actor_data = await self.apg.get_ap_actor_data_from_account(ap_account)
collection = await self.apg.ap_get_object(actor_data, collection_name)
if not collection:
raise error.StanzaError(
"item-not-found",
@ -442,7 +442,7 @@ class APPubsubService(rsm.PubSubService):
)
kwargs["parser"] = parser
return await self.apg.getAPItems(collection, **kwargs)
return await self.apg.get_ap_items(collection, **kwargs)
@ensure_deferred
async def retract(self, requestor, service, nodeIdentifier, itemIdentifiers):
@ -459,11 +459,11 @@ class APPubsubService(rsm.PubSubService):
sub_state = SubscriptionState.PENDING
else:
sub_state = SubscriptionState.SUBSCRIBED
node = await self.host.memory.storage.getPubsubNode(
node = await self.host.memory.storage.get_pubsub_node(
client, service, nodeIdentifier, with_subscriptions=True
)
if node is None:
node = await self.host.memory.storage.setPubsubNode(
node = await self.host.memory.storage.set_pubsub_node(
client,
service,
nodeIdentifier,
@ -510,13 +510,13 @@ class APPubsubService(rsm.PubSubService):
if nodeIdentifier in (self.apg._m.namespace, self.apg._events.namespace):
# if we subscribe to microblog or events node, we follow the corresponding
# account
req_actor_id, recip_actor_id, inbox = await self.getAPActorIdsAndInbox(
req_actor_id, recip_actor_id, inbox = await self.get_ap_actor_ids_and_inbox(
requestor, service
)
data = self.apg.create_activity("Follow", req_actor_id, recip_actor_id)
resp = await self.apg.signAndPost(inbox, req_actor_id, data)
resp = await self.apg.sign_and_post(inbox, req_actor_id, data)
if resp.code >= 300:
text = await resp.text()
raise error.StanzaError("service-unavailable", text=text)
@ -524,7 +524,7 @@ class APPubsubService(rsm.PubSubService):
@ensure_deferred
async def unsubscribe(self, requestor, service, nodeIdentifier, subscriber):
req_actor_id, recip_actor_id, inbox = await self.getAPActorIdsAndInbox(
req_actor_id, recip_actor_id, inbox = await self.get_ap_actor_ids_and_inbox(
requestor, service
)
data = self.apg.create_activity(
@ -537,7 +537,7 @@ class APPubsubService(rsm.PubSubService):
)
)
resp = await self.apg.signAndPost(inbox, req_actor_id, data)
resp = await self.apg.sign_and_post(inbox, req_actor_id, data)
if resp.code >= 300:
text = await resp.text()
raise error.StanzaError("service-unavailable", text=text)

View file

@ -113,7 +113,7 @@ class HTTPFileServer(resource.Resource):
return resource.ErrorPage(code, brief, details).render(request)
def getDispositionType(self, media_type, media_subtype):
def get_disposition_type(self, media_type, media_subtype):
if media_type in ('image', 'video'):
return 'inline'
elif media_type == 'application' and media_subtype == 'pdf':
@ -136,7 +136,7 @@ class HTTPFileServer(resource.Resource):
"Date, Content-Length, Content-Range")
return super().render(request)
def render_OPTIONS(self, request):
def render_options(self, request):
request.setResponseCode(http.OK)
return b""
@ -146,17 +146,17 @@ class HTTPFileServer(resource.Resource):
except exceptions.DataError:
return self.errorPage(request, http.NOT_FOUND)
defer.ensureDeferred(self.renderGet(request))
defer.ensureDeferred(self.render_get(request))
return server.NOT_DONE_YET
async def renderGet(self, request):
async def render_get(self, request):
try:
upload_id, filename = request.upload_data
except exceptions.DataError:
request.write(self.errorPage(request, http.FORBIDDEN))
request.finish()
return
found_files = await request.file_sharing.host.memory.getFiles(
found_files = await request.file_sharing.host.memory.get_files(
client=None, peer_jid=None, perms_to_check=None, public_id=upload_id)
if not found_files:
request.write(self.errorPage(request, http.NOT_FOUND))
@ -170,7 +170,7 @@ class HTTPFileServer(resource.Resource):
file_res = static.File(file_path)
file_res.type = f'{found_file["media_type"]}/{found_file["media_subtype"]}'
file_res.encoding = file_res.contentEncodings.get(Path(found_file['name']).suffix)
disp_type = self.getDispositionType(
disp_type = self.get_disposition_type(
found_file['media_type'], found_file['media_subtype'])
# the URL is percent encoded, and not all browsers/tools unquote the file name,
# thus we add a content disposition header
@ -190,10 +190,10 @@ class HTTPFileServer(resource.Resource):
request.finish()
def render_PUT(self, request):
defer.ensureDeferred(self.renderPut(request))
defer.ensureDeferred(self.render_put(request))
return server.NOT_DONE_YET
async def renderPut(self, request):
async def render_put(self, request):
try:
client, upload_request = request.upload_request_data
upload_id, filename = request.upload_data
@ -228,7 +228,7 @@ class HTTPFileServer(resource.Resource):
"path": path
}
await request.file_sharing.registerReceivedFile(
await request.file_sharing.register_received_file(
client, upload_request.from_, file_data, tmp_file_path,
public_id=public_id,
)
@ -273,7 +273,7 @@ class FileSharingRequest(server.Request):
def file_tmp_dir(self):
return self.channel.site.file_tmp_dir
def refuseRequest(self):
def refuse_request(self):
if self.content is not None:
self.content.close()
self.content = open(os.devnull, 'w+b')
@ -287,16 +287,16 @@ class FileSharingRequest(server.Request):
upload_id, filename = self.upload_data
except exceptions.DataError as e:
log.warning(f"Invalid PUT request, we stop here: {e}")
return self.refuseRequest()
return self.refuse_request()
try:
client, upload_request, timer = self.file_sharing.expected_uploads.pop(upload_id)
except KeyError:
log.warning(f"unknown (expired?) upload ID received for a PUT: {upload_id!r}")
return self.refuseRequest()
return self.refuse_request()
if not timer.active:
log.warning(f"upload id {upload_id!r} used for a PUT, but it is expired")
return self.refuseRequest()
return self.refuse_request()
timer.cancel()
@ -305,7 +305,7 @@ class FileSharingRequest(server.Request):
f"invalid filename for PUT (upload id: {upload_id!r}, URL: {self.channel._path.decode()}). Original "
f"{upload_request.filename!r} doesn't match {filename!r}"
)
return self.refuseRequest()
return self.refuse_request()
self.upload_request_data = (client, upload_request)
@ -355,24 +355,24 @@ class FileSharing:
self._h = self.host.plugins["XEP-0300"]
self._t = self.host.plugins["XEP-0264"]
self._hu = self.host.plugins["XEP-0363"]
self._hu.registerHandler(self._on_http_upload)
self.host.trigger.add("FILE_getDestDir", self._getDestDirTrigger)
self._hu.register_handler(self._on_http_upload)
self.host.trigger.add("FILE_getDestDir", self._get_dest_dir_trigger)
self.host.trigger.add(
"XEP-0234_fileSendingRequest", self._fileSendingRequestTrigger, priority=1000
"XEP-0234_fileSendingRequest", self._file_sending_request_trigger, priority=1000
)
self.host.trigger.add("XEP-0234_buildFileElement", self._addFileMetadataElts)
self.host.trigger.add("XEP-0234_parseFileElement", self._getFileMetadataElts)
self.host.trigger.add("XEP-0329_compGetFilesFromNode", self._addFileMetadata)
self.host.trigger.add("XEP-0234_buildFileElement", self._add_file_metadata_elts)
self.host.trigger.add("XEP-0234_parseFileElement", self._get_file_metadata_elts)
self.host.trigger.add("XEP-0329_compGetFilesFromNode", self._add_file_metadata)
self.host.trigger.add(
"XEP-0329_compGetFilesFromNode_build_directory",
self._addDirectoryMetadataElts)
self._add_directory_metadata_elts)
self.host.trigger.add(
"XEP-0329_parseResult_directory",
self._getDirectoryMetadataElts)
self._get_directory_metadata_elts)
self.files_path = self.host.get_local_path(None, C.FILES_DIR)
self.http_port = int(self.host.memory.getConfig(
self.http_port = int(self.host.memory.config_get(
'component file-sharing', 'http_upload_port', 8888))
connection_type = self.host.memory.getConfig(
connection_type = self.host.memory.config_get(
'component file-sharing', 'http_upload_connection_type', 'https')
if connection_type not in ('http', 'https'):
raise exceptions.ConfigError(
@ -383,51 +383,51 @@ class FileSharing:
if connection_type == 'http':
reactor.listenTCP(self.http_port, self.server)
else:
options = tls.getOptionsFromConfig(
options = tls.get_options_from_config(
self.host.memory.config, "component file-sharing")
tls.TLSOptionsCheck(options)
context_factory = tls.getTLSContextFactory(options)
tls.tls_options_check(options)
context_factory = tls.get_tls_context_factory(options)
reactor.listenSSL(self.http_port, self.server, context_factory)
def getHandler(self, client):
def get_handler(self, client):
return Comments_handler(self)
def profileConnecting(self, client):
def profile_connecting(self, client):
# we activate HTTP upload
client.enabled_features.add("XEP-0363")
self.init()
public_base_url = self.host.memory.getConfig(
public_base_url = self.host.memory.config_get(
'component file-sharing', 'http_upload_public_facing_url')
if public_base_url is None:
client._file_sharing_base_url = f"https://{client.host}:{self.http_port}"
else:
client._file_sharing_base_url = public_base_url
path = client.file_tmp_dir = os.path.join(
self.host.memory.getConfig("", "local_dir"),
self.host.memory.config_get("", "local_dir"),
C.FILES_TMP_DIR,
regex.pathEscape(client.profile),
regex.path_escape(client.profile),
)
if not os.path.exists(path):
os.makedirs(path)
def getQuota(self, client, entity):
def get_quota(self, client, entity):
"""Return maximum size allowed for all files for entity"""
quotas = self.host.memory.getConfig("component file-sharing", "quotas_json", {})
if self.host.memory.isAdminJID(entity):
quotas = self.host.memory.config_get("component file-sharing", "quotas_json", {})
if self.host.memory.is_admin_jid(entity):
quota = quotas.get("admins")
else:
try:
quota = quotas["jids"][entity.userhost()]
except KeyError:
quota = quotas.get("users")
return None if quota is None else utils.parseSize(quota)
return None if quota is None else utils.parse_size(quota)
async def generate_thumbnails(self, extra: dict, image_path: Path):
thumbnails = extra.setdefault(C.KEY_THUMBNAILS, [])
for max_thumb_size in self._t.SIZES:
try:
thumb_size, thumb_id = await self._t.generateThumbnail(
thumb_size, thumb_id = await self._t.generate_thumbnail(
image_path,
max_thumb_size,
#  we keep thumbnails for 6 months
@ -438,7 +438,7 @@ class FileSharing:
break
thumbnails.append({"id": thumb_id, "size": thumb_size})
async def registerReceivedFile(
async def register_received_file(
self, client, peer_jid, file_data, file_path, public_id=None, extra=None):
"""Post file reception tasks
@ -460,9 +460,9 @@ class FileSharing:
log.debug(_("Reusing already generated hash"))
file_hash = file_data["hash_hasher"].hexdigest()
else:
hasher = self._h.getHasher(HASH_ALGO)
hasher = self._h.get_hasher(HASH_ALGO)
with file_path.open('rb') as f:
file_hash = await self._h.calculateHash(f, hasher)
file_hash = await self._h.calculate_hash(f, hasher)
final_path = self.files_path/file_hash
if final_path.is_file():
@ -493,7 +493,7 @@ class FileSharing:
else:
await self.generate_thumbnails(extra, thumb_path)
await self.host.memory.setFile(
await self.host.memory.set_file(
client,
name=name,
version="",
@ -508,7 +508,7 @@ class FileSharing:
extra=extra,
)
async def _getDestDirTrigger(
async def _get_dest_dir_trigger(
self, client, peer_jid, transfer_data, file_data, stream_object
):
"""This trigger accept file sending request, and store file locally"""
@ -522,17 +522,17 @@ class FileSharing:
assert C.KEY_PROGRESS_ID in file_data
filename = file_data["name"]
assert filename and not "/" in filename
quota = self.getQuota(client, peer_jid)
quota = self.get_quota(client, peer_jid)
if quota is not None:
used_space = await self.host.memory.fileGetUsedSpace(client, peer_jid)
used_space = await self.host.memory.file_get_used_space(client, peer_jid)
if (used_space + file_data["size"]) > quota:
raise error.StanzaError(
"not-acceptable",
text=OVER_QUOTA_TXT.format(
quota=utils.getHumanSize(quota),
used_space=utils.getHumanSize(used_space),
file_size=utils.getHumanSize(file_data['size'])
quota=utils.get_human_size(quota),
used_space=utils.get_human_size(used_space),
file_size=utils.get_human_size(file_data['size'])
)
)
file_tmp_dir = self.host.get_local_path(
@ -543,26 +543,26 @@ class FileSharing:
transfer_data["finished_d"].addCallback(
lambda __: defer.ensureDeferred(
self.registerReceivedFile(client, peer_jid, file_data, file_tmp_path)
self.register_received_file(client, peer_jid, file_data, file_tmp_path)
)
)
self._f.openFileWrite(
self._f.open_file_write(
client, file_tmp_path, transfer_data, file_data, stream_object
)
return False, True
async def _retrieveFiles(
async def _retrieve_files(
self, client, session, content_data, content_name, file_data, file_elt
):
"""This method retrieve a file on request, and send if after checking permissions"""
peer_jid = session["peer_jid"]
if session['local_jid'].user:
owner = client.getOwnerFromJid(session['local_jid'])
owner = client.get_owner_from_jid(session['local_jid'])
else:
owner = peer_jid
try:
found_files = await self.host.memory.getFiles(
found_files = await self.host.memory.get_files(
client,
peer_jid=peer_jid,
name=file_data.get("name"),
@ -595,7 +595,7 @@ class FileSharing:
type_=found_file['type']))
file_hash = found_file["file_hash"]
file_path = self.files_path / file_hash
file_data["hash_hasher"] = hasher = self._h.getHasher(found_file["hash_algo"])
file_data["hash_hasher"] = hasher = self._h.get_hasher(found_file["hash_algo"])
size = file_data["size"] = found_file["size"]
file_data["file_hash"] = file_hash
file_data["hash_algo"] = found_file["hash_algo"]
@ -608,13 +608,13 @@ class FileSharing:
self.host,
client,
file_path,
uid=self._jf.getProgressId(session, content_name),
uid=self._jf.get_progress_id(session, content_name),
size=size,
data_cb=lambda data: hasher.update(data),
)
return True
def _fileSendingRequestTrigger(
def _file_sending_request_trigger(
self, client, session, content_data, content_name, file_data, file_elt
):
if not client.is_component:
@ -622,7 +622,7 @@ class FileSharing:
else:
return (
False,
defer.ensureDeferred(self._retrieveFiles(
defer.ensureDeferred(self._retrieve_files(
client, session, content_data, content_name, file_data, file_elt
)),
)
@ -642,19 +642,19 @@ class FileSharing:
if request.from_.host not in client._file_sharing_allowed_hosts:
raise error.StanzaError("forbidden")
quota = self.getQuota(client, request.from_)
quota = self.get_quota(client, request.from_)
if quota is not None:
used_space = await self.host.memory.fileGetUsedSpace(client, request.from_)
used_space = await self.host.memory.file_get_used_space(client, request.from_)
if (used_space + request.size) > quota:
raise error.StanzaError(
"not-acceptable",
text=OVER_QUOTA_TXT.format(
quota=utils.getHumanSize(quota),
used_space=utils.getHumanSize(used_space),
file_size=utils.getHumanSize(request.size)
quota=utils.get_human_size(quota),
used_space=utils.get_human_size(used_space),
file_size=utils.get_human_size(request.size)
),
appCondition = self._hu.getFileTooLargeElt(max(quota - used_space, 0))
appCondition = self._hu.get_file_too_large_elt(max(quota - used_space, 0))
)
upload_id = shortuuid.ShortUUID().random(length=30)
@ -671,7 +671,7 @@ class FileSharing:
## metadata triggers ##
def _addFileMetadataElts(self, client, file_elt, extra_args):
def _add_file_metadata_elts(self, client, file_elt, extra_args):
# affiliation
affiliation = extra_args.get('affiliation')
if affiliation is not None:
@ -693,7 +693,7 @@ class FileSharing:
comment_elt["count"] = str(count)
return True
def _getFileMetadataElts(self, client, file_elt, file_data):
def _get_file_metadata_elts(self, client, file_elt, file_data):
# affiliation
try:
affiliation_elt = next(file_elt.elements(NS_FS_AFFILIATION, "affiliation"))
@ -712,17 +712,17 @@ class FileSharing:
file_data["comments_count"] = comments_elt["count"]
return True
def _addFileMetadata(
def _add_file_metadata(
self, client, iq_elt, iq_result_elt, owner, node_path, files_data):
for file_data in files_data:
file_data["comments_url"] = uri.buildXMPPUri(
file_data["comments_url"] = uri.build_xmpp_uri(
"pubsub",
path=client.jid.full(),
node=COMMENT_NODE_PREFIX + file_data["id"],
)
return True
def _addDirectoryMetadataElts(
def _add_directory_metadata_elts(
self, client, file_data, directory_elt, owner, node_path):
affiliation = file_data.get('affiliation')
if affiliation is not None:
@ -731,7 +731,7 @@ class FileSharing:
content=affiliation
)
def _getDirectoryMetadataElts(
def _get_directory_metadata_elts(
self, client, elt, file_data):
try:
affiliation_elt = next(elt.elements(NS_FS_AFFILIATION, "affiliation"))
@ -754,7 +754,7 @@ class Comments_handler(pubsub.PubSubService):
"name": "files commenting service",
}
def _getFileId(self, nodeIdentifier):
def _get_file_id(self, nodeIdentifier):
if not nodeIdentifier.startswith(COMMENT_NODE_PREFIX):
raise error.StanzaError("item-not-found")
file_id = nodeIdentifier[len(COMMENT_NODE_PREFIX) :]
@ -762,10 +762,10 @@ class Comments_handler(pubsub.PubSubService):
raise error.StanzaError("item-not-found")
return file_id
async def getFileData(self, requestor, nodeIdentifier):
file_id = self._getFileId(nodeIdentifier)
async def get_file_data(self, requestor, nodeIdentifier):
file_id = self._get_file_id(nodeIdentifier)
try:
files = await self.host.memory.getFiles(self.parent, requestor, file_id)
files = await self.host.memory.get_files(self.parent, requestor, file_id)
except (exceptions.NotFound, exceptions.PermissionError):
# we don't differenciate between NotFound and PermissionError
# to avoid leaking information on existing files
@ -776,7 +776,7 @@ class Comments_handler(pubsub.PubSubService):
raise error.InternalError("there should be only one file")
return files[0]
def commentsUpdate(self, extra, new_comments, peer_jid):
def comments_update(self, extra, new_comments, peer_jid):
"""update comments (replace or insert new_comments)
@param extra(dict): extra data to update
@ -807,7 +807,7 @@ class Comments_handler(pubsub.PubSubService):
current_comments.extend(new_comments)
def commentsDelete(self, extra, comments):
def comments_delete(self, extra, comments):
try:
comments_dict = extra["comments"]
except KeyError:
@ -818,7 +818,7 @@ class Comments_handler(pubsub.PubSubService):
except ValueError:
continue
def _getFrom(self, item_elt):
def _get_from(self, item_elt):
"""retrieve publisher of an item
@param item_elt(domish.element): <item> element
@ -832,22 +832,22 @@ class Comments_handler(pubsub.PubSubService):
@ensure_deferred
async def publish(self, requestor, service, nodeIdentifier, items):
#  we retrieve file a first time to check authorisations
file_data = await self.getFileData(requestor, nodeIdentifier)
file_data = await self.get_file_data(requestor, nodeIdentifier)
file_id = file_data["id"]
comments = [(item["id"], self._getFrom(item), item.toXml()) for item in items]
comments = [(item["id"], self._get_from(item), item.toXml()) for item in items]
if requestor.userhostJID() == file_data["owner"]:
peer_jid = None
else:
peer_jid = requestor.userhost()
update_cb = partial(self.commentsUpdate, new_comments=comments, peer_jid=peer_jid)
update_cb = partial(self.comments_update, new_comments=comments, peer_jid=peer_jid)
try:
await self.host.memory.fileUpdate(file_id, "extra", update_cb)
await self.host.memory.file_update(file_id, "extra", update_cb)
except exceptions.PermissionError:
raise error.StanzaError("not-authorized")
@ensure_deferred
async def items(self, requestor, service, nodeIdentifier, maxItems, itemIdentifiers):
file_data = await self.getFileData(requestor, nodeIdentifier)
file_data = await self.get_file_data(requestor, nodeIdentifier)
comments = file_data["extra"].get("comments", [])
if itemIdentifiers:
return [generic.parseXml(c[2]) for c in comments if c[0] in itemIdentifiers]
@ -856,7 +856,7 @@ class Comments_handler(pubsub.PubSubService):
@ensure_deferred
async def retract(self, requestor, service, nodeIdentifier, itemIdentifiers):
file_data = await self.getFileData(requestor, nodeIdentifier)
file_data = await self.get_file_data(requestor, nodeIdentifier)
file_id = file_data["id"]
try:
comments = file_data["extra"]["comments"]
@ -880,5 +880,5 @@ class Comments_handler(pubsub.PubSubService):
if not all([c[1] == requestor.userhost() for c in to_remove]):
raise error.StanzaError("not-authorized")
remove_cb = partial(self.commentsDelete, comments=to_remove)
await self.host.memory.fileUpdate(file_id, "extra", remove_cb)
remove_cb = partial(self.comments_delete, comments=to_remove)
await self.host.memory.file_update(file_id, "extra", remove_cb)

View file

@ -74,8 +74,8 @@ class FileSharingManagement(object):
self._c = host.plugins["XEP-0050"]
self._t = host.plugins["XEP-0264"]
self.files_path = host.get_local_path(None, C.FILES_DIR)
host.bridge.addMethod(
"fileSharingDelete",
host.bridge.add_method(
"file_sharing_delete",
".plugin",
in_sign="ssss",
out_sign="",
@ -83,30 +83,30 @@ class FileSharingManagement(object):
async_=True,
)
def profileConnected(self, client):
self._c.addAdHocCommand(
client, self._onChangeFile, "Change Permissions of File(s)",
def profile_connected(self, client):
self._c.add_ad_hoc_command(
client, self._on_change_file, "Change Permissions of File(s)",
node=NS_FILE_MANAGEMENT_PERM,
allowed_magics=C.ENTITY_ALL,
)
self._c.addAdHocCommand(
client, self._onDeleteFile, "Delete File(s)",
self._c.add_ad_hoc_command(
client, self._on_delete_file, "Delete File(s)",
node=NS_FILE_MANAGEMENT_DELETE,
allowed_magics=C.ENTITY_ALL,
)
self._c.addAdHocCommand(
client, self._onGenThumbnails, "Generate Thumbnails",
self._c.add_ad_hoc_command(
client, self._on_gen_thumbnails, "Generate Thumbnails",
node=NS_FILE_MANAGEMENT_THUMB,
allowed_magics=C.ENTITY_ALL,
)
self._c.addAdHocCommand(
client, self._onQuota, "Get Quota",
self._c.add_ad_hoc_command(
client, self._on_quota, "Get Quota",
node=NS_FILE_MANAGEMENT_QUOTA,
allowed_magics=C.ENTITY_ALL,
)
def _delete(self, service_jid_s, path, namespace, profile):
client = self.host.getClient(profile)
client = self.host.get_client(profile)
service_jid = jid.JID(service_jid_s) if service_jid_s else None
return defer.ensureDeferred(self._c.sequence(
client,
@ -127,7 +127,7 @@ class FileSharingManagement(object):
note = (self._c.NOTE.ERROR, reason)
return payload, status, None, note
def _getRootArgs(self):
def _get_root_args(self):
"""Create the form to select the file to use
@return (tuple): arguments to use in defer.returnValue
@ -149,7 +149,7 @@ class FileSharingManagement(object):
payload = form.toElement()
return payload, status, None, None
async def _getFileData(self, client, session_data, command_form):
async def _get_file_data(self, client, session_data, command_form):
"""Retrieve field requested in root form
"found_file" will also be set in session_data
@ -162,10 +162,10 @@ class FileSharingManagement(object):
path = fields['path'].value.strip()
namespace = fields['namespace'].value or None
except KeyError:
self._c.adHocError(self._c.ERROR.BAD_PAYLOAD)
self._c.ad_hoc_error(self._c.ERROR.BAD_PAYLOAD)
if not path:
self._c.adHocError(self._c.ERROR.BAD_PAYLOAD)
self._c.ad_hoc_error(self._c.ERROR.BAD_PAYLOAD)
requestor = session_data['requestor']
requestor_bare = requestor.userhostJID()
@ -176,7 +176,7 @@ class FileSharingManagement(object):
# this must be managed
try:
found_files = await self.host.memory.getFiles(
found_files = await self.host.memory.get_files(
client, requestor_bare, path=parent_path, name=basename,
namespace=namespace)
found_file = found_files[0]
@ -194,7 +194,7 @@ class FileSharingManagement(object):
session_data['namespace'] = namespace
return found_file
def _updateReadPermission(self, access, allowed_jids):
def _update_read_permission(self, access, allowed_jids):
if not allowed_jids:
if C.ACCESS_PERM_READ in access:
del access[C.ACCESS_PERM_READ]
@ -208,27 +208,27 @@ class FileSharingManagement(object):
"jids": [j.full() for j in allowed_jids]
}
async def _updateDir(self, client, requestor, namespace, file_data, allowed_jids):
async def _update_dir(self, client, requestor, namespace, file_data, allowed_jids):
"""Recursively update permission of a directory and all subdirectories
@param file_data(dict): metadata of the file
@param allowed_jids(list[jid.JID]): list of entities allowed to read the file
"""
assert file_data['type'] == C.FILE_TYPE_DIRECTORY
files_data = await self.host.memory.getFiles(
files_data = await self.host.memory.get_files(
client, requestor, parent=file_data['id'], namespace=namespace)
for file_data in files_data:
if not file_data['access'].get(C.ACCESS_PERM_READ, {}):
log.debug("setting {perm} read permission for {name}".format(
perm=allowed_jids, name=file_data['name']))
await self.host.memory.fileUpdate(
await self.host.memory.file_update(
file_data['id'], 'access',
partial(self._updateReadPermission, allowed_jids=allowed_jids))
partial(self._update_read_permission, allowed_jids=allowed_jids))
if file_data['type'] == C.FILE_TYPE_DIRECTORY:
await self._updateDir(client, requestor, namespace, file_data, 'PUBLIC')
await self._update_dir(client, requestor, namespace, file_data, 'PUBLIC')
async def _onChangeFile(self, client, command_elt, session_data, action, node):
async def _on_change_file(self, client, command_elt, session_data, action, node):
try:
x_elt = next(command_elt.elements(data_form.NS_X_DATA, "x"))
command_form = data_form.Form.fromElement(x_elt)
@ -241,12 +241,12 @@ class FileSharingManagement(object):
if command_form is None or len(command_form.fields) == 0:
# root request
return self._getRootArgs()
return self._get_root_args()
elif found_file is None:
# file selected, we retrieve it and ask for permissions
try:
found_file = await self._getFileData(client, session_data, command_form)
found_file = await self._get_file_data(client, session_data, command_form)
except WorkflowError as e:
return e.err_args
@ -288,7 +288,7 @@ class FileSharingManagement(object):
try:
read_allowed = command_form.fields['read_allowed']
except KeyError:
self._c.adHocError(self._c.ERROR.BAD_PAYLOAD)
self._c.ad_hoc_error(self._c.ERROR.BAD_PAYLOAD)
if read_allowed.value == 'PUBLIC':
allowed_jids = 'PUBLIC'
@ -301,26 +301,26 @@ class FileSharingManagement(object):
except RuntimeError as e:
log.warning(_("Can't use read_allowed values: {reason}").format(
reason=e))
self._c.adHocError(self._c.ERROR.BAD_PAYLOAD)
self._c.ad_hoc_error(self._c.ERROR.BAD_PAYLOAD)
if found_file['type'] == C.FILE_TYPE_FILE:
await self.host.memory.fileUpdate(
await self.host.memory.file_update(
found_file['id'], 'access',
partial(self._updateReadPermission, allowed_jids=allowed_jids))
partial(self._update_read_permission, allowed_jids=allowed_jids))
else:
try:
recursive = command_form.fields['recursive']
except KeyError:
self._c.adHocError(self._c.ERROR.BAD_PAYLOAD)
await self.host.memory.fileUpdate(
self._c.ad_hoc_error(self._c.ERROR.BAD_PAYLOAD)
await self.host.memory.file_update(
found_file['id'], 'access',
partial(self._updateReadPermission, allowed_jids=allowed_jids))
partial(self._update_read_permission, allowed_jids=allowed_jids))
if recursive:
# we set all file under the directory as public (if they haven't
# already a permission set), so allowed entities of root directory
# can read them.
namespace = session_data['namespace']
await self._updateDir(
await self._update_dir(
client, requestor_bare, namespace, found_file, 'PUBLIC')
# job done, we can end the session
@ -329,7 +329,7 @@ class FileSharingManagement(object):
note = (self._c.NOTE.INFO, _("management session done"))
return (payload, status, None, note)
async def _onDeleteFile(self, client, command_elt, session_data, action, node):
async def _on_delete_file(self, client, command_elt, session_data, action, node):
try:
x_elt = next(command_elt.elements(data_form.NS_X_DATA, "x"))
command_form = data_form.Form.fromElement(x_elt)
@ -342,12 +342,12 @@ class FileSharingManagement(object):
if command_form is None or len(command_form.fields) == 0:
# root request
return self._getRootArgs()
return self._get_root_args()
elif found_file is None:
# file selected, we need confirmation before actually deleting
try:
found_file = await self._getFileData(client, session_data, command_form)
found_file = await self._get_file_data(client, session_data, command_form)
except WorkflowError as e:
return e.err_args
if found_file['type'] == C.FILE_TYPE_DIRECTORY:
@ -373,31 +373,31 @@ class FileSharingManagement(object):
try:
confirmed = C.bool(command_form.fields['confirm'].value)
except KeyError:
self._c.adHocError(self._c.ERROR.BAD_PAYLOAD)
self._c.ad_hoc_error(self._c.ERROR.BAD_PAYLOAD)
if not confirmed:
note = None
else:
recursive = found_file['type'] == C.FILE_TYPE_DIRECTORY
await self.host.memory.fileDelete(
await self.host.memory.file_delete(
client, requestor_bare, found_file['id'], recursive)
note = (self._c.NOTE.INFO, _("file deleted"))
status = self._c.STATUS.COMPLETED
payload = None
return (payload, status, None, note)
def _updateThumbs(self, extra, thumbnails):
def _update_thumbs(self, extra, thumbnails):
extra[C.KEY_THUMBNAILS] = thumbnails
async def _genThumbs(self, client, requestor, namespace, file_data):
async def _gen_thumbs(self, client, requestor, namespace, file_data):
"""Recursively generate thumbnails
@param file_data(dict): metadata of the file
"""
if file_data['type'] == C.FILE_TYPE_DIRECTORY:
sub_files_data = await self.host.memory.getFiles(
sub_files_data = await self.host.memory.get_files(
client, requestor, parent=file_data['id'], namespace=namespace)
for sub_file_data in sub_files_data:
await self._genThumbs(client, requestor, namespace, sub_file_data)
await self._gen_thumbs(client, requestor, namespace, sub_file_data)
elif file_data['type'] == C.FILE_TYPE_FILE:
media_type = file_data['media_type']
@ -407,7 +407,7 @@ class FileSharingManagement(object):
for max_thumb_size in self._t.SIZES:
try:
thumb_size, thumb_id = await self._t.generateThumbnail(
thumb_size, thumb_id = await self._t.generate_thumbnail(
file_path,
max_thumb_size,
#  we keep thumbnails for 6 months
@ -419,9 +419,9 @@ class FileSharingManagement(object):
break
thumbnails.append({"id": thumb_id, "size": thumb_size})
await self.host.memory.fileUpdate(
await self.host.memory.file_update(
file_data['id'], 'extra',
partial(self._updateThumbs, thumbnails=thumbnails))
partial(self._update_thumbs, thumbnails=thumbnails))
log.info("thumbnails for [{file_name}] generated"
.format(file_name=file_data['name']))
@ -429,7 +429,7 @@ class FileSharingManagement(object):
else:
log.warning("unmanaged file type: {type_}".format(type_=file_data['type']))
async def _onGenThumbnails(self, client, command_elt, session_data, action, node):
async def _on_gen_thumbnails(self, client, command_elt, session_data, action, node):
try:
x_elt = next(command_elt.elements(data_form.NS_X_DATA, "x"))
command_form = data_form.Form.fromElement(x_elt)
@ -441,17 +441,17 @@ class FileSharingManagement(object):
if command_form is None or len(command_form.fields) == 0:
# root request
return self._getRootArgs()
return self._get_root_args()
elif found_file is None:
# file selected, we retrieve it and ask for permissions
try:
found_file = await self._getFileData(client, session_data, command_form)
found_file = await self._get_file_data(client, session_data, command_form)
except WorkflowError as e:
return e.err_args
log.info("Generating thumbnails as requested")
await self._genThumbs(client, requestor, found_file['namespace'], found_file)
await self._gen_thumbs(client, requestor, found_file['namespace'], found_file)
# job done, we can end the session
status = self._c.STATUS.COMPLETED
@ -459,11 +459,11 @@ class FileSharingManagement(object):
note = (self._c.NOTE.INFO, _("thumbnails generated"))
return (payload, status, None, note)
async def _onQuota(self, client, command_elt, session_data, action, node):
async def _on_quota(self, client, command_elt, session_data, action, node):
requestor = session_data['requestor']
quota = self.host.plugins["file_sharing"].getQuota(client, requestor)
quota = self.host.plugins["file_sharing"].get_quota(client, requestor)
try:
size_used = await self.host.memory.fileGetUsedSpace(client, requestor)
size_used = await self.host.memory.file_get_used_space(client, requestor)
except exceptions.PermissionError:
raise WorkflowError(self._err(_("forbidden")))
status = self._c.STATUS.COMPLETED
@ -473,10 +473,10 @@ class FileSharingManagement(object):
note = (
self._c.NOTE.INFO,
_("You are currently using {size_used} on {size_quota}").format(
size_used = utils.getHumanSize(size_used),
size_used = utils.get_human_size(size_used),
size_quota = (
_("unlimited quota") if quota is None
else utils.getHumanSize(quota)
else utils.get_human_size(quota)
)
)
)

View file

@ -45,11 +45,11 @@ class Manhole(object):
def __init__(self, host):
self.host = host
port = int(host.memory.getConfig(None, "manhole_debug_dangerous_port_int", 0))
port = int(host.memory.config_get(None, "manhole_debug_dangerous_port_int", 0))
if port:
self.startManhole(port)
self.start_manhole(port)
def startManhole(self, port):
def start_manhole(self, port):
log.warning(_("/!\\ Manhole debug server activated, be sure to not use it in "
"production, this is dangerous /!\\"))
log.info(_("You can connect to manhole server using telnet on port {port}")

View file

@ -72,7 +72,7 @@ class ExportCommandProtocol(protocol.ProcessProtocol):
def write(self, message):
self.transport.write(message.encode("utf-8"))
def boolOption(self, key):
def bool_option(self, key):
""" Get boolean value from options
@param key: name of the option
@return: True if key exists and set to "true" (case insensitive),
@ -92,13 +92,13 @@ class CommandExport(object):
log.info(_("Plugin command export initialization"))
self.host = host
self.spawned = {} # key = entity
host.trigger.add("messageReceived", self.messageReceivedTrigger, priority=10000)
host.bridge.addMethod(
"exportCommand",
host.trigger.add("messageReceived", self.message_received_trigger, priority=10000)
host.bridge.add_method(
"command_export",
".plugin",
in_sign="sasasa{ss}s",
out_sign="",
method=self._exportCommand,
method=self._export_command,
)
def removeProcess(self, entity, process):
@ -113,7 +113,7 @@ class CommandExport(object):
except ValueError:
pass
def messageReceivedTrigger(self, client, message_elt, post_treat):
def message_received_trigger(self, client, message_elt, post_treat):
""" Check if source is linked and repeat message, else do nothing """
from_jid = jid.JID(message_elt["from"])
spawned_key = (from_jid.userhostJID(), client.profile)
@ -131,15 +131,15 @@ class CommandExport(object):
exclusive = False
for process in processes_set:
process.write(mess_data)
_continue &= process.boolOption("continue")
exclusive |= process.boolOption("exclusive")
_continue &= process.bool_option("continue")
exclusive |= process.bool_option("exclusive")
if exclusive:
raise trigger.SkipOtherTriggers
return _continue
return True
def _exportCommand(self, command, args, targets, options, profile_key):
def _export_command(self, command, args, targets, options, profile_key):
""" Export a commands to authorised targets
@param command: full path of the command to execute
@param args: list of arguments, with command name as first one
@ -150,7 +150,7 @@ class CommandExport(object):
- pty: if set, launch in a pseudo terminal
- continue: continue normal messageReceived handling
"""
client = self.host.getClient(profile_key)
client = self.host.get_client(profile_key)
for target in targets:
try:
_jid = jid.JID(target)
@ -163,5 +163,5 @@ class CommandExport(object):
process_prot = ExportCommandProtocol(self, client, _jid, options)
self.spawned.setdefault((_jid, client.profile), set()).add(process_prot)
reactor.spawnProcess(
process_prot, command, args, usePTY=process_prot.boolOption("pty")
process_prot, command, args, usePTY=process_prot.bool_option("pty")
)

View file

@ -61,10 +61,10 @@ class Invitation(object):
# map from namespace of the invitation to callback handling it
self._ns_cb = {}
def getHandler(self, client):
def get_handler(self, client):
return PubsubInvitationHandler(self)
def registerNamespace(self, namespace, callback):
def register_namespace(self, namespace, callback):
"""Register a callback for a namespace
@param namespace(unicode): namespace handled
@ -95,7 +95,7 @@ class Invitation(object):
.format(namespace=namespace, callback=self._ns_cb[namespace]))
self._ns_cb[namespace] = callback
def _generateBaseInvitation(self, client, invitee_jid, name, extra):
def _generate_base_invitation(self, client, invitee_jid, name, extra):
"""Generate common mess_data end invitation_elt
@param invitee_jid(jid.JID): entitee to send invitation to
@ -113,8 +113,8 @@ class Invitation(object):
"subject": {},
"extra": {},
}
client.generateMessageXML(mess_data)
self._h.addHintElements(mess_data["xml"], [self._h.HINT_STORE])
client.generate_message_xml(mess_data)
self._h.add_hint_elements(mess_data["xml"], [self._h.HINT_STORE])
invitation_elt = mess_data["xml"].addElement("invitation", NS_INVITATION)
if name is not None:
invitation_elt["name"] = name
@ -128,7 +128,7 @@ class Invitation(object):
invitation_elt['thumb_url'] = thumb_url
return mess_data, invitation_elt
def sendPubsubInvitation(
def send_pubsub_invitation(
self,
client: SatXMPPEntity,
invitee_jid: jid.JID,
@ -145,12 +145,12 @@ class Invitation(object):
@param node: pubsub node
@param item_id: pubsub id
None when the invitation is for a whole node
@param name: see [_generateBaseInvitation]
@param extra: see [_generateBaseInvitation]
@param name: see [_generate_base_invitation]
@param extra: see [_generate_base_invitation]
"""
if extra is None:
extra = {}
mess_data, invitation_elt = self._generateBaseInvitation(
mess_data, invitation_elt = self._generate_base_invitation(
client, invitee_jid, name, extra)
pubsub_elt = invitation_elt.addElement("pubsub")
pubsub_elt["service"] = service.full()
@ -172,7 +172,7 @@ class Invitation(object):
invitation_elt.addChild(extra.pop("element"))
client.send(mess_data["xml"])
async def sendFileSharingInvitation(
async def send_file_sharing_invitation(
self, client, invitee_jid, service, repos_type=None, namespace=None, path=None,
name=None, extra=None
):
@ -185,13 +185,13 @@ class Invitation(object):
- "photos": photos album
@param namespace(unicode, None): namespace of the shared repository
@param path(unicode, None): path of the shared repository
@param name(unicode, None): see [_generateBaseInvitation]
@param extra(dict, None): see [_generateBaseInvitation]
@param name(unicode, None): see [_generate_base_invitation]
@param extra(dict, None): see [_generate_base_invitation]
"""
if extra is None:
extra = {}
li_plg = self.host.plugins["LIST_INTEREST"]
li_plg.normaliseFileSharingService(client, service)
li_plg.normalise_file_sharing_service(client, service)
# FIXME: not the best place to adapt permission, but it's necessary to check them
# for UX
@ -205,7 +205,7 @@ class Invitation(object):
if "thumb_url" not in extra:
# we have no thumbnail, we check in our own list of interests if there is one
try:
item_id = li_plg.getFileSharingId(service, namespace, path)
item_id = li_plg.get_file_sharing_id(service, namespace, path)
own_interest = await li_plg.get(client, item_id)
except exceptions.NotFound:
log.debug(
@ -218,7 +218,7 @@ class Invitation(object):
except KeyError:
pass
mess_data, invitation_elt = self._generateBaseInvitation(
mess_data, invitation_elt = self._generate_base_invitation(
client, invitee_jid, name, extra)
file_sharing_elt = invitation_elt.addElement("file_sharing")
file_sharing_elt["service"] = service.full()
@ -235,7 +235,7 @@ class Invitation(object):
file_sharing_elt["path"] = path
client.send(mess_data["xml"])
async def _parsePubsubElt(self, client, pubsub_elt):
async def _parse_pubsub_elt(self, client, pubsub_elt):
try:
service = jid.JID(pubsub_elt["service"])
node = pubsub_elt["node"]
@ -246,7 +246,7 @@ class Invitation(object):
if item_id is not None:
try:
items, metadata = await self._p.getItems(
items, metadata = await self._p.get_items(
client, service, node, item_ids=[item_id]
)
except Exception as e:
@ -276,7 +276,7 @@ class Invitation(object):
return namespace, args
async def _parseFileSharingElt(self, client, file_sharing_elt):
async def _parse_file_sharing_elt(self, client, file_sharing_elt):
try:
service = jid.JID(file_sharing_elt["service"])
except (RuntimeError, KeyError):
@ -286,10 +286,10 @@ class Invitation(object):
sharing_ns = file_sharing_elt.getAttribute("namespace")
path = file_sharing_elt.getAttribute("path")
args = [service, repos_type, sharing_ns, path]
ns_fis = self.host.getNamespace("fis")
ns_fis = self.host.get_namespace("fis")
return ns_fis, args
async def onInvitation(self, message_elt, client):
async def on_invitation(self, message_elt, client):
log.debug("invitation received [{profile}]".format(profile=client.profile))
invitation_elt = message_elt.invitation
@ -303,9 +303,9 @@ class Invitation(object):
log.warning("unexpected element: {xml}".format(xml=elt.toXml()))
continue
if elt.name == "pubsub":
method = self._parsePubsubElt
method = self._parse_pubsub_elt
elif elt.name == "file_sharing":
method = self._parseFileSharingElt
method = self._parse_file_sharing_elt
else:
log.warning("not implemented invitation element: {xml}".format(
xml = elt.toXml()))
@ -324,7 +324,7 @@ class Invitation(object):
'No handler for namespace "{namespace}", invitation ignored')
.format(namespace=namespace))
else:
await utils.asDeferred(cb, client, namespace, name, extra, *args)
await utils.as_deferred(cb, client, namespace, name, extra, *args)
@implementer(iwokkel.IDisco)
@ -337,7 +337,7 @@ class PubsubInvitationHandler(XMPPHandler):
self.xmlstream.addObserver(
INVITATION,
lambda message_elt: defer.ensureDeferred(
self.plugin_parent.onInvitation(message_elt, client=self.parent)
self.plugin_parent.on_invitation(message_elt, client=self.parent)
),
)

View file

@ -45,32 +45,32 @@ class FileSharingInvitation:
def __init__(self, host):
log.info(_("File Sharing Invitation plugin initialization"))
self.host = host
ns_fis = host.getNamespace("fis")
host.plugins["INVITATION"].registerNamespace(ns_fis, self.onInvitation)
host.bridge.addMethod(
"FISInvite",
ns_fis = host.get_namespace("fis")
host.plugins["INVITATION"].register_namespace(ns_fis, self.on_invitation)
host.bridge.add_method(
"fis_invite",
".plugin",
in_sign="ssssssss",
out_sign="",
method=self._sendFileSharingInvitation,
method=self._send_file_sharing_invitation,
async_=True
)
def _sendFileSharingInvitation(
def _send_file_sharing_invitation(
self, invitee_jid_s, service_s, repos_type=None, namespace=None, path=None,
name=None, extra_s='', profile_key=C.PROF_KEY_NONE):
client = self.host.getClient(profile_key)
client = self.host.get_client(profile_key)
invitee_jid = jid.JID(invitee_jid_s)
service = jid.JID(service_s)
extra = data_format.deserialise(extra_s)
return defer.ensureDeferred(
self.host.plugins["INVITATION"].sendFileSharingInvitation(
self.host.plugins["INVITATION"].send_file_sharing_invitation(
client, invitee_jid, service, repos_type=repos_type or None,
namespace=namespace or None, path=path or None, name=name or None,
extra=extra)
)
def onInvitation(
def on_invitation(
self,
client: SatXMPPEntity,
namespace: str,
@ -97,7 +97,7 @@ class FileSharingInvitation:
path=path)
)
return defer.ensureDeferred(
self.host.plugins['LIST_INTEREST'].registerFileSharing(
self.host.plugins['LIST_INTEREST'].register_file_sharing(
client, service, repos_type, sharing_ns, path, name, extra
)
)

View file

@ -51,12 +51,12 @@ class PubsubInvitation:
self._p = host.plugins["XEP-0060"]
# namespace to handler map
self._ns_handler = {}
host.bridge.addMethod(
"psInvite",
host.bridge.add_method(
"ps_invite",
".plugin",
in_sign="sssssss",
out_sign="",
method=self._sendPubsubInvitation,
method=self._send_pubsub_invitation,
async_=True
)
@ -66,12 +66,12 @@ class PubsubInvitation:
handler
) -> None:
self._ns_handler[namespace] = handler
self.host.plugins["INVITATION"].registerNamespace(namespace, self.onInvitation)
self.host.plugins["INVITATION"].register_namespace(namespace, self.on_invitation)
def _sendPubsubInvitation(
def _send_pubsub_invitation(
self, invitee_jid_s, service_s, node, item_id=None,
name=None, extra_s='', profile_key=C.PROF_KEY_NONE):
client = self.host.getClient(profile_key)
client = self.host.get_client(profile_key)
invitee_jid = jid.JID(invitee_jid_s)
service = jid.JID(service_s)
extra = data_format.deserialise(extra_s)
@ -104,13 +104,13 @@ class PubsubInvitation:
if namespace:
try:
handler = self._ns_handler[namespace]
preflight = handler.invitePreflight
preflight = handler.invite_preflight
except KeyError:
pass
except AttributeError:
log.debug(f"no invitePreflight method found for {namespace!r}")
log.debug(f"no invite_preflight method found for {namespace!r}")
else:
await utils.asDeferred(
await utils.as_deferred(
preflight,
client, invitee_jid, service, node, item_id, name, extra
)
@ -118,11 +118,11 @@ class PubsubInvitation:
item_id = extra.pop("default_item_id", None)
# we authorize our invitee to see the nodes of interest
await self._p.setNodeAffiliations(client, service, node, {invitee_jid: "member"})
await self._p.set_node_affiliations(client, service, node, {invitee_jid: "member"})
log.debug(f"affiliation set on {service}'s {node!r} node")
# now we send the invitation
self.host.plugins["INVITATION"].sendPubsubInvitation(
self.host.plugins["INVITATION"].send_pubsub_invitation(
client,
invitee_jid,
service,
@ -132,7 +132,7 @@ class PubsubInvitation:
extra=extra
)
async def onInvitation(
async def on_invitation(
self,
client: SatXMPPEntity,
namespace: str,
@ -153,7 +153,7 @@ class PubsubInvitation:
except AttributeError:
log.debug(f"no on_invitation_preflight method found for {namespace!r}")
else:
await utils.asDeferred(
await utils.as_deferred(
preflight,
client, namespace, name, extra, service, node, item_id, item_elt
)
@ -164,6 +164,6 @@ class PubsubInvitation:
if not name:
name = extra.pop("name", "")
return await self.host.plugins['LIST_INTEREST'].registerPubsub(
return await self.host.plugins['LIST_INTEREST'].register_pubsub(
client, namespace, service, node, item_id, creator,
name, element, extra)

View file

@ -60,7 +60,7 @@ class StreamProtocol(protocol.Protocol):
def __init__(self):
self.pause = False
def setPause(self, paused):
def set_pause(self, paused):
# in Python 2.x, Twisted classes are old style
# so we can use property and setter
if paused:
@ -78,10 +78,10 @@ class StreamProtocol(protocol.Protocol):
def connectionMade(self):
if self.factory.client_conn is not None:
self.transport.loseConnection()
self.factory.setClientConn(self)
self.factory.set_client_conn(self)
def dataReceived(self, data):
self.factory.writeToConsumer(data)
self.factory.write_to_consumer(data)
def sendData(self, data):
self.transport.write(data)
@ -92,9 +92,9 @@ class StreamProtocol(protocol.Protocol):
return
if reason.type == error.ConnectionDone:
self.factory.streamFinished()
self.factory.stream_finished()
else:
self.factory.streamFailed(reason)
self.factory.stream_failed(reason)
@interface.implementer(stream.IStreamProducer)
@ -109,15 +109,15 @@ class StreamFactory(protocol.Factory):
def __init__(self):
self.client_conn = None
def setClientConn(self, stream_protocol):
def set_client_conn(self, stream_protocol):
# in Python 2.x, Twisted classes are old style
# so we can use property and setter
assert self.client_conn is None
self.client_conn = stream_protocol
if self.consumer is None:
self.client_conn.setPause(True)
self.client_conn.set_pause(True)
def startStream(self, consumer):
def start_stream(self, consumer):
if self.consumer is not None:
raise exceptions.InternalError(
_("stream can't be used with multiple consumers")
@ -127,17 +127,17 @@ class StreamFactory(protocol.Factory):
consumer.registerProducer(self, True)
self.deferred = defer.Deferred()
if self.client_conn is not None:
self.client_conn.setPause(False)
self.client_conn.set_pause(False)
return self.deferred
def streamFinished(self):
def stream_finished(self):
self.client_conn = None
if self.consumer:
self.consumer.unregisterProducer()
self.port_listening.stopListening()
self.deferred.callback(None)
def streamFailed(self, failure_):
def stream_failed(self, failure_):
self.client_conn = None
if self.consumer:
self.consumer.unregisterProducer()
@ -146,7 +146,7 @@ class StreamFactory(protocol.Factory):
elif self.producer:
self.producer.stopProducing()
def stopStream(self):
def stop_stream(self):
if self.client_conn is not None:
self.client_conn.disconnect()
@ -154,10 +154,10 @@ class StreamFactory(protocol.Factory):
self.producer = producer
def pauseProducing(self):
self.client_conn.setPause(True)
self.client_conn.set_pause(True)
def resumeProducing(self):
self.client_conn.setPause(False)
self.client_conn.set_pause(False)
def stopProducing(self):
if self.client_conn:
@ -169,7 +169,7 @@ class StreamFactory(protocol.Factory):
except AttributeError:
log.warning(_("No client connected, can't send data"))
def writeToConsumer(self, data):
def write_to_consumer(self, data):
self.consumer.write(data)
@ -180,23 +180,23 @@ class JingleStream(object):
log.info(_("Plugin Stream initialization"))
self.host = host
self._j = host.plugins["XEP-0166"] # shortcut to access jingle
self._j.registerApplication(NS_STREAM, self)
host.bridge.addMethod(
"streamOut",
self._j.register_application(NS_STREAM, self)
host.bridge.add_method(
"stream_out",
".plugin",
in_sign="ss",
out_sign="s",
method=self._streamOut,
method=self._stream_out,
async_=True,
)
# jingle callbacks
def _streamOut(self, to_jid_s, profile_key):
client = self.host.getClient(profile_key)
return defer.ensureDeferred(self.streamOut(client, jid.JID(to_jid_s)))
def _stream_out(self, to_jid_s, profile_key):
client = self.host.get_client(profile_key)
return defer.ensureDeferred(self.stream_out(client, jid.JID(to_jid_s)))
async def streamOut(self, client, to_jid):
async def stream_out(self, client, to_jid):
"""send a stream
@param peer_jid(jid.JID): recipient
@ -230,7 +230,7 @@ class JingleStream(object):
))
return str(port)
def jingleSessionInit(self, client, session, content_name, stream_object):
def jingle_session_init(self, client, session, content_name, stream_object):
content_data = session["contents"][content_name]
application_data = content_data["application_data"]
assert "stream_object" not in application_data
@ -239,7 +239,7 @@ class JingleStream(object):
return desc_elt
@defer.inlineCallbacks
def jingleRequestConfirmation(self, client, action, session, content_name, desc_elt):
def jingle_request_confirmation(self, client, action, session, content_name, desc_elt):
"""This method request confirmation for a jingle session"""
content_data = session["contents"][content_name]
if content_data["senders"] not in (
@ -249,7 +249,7 @@ class JingleStream(object):
log.warning("Bad sender, assuming initiator")
content_data["senders"] = self._j.ROLE_INITIATOR
confirm_data = yield xml_tools.deferDialog(
confirm_data = yield xml_tools.defer_dialog(
self.host,
_(CONFIRM).format(peer=session["peer_jid"].full()),
_(CONFIRM_TITLE),
@ -274,10 +274,10 @@ class JingleStream(object):
content_data["stream_object"] = factory
finished_d = content_data["finished_d"] = defer.Deferred()
args = [client, session, content_name, content_data]
finished_d.addCallbacks(self._finishedCb, self._finishedEb, args, None, args)
finished_d.addCallbacks(self._finished_cb, self._finished_eb, args, None, args)
defer.returnValue(True)
def jingleHandler(self, client, action, session, content_name, desc_elt):
def jingle_handler(self, client, action, session, content_name, desc_elt):
content_data = session["contents"][content_name]
application_data = content_data["application_data"]
if action in (self._j.A_ACCEPTED_ACK, self._j.A_SESSION_INITIATE):
@ -287,19 +287,19 @@ class JingleStream(object):
content_data["stream_object"] = application_data["stream_object"]
finished_d = content_data["finished_d"] = defer.Deferred()
args = [client, session, content_name, content_data]
finished_d.addCallbacks(self._finishedCb, self._finishedEb, args, None, args)
finished_d.addCallbacks(self._finished_cb, self._finished_eb, args, None, args)
else:
log.warning("FIXME: unmanaged action {}".format(action))
return desc_elt
def _finishedCb(self, __, client, session, content_name, content_data):
def _finished_cb(self, __, client, session, content_name, content_data):
log.info("Pipe transfer completed")
self._j.contentTerminate(client, session, content_name)
content_data["stream_object"].stopStream()
self._j.content_terminate(client, session, content_name)
content_data["stream_object"].stop_stream()
def _finishedEb(self, failure, client, session, content_name, content_data):
def _finished_eb(self, failure, client, session, content_name, content_data):
log.warning("Error while streaming pipe: {}".format(failure))
self._j.contentTerminate(
self._j.content_terminate(
client, session, content_name, reason=self._j.REASON_FAILED_TRANSPORT
)
content_data["stream_object"].stopStream()
content_data["stream_object"].stop_stream()

View file

@ -65,9 +65,9 @@ class LangDetect(object):
def __init__(self, host):
log.info(_("Language detection plugin initialization"))
self.host = host
host.memory.updateParams(PARAMS)
host.trigger.add("messageReceived", self.messageReceivedTrigger)
host.trigger.add("sendMessage", self.MessageSendTrigger)
host.memory.update_params(PARAMS)
host.trigger.add("messageReceived", self.message_received_trigger)
host.trigger.add("sendMessage", self.message_send_trigger)
def add_language(self, mess_data):
message = mess_data["message"]
@ -78,18 +78,18 @@ class LangDetect(object):
mess_data["message"] = {lang: msg}
return mess_data
def messageReceivedTrigger(self, client, message_elt, post_treat):
def message_received_trigger(self, client, message_elt, post_treat):
""" Check if source is linked and repeat message, else do nothing """
lang_detect = self.host.memory.getParamA(
lang_detect = self.host.memory.param_get_a(
NAME, CATEGORY, profile_key=client.profile
)
if lang_detect:
post_treat.addCallback(self.add_language)
return True
def MessageSendTrigger(self, client, data, pre_xml_treatments, post_xml_treatments):
lang_detect = self.host.memory.getParamA(
def message_send_trigger(self, client, data, pre_xml_treatments, post_xml_treatments):
lang_detect = self.host.memory.param_get_a(
NAME, CATEGORY, profile_key=client.profile
)
if lang_detect:

View file

@ -56,32 +56,32 @@ class ListInterest(object):
log.info(_("List of Interest plugin initialization"))
self.host = host
self._p = self.host.plugins["XEP-0060"]
host.bridge.addMethod(
"interestsList",
host.bridge.add_method(
"interests_list",
".plugin",
in_sign="ssss",
out_sign="aa{ss}",
method=self._listInterests,
method=self._list_interests,
async_=True,
)
host.bridge.addMethod(
"interestsRegisterFileSharing",
host.bridge.add_method(
"interests_file_sharing_register",
".plugin",
in_sign="sssssss",
out_sign="",
method=self._registerFileSharing,
method=self._register_file_sharing,
async_=True,
)
host.bridge.addMethod(
"interestRetract",
host.bridge.add_method(
"interest_retract",
".plugin",
in_sign="sss",
out_sign="",
method=self._interestRetract,
method=self._interest_retract,
async_=True,
)
def getHandler(self, client):
def get_handler(self, client):
return ListInterestHandler(self)
@defer.inlineCallbacks
@ -99,7 +99,7 @@ class ListInterest(object):
if e.condition == "conflict":
log.debug(_("requested node already exists"))
async def registerPubsub(self, client, namespace, service, node, item_id=None,
async def register_pubsub(self, client, namespace, service, node, item_id=None,
creator=False, name=None, element=None, extra=None):
"""Register an interesting element in personal list
@ -142,26 +142,26 @@ class ListInterest(object):
}
if item_id:
uri_kwargs['id'] = item_id
interest_uri = uri.buildXMPPUri("pubsub", **uri_kwargs)
interest_uri = uri.build_xmpp_uri("pubsub", **uri_kwargs)
# we use URI of the interest as item id to avoid duplicates
item_elt = pubsub.Item(interest_uri, payload=interest_elt)
await self._p.publish(
client, client.jid.userhostJID(), NS_LIST_INTEREST, items=[item_elt]
)
def _registerFileSharing(
def _register_file_sharing(
self, service, repos_type, namespace, path, name, extra_raw,
profile
):
client = self.host.getClient(profile)
client = self.host.get_client(profile)
extra = data_format.deserialise(extra_raw)
return defer.ensureDeferred(self.registerFileSharing(
return defer.ensureDeferred(self.register_file_sharing(
client, jid.JID(service), repos_type or None, namespace or None, path or None,
name or None, extra
))
def normaliseFileSharingService(self, client, service):
def normalise_file_sharing_service(self, client, service):
# FIXME: Q&D fix as the bare file sharing service JID will lead to user own
# repository, which thus would not be the same for the host and the guest.
# By specifying the user part, we for the use of the host repository.
@ -169,10 +169,10 @@ class ListInterest(object):
if service.user is None:
service.user = self.host.plugins['XEP-0106'].escape(client.jid.user)
def getFileSharingId(self, service, namespace, path):
def get_file_sharing_id(self, service, namespace, path):
return f"{service}_{namespace or ''}_{path or ''}"
async def registerFileSharing(
async def register_file_sharing(
self, client, service, repos_type=None, namespace=None, path=None, name=None,
extra=None):
"""Register an interesting file repository in personal list
@ -182,15 +182,15 @@ class ListInterest(object):
@param namespace(unicode, None): namespace of the repository
@param path(unicode, None): path of the repository
@param name(unicode, None): name of the repository
@param extra(dict, None): same as [registerPubsub]
@param extra(dict, None): same as [register_pubsub]
"""
if extra is None:
extra = {}
self.normaliseFileSharingService(client, service)
self.normalise_file_sharing_service(client, service)
await self.createNode(client)
item_id = self.getFileSharingId(service, namespace, path)
item_id = self.get_file_sharing_id(service, namespace, path)
interest_elt = domish.Element((NS_LIST_INTEREST, "interest"))
interest_elt["namespace"] = self.host.getNamespace("fis")
interest_elt["namespace"] = self.host.get_namespace("fis")
if name is not None:
interest_elt['name'] = name
thumb_url = extra.get('thumb_url')
@ -210,7 +210,7 @@ class ListInterest(object):
client, client.jid.userhostJID(), NS_LIST_INTEREST, items=[item_elt]
)
def _listInterestsSerialise(self, interests_data):
def _list_interests_serialise(self, interests_data):
interests = []
for item_elt in interests_data[0]:
interest_data = {"id": item_elt['id']}
@ -252,16 +252,16 @@ class ListInterest(object):
return interests
def _listInterests(self, service, node, namespace, profile):
def _list_interests(self, service, node, namespace, profile):
service = jid.JID(service) if service else None
node = node or None
namespace = namespace or None
client = self.host.getClient(profile)
d = defer.ensureDeferred(self.listInterests(client, service, node, namespace))
d.addCallback(self._listInterestsSerialise)
client = self.host.get_client(profile)
d = defer.ensureDeferred(self.list_interests(client, service, node, namespace))
d.addCallback(self._list_interests_serialise)
return d
async def listInterests(self, client, service=None, node=None, namespace=None):
async def list_interests(self, client, service=None, node=None, namespace=None):
"""Retrieve list of interests
@param service(jid.JID, None): service to use
@ -270,12 +270,12 @@ class ListInterest(object):
None to use default node
@param namespace(unicode, None): filter interests of this namespace
None to retrieve all interests
@return: same as [XEP_0060.getItems]
@return: same as [XEP_0060.get_items]
"""
# TODO: if a MAM filter were available, it would improve performances
if not node:
node = NS_LIST_INTEREST
items, metadata = await self._p.getItems(client, service, node)
items, metadata = await self._p.get_items(client, service, node)
if namespace is not None:
filtered_items = []
for item in items:
@ -291,17 +291,17 @@ class ListInterest(object):
return (items, metadata)
def _interestRetract(self, service_s, item_id, profile_key):
d = self._p._retractItem(
def _interest_retract(self, service_s, item_id, profile_key):
d = self._p._retract_item(
service_s, NS_LIST_INTEREST, item_id, True, profile_key)
d.addCallback(lambda __: None)
return d
async def get(self, client: SatXMPPEntity, item_id: str) -> dict:
"""Retrieve a specific interest in profile's list"""
items_data = await self._p.getItems(client, None, NS_LIST_INTEREST, item_ids=[item_id])
items_data = await self._p.get_items(client, None, NS_LIST_INTEREST, item_ids=[item_id])
try:
return self._listInterestsSerialise(items_data)[0]
return self._list_interests_serialise(items_data)[0]
except IndexError:
raise exceptions.NotFound

View file

@ -48,21 +48,21 @@ class Exp_Parrot(object):
# XXX: This plugin can be potentially dangerous if we don't trust entities linked
# this is specially true if we have other triggers.
# sendMessageTrigger avoid other triggers execution, it's deactivated to allow
# send_message_trigger avoid other triggers execution, it's deactivated to allow
# /unparrot command in text commands plugin.
# FIXME: potentially unsecure, specially with e2e encryption
def __init__(self, host):
log.info(_("Plugin Parrot initialization"))
self.host = host
host.trigger.add("messageReceived", self.messageReceivedTrigger, priority=100)
# host.trigger.add("sendMessage", self.sendMessageTrigger, priority=100)
host.trigger.add("messageReceived", self.message_received_trigger, priority=100)
# host.trigger.add("sendMessage", self.send_message_trigger, priority=100)
try:
self.host.plugins[C.TEXT_CMDS].registerTextCommands(self)
self.host.plugins[C.TEXT_CMDS].register_text_commands(self)
except KeyError:
log.info(_("Text commands not available"))
# def sendMessageTrigger(self, client, mess_data, treatments):
# def send_message_trigger(self, client, mess_data, treatments):
# """ Deactivate other triggers if recipient is in parrot links """
# try:
# _links = client.parrot_links
@ -73,7 +73,7 @@ class Exp_Parrot(object):
# log.debug("Parrot link detected, skipping other triggers")
# raise trigger.SkipOtherTriggers
def messageReceivedTrigger(self, client, message_elt, post_treat):
def message_received_trigger(self, client, message_elt, post_treat):
""" Check if source is linked and repeat message, else do nothing """
# TODO: many things are not repeated (subject, thread, etc)
from_jid = message_elt["from"]
@ -92,13 +92,13 @@ class Exp_Parrot(object):
lang = e.getAttribute("lang") or ""
try:
entity_type = self.host.memory.getEntityData(
entity_type = self.host.memory.entity_data_get(
client, from_jid, [C.ENTITY_TYPE])[C.ENTITY_TYPE]
except (UnknownEntityError, KeyError):
entity_type = "contact"
if entity_type == C.ENTITY_TYPE_MUC:
src_txt = from_jid.resource
if src_txt == self.host.plugins["XEP-0045"].getRoomNick(
if src_txt == self.host.plugins["XEP-0045"].get_room_nick(
client, from_jid.userhostJID()
):
# we won't repeat our own messages
@ -115,7 +115,7 @@ class Exp_Parrot(object):
return True
def addParrot(self, client, source_jid, dest_jid):
def add_parrot(self, client, source_jid, dest_jid):
"""Add a parrot link from one entity to another one
@param source_jid: entity from who messages will be repeated
@ -132,7 +132,7 @@ class Exp_Parrot(object):
% (source_jid.userhost(), str(dest_jid))
)
def removeParrot(self, client, source_jid):
def remove_parrot(self, client, source_jid):
"""Remove parrot link
@param source_jid: this entity will no more be repeated
@ -152,17 +152,17 @@ class Exp_Parrot(object):
if not link_left_jid.user or not link_left_jid.host:
raise jid.InvalidFormat
except (RuntimeError, jid.InvalidFormat, AttributeError):
txt_cmd.feedBack(
txt_cmd.feed_back(
client, "Can't activate Parrot mode for invalid jid", mess_data
)
return False
link_right_jid = mess_data["to"]
self.addParrot(client, link_left_jid, link_right_jid)
self.addParrot(client, link_right_jid, link_left_jid)
self.add_parrot(client, link_left_jid, link_right_jid)
self.add_parrot(client, link_right_jid, link_left_jid)
txt_cmd.feedBack(
txt_cmd.feed_back(
client,
"Parrot mode activated for {}".format(str(link_left_jid)),
mess_data,
@ -180,17 +180,17 @@ class Exp_Parrot(object):
if not link_left_jid.user or not link_left_jid.host:
raise jid.InvalidFormat
except jid.InvalidFormat:
txt_cmd.feedBack(
txt_cmd.feed_back(
client, "Can't deactivate Parrot mode for invalid jid", mess_data
)
return False
link_right_jid = mess_data["to"]
self.removeParrot(client, link_left_jid)
self.removeParrot(client, link_right_jid)
self.remove_parrot(client, link_left_jid)
self.remove_parrot(client, link_right_jid)
txt_cmd.feedBack(
txt_cmd.feed_back(
client,
"Parrot mode deactivated for {} and {}".format(
str(link_left_jid), str(link_right_jid)

Some files were not shown because too many files have changed in this diff Show more