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:
parent
d50412c7f7
commit
6a6f15707a
131 changed files with 9945 additions and 9945 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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}")
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in a new issue