massive refactoring to switch from camelCase to snake_case:

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

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

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

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

View file

@ -384,7 +384,7 @@ like this:
The encoding is explained in the documentation of the following method:
.. automethod:: sat.plugins.plugin_comp_ap_gateway.APGateway.getJIDAndNode
.. automethod:: sat.plugins.plugin_comp_ap_gateway.APGateway.get_jid_and_node
.. [#AP_chars] Most if not all AP implementations use webfinger `acct` URI as a de-facto
@ -859,10 +859,10 @@ Using the Component (for developers)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Publication of AP items can be tested using the following method (with can be accessed
through the ``APSend`` bridge method, client is then replaced by the ``profile`` name, as
through the ``ap_send`` bridge method, client is then replaced by the ``profile`` name, as
last argument):
.. automethod:: sat.plugins.plugin_comp_ap_gateway.APGateway.publishMessage
.. automethod:: sat.plugins.plugin_comp_ap_gateway.APGateway.publish_message
The method can be used either with CLI's :ref:`debug bridge method
<li_debug_bridge_method>` or with any D-Bus tool like ``qdbus`` or ``d-feet`` (only if you
@ -875,7 +875,7 @@ On its ``example.net`` Mastodon instance, Pierre has published a message with th
``https://example.net/@pierre/106986412193109832``. To send a reply to this message,
Louise can use the following command::
$ li debug bridge method -c APSend '"{\"node\": \"https://example.net/@pierre/106986412193109832\", \"content\": \"A lille hello from XMPP\"}","pierre\\40example.net@ap.example.org", "louise"'
$ li debug bridge method -c ap_send '"{\"node\": \"https://example.net/@pierre/106986412193109832\", \"content\": \"A lille hello from XMPP\"}","pierre\\40example.net@ap.example.org", "louise"'
Note the double escaping, one for the shell argument, and the other to specify JSON
object.

View file

@ -60,9 +60,9 @@ To save resources, not all nodes are fully cached. When a node is checked, a ser
analysers are checked, and the first one matching is used to determine if the node must be
synchronised or not.
Analysers can be registered by any plugins using ``registerAnalyser`` method:
Analysers can be registered by any plugins using ``register_analyser`` method:
.. automethod:: sat.plugins.plugin_pubsub_cache.PubsubCache.registerAnalyser
.. automethod:: sat.plugins.plugin_pubsub_cache.PubsubCache.register_analyser
If no analyser is found, ``to_sync`` is false, or an error happens during the caching,
the node won't be synchronised and the pubsub service will always be requested.

View file

@ -333,11 +333,11 @@ Get description of ``dotclear`` importer::
$ li blog import dotclear
Import a Dotclear blog::
import a Dotclear blog::
$ li blog import dotclear /path/to/dotclear.dump
Import a Dotclear blog without uploading images::
import a Dotclear blog without uploading images::
$ li blog import --no-images-upload dotclear /path/to/dotclear.dump

View file

@ -17,7 +17,7 @@ Python arguments as many shell arguments, or put them in a single shell argument
You profile is automatically set if the method requires it (using the value of ``-p
PROFILE, --profile PROFILE``), so you must not specify it as an extra argument.
You can refer to `Bridge API documentation`_ to get core methods signatures
You can refer to `bridge API documentation`_ to get core methods signatures
.. _Bridge API documentation: https://wiki.goffi.org/wiki/Bridge_API
@ -26,12 +26,12 @@ examples
--------
Send a message using a single shell arguments for all Python arguments. We
use first the method name (``messageSend``), then the required arguments (see `Bridge
use first the method name (``message_send``), then the required arguments (see `bridge
API documentation`_ for details), without the profile as it is automatically set. We
specify them as Python in one shell argument, so we use single quote (``\```)first for
s hell string, and inside it we use double quote (``"``) for Python strings::
$ li debug bridge method messageSend '"louise@example.org", {"": "test message"}, {}, "auto", {}'
$ li debug bridge method message_send '"louise@example.org", {"": "test message"}, {}, "auto", {}'
.. note::
@ -39,7 +39,7 @@ s hell string, and inside it we use double quote (``"``) for Python strings::
Get version string of Libervia::
$ li debug bridge method getVersion
$ li debug bridge method version_get
bridge signal
@ -56,7 +56,7 @@ Send a note with ``info`` level and hand written XMLUI. Here me use a shell vari
store the level, so we can easily change it if we want to use an other level for tests.
Note the use of quotes (to escape both for shell and Python)::
$ LEVEL='info'; li debug bridge signal -c actionNew '{"xmlui": '"'"'<?xml version="1.0" ?><sat_xmlui title="test title" type="dialog"><dialog level="'$LEVEL'" type="note"><message>test message\non\nseveral\nlines</message></dialog></sat_xmlui>'"'"'}' '""' -1
$ LEVEL='info'; li debug bridge signal -c action_new '{"xmlui": '"'"'<?xml version="1.0" ?><sat_xmlui title="test title" type="dialog"><dialog level="'$LEVEL'" type="note"><message>test message\non\nseveral\nlines</message></dialog></sat_xmlui>'"'"'}' '""' -1
monitor

View file

@ -35,10 +35,10 @@ Create a new event. You can specify the starting time of the event with ``-S TIM
If your organsise an item, the ``--rsvp`` flag should be used: it will use the default
RSVP form which ask for attendance. If you want to request more information to your guest,
``--rsvp_json JSON`` can be used: the JSON argument is a data dict as described in
``dataDict2dataForm`` function where the ``namespace`` key is not necessary (it's set
``data_dict_2_data_form`` function where the ``namespace`` key is not necessary (it's set
automatically):
.. autofunction:: sat.tools.xml_tools.dataDict2dataForm
.. autofunction:: sat.tools.xml_tools.data_dict_2_data_form
If the event links to an other one, ``--external JID NODE ITEM`` can be user

View file

@ -68,7 +68,7 @@ Delete item with id ``456`` from tickets on PubSub service ``pubsub.example.org`
import
======
Import lists from an external source. This works in the same way as
import lists from an external source. This works in the same way as
:ref:`libervia-cli_blog_import`: you need to specify an importer and a data location. If you let
both positional argument empty, you'll get list of importers, if you specify importer but
not data location, you'll get a description on how the importer works.
@ -99,7 +99,7 @@ Get description of list importer for Bugzilla::
$ li list import bugzilla
Import lists from a Bugzilla XML export file at ``~/bugzilla_export.xml`` to the
import lists from a Bugzilla XML export file at ``~/bugzilla_export.xml`` to the
``pubsub.example.org`` PubSub service. We use default lists node and want a progression
bar::

View file

@ -66,7 +66,7 @@ Display details for merge request with id 456::
import
======
Import a merge request into your project. You mainly have to be in the project repository
import a merge request into your project. You mainly have to be in the project repository
(or specify it using ``-r PATH, --repository PATH``) and to specify the id of the patch to
import (using ``-i ITEM, --item ITEM``). The behaviour depends of the type of the patch,
for Mercurial, the patch will be imported as `MQ`_ patch.
@ -76,6 +76,6 @@ for Mercurial, the patch will be imported as `MQ`_ patch.
example
-------
Import the merge request with id 321::
import the merge request with id 321::
$ li merge-request import -i 321

View file

@ -93,7 +93,7 @@ Make the ``public_notes`` node accessible to the world::
import
======
Import a raw XML containing items to create in the node. The path to the XML file is used
import a raw XML containing items to create in the node. The path to the XML file is used
as positional argument.
The XML file must contain full `<item>` element for each item to import. The output of ``pubsub get`` can be used directly.
@ -103,7 +103,7 @@ If you want to change publisher of one or more items (i.e. if you want to use an
example
-------
Import a node backup which has previously been saved using ``li blog get -M -1 -n
import a node backup which has previously been saved using ``li blog get -M -1 -n
some_node > some_node_backup.xml``::
$ li pubsub node import -n some_node ~/some_node_backup.xml

View file

@ -74,7 +74,7 @@ class Constructor(object):
function[option] = value
return function
def getDefault(self, name):
def get_default(self, name):
"""Return default values of a function in a dict
@param name: Name of the function to get
@return: dict, each key is the integer param number (no key if no default value)"""
@ -106,7 +106,7 @@ class Constructor(object):
flags.append(option)
return flags
def getArgumentsDoc(self, name):
def get_arguments_doc(self, name):
"""Return documentation of arguments
@param name: Name of the function to get
@return: dict, each key is the integer param number (no key if no argument doc), value is a tuple (name, doc)"""
@ -131,7 +131,7 @@ class Constructor(object):
doc_dict[idx] = (value_match.group(1), value_match.group(2))
return doc_dict
def getDoc(self, name):
def get_doc(self, name):
"""Return documentation of the method
@param name: Name of the function to get
@return: string documentation, or None"""
@ -139,7 +139,7 @@ class Constructor(object):
return self.bridge_template.get(name, "doc")
return None
def argumentsParser(self, signature):
def arguments_parser(self, signature):
"""Generator which return individual arguments signatures from a global signature"""
start = 0
i = 0
@ -176,19 +176,19 @@ class Constructor(object):
yield signature[start:i]
start = i
def getArguments(self, signature, name=None, default=None, unicode_protect=False):
def get_arguments(self, signature, name=None, default=None, unicode_protect=False):
"""Return arguments to user given a signature
@param signature: signature in the short form (using s,a,i,b etc)
@param name: dictionary of arguments name like given by getArgumentsDoc
@param default: dictionary of default values, like given by getDefault
@param name: dictionary of arguments name like given by get_arguments_doc
@param default: dictionary of default values, like given by get_default
@param unicode_protect: activate unicode protection on strings (return strings as unicode(str))
@return (str): arguments that correspond to a signature (e.g.: "sss" return "arg1, arg2, arg3")
"""
idx = 0
attr_string = []
for arg in self.argumentsParser(signature):
for arg in self.arguments_parser(signature):
attr_string.append(
(
"str(%(name)s)%(default)s"
@ -206,7 +206,7 @@ class Constructor(object):
return ", ".join(attr_string)
def getTemplatePath(self, template_file):
def get_template_path(self, template_file):
"""return template path corresponding to file name
@param template_file(str): name of template file
@ -232,12 +232,12 @@ class Constructor(object):
def generate(self, side):
"""generate bridge
call generateCoreSide or generateFrontendSide if they exists
call generate_core_side or generateFrontendSide if they exists
else call generic self._generate method
"""
try:
if side == "core":
method = self.generateCoreSide
method = self.generate_core_side
elif side == "frontend":
if not self.FRONTEND_ACTIVATE:
print("This constructor only handle core, please use core side")
@ -272,8 +272,8 @@ class Constructor(object):
for section in sections:
function = self.getValues(section)
print(("Adding %s %s" % (section, function["type"])))
default = self.getDefault(section)
arg_doc = self.getArgumentsDoc(section)
default = self.get_default(section)
arg_doc = self.get_arguments_doc(section)
async_ = "async" in self.getFlags(section)
completion = {
"sig_in": function["sig_in"] or "",
@ -281,10 +281,10 @@ class Constructor(object):
"category": "plugin" if function["category"] == "plugin" else "core",
"name": section,
# arguments with default values
"args": self.getArguments(
"args": self.get_arguments(
function["sig_in"], name=arg_doc, default=default
),
"args_no_default": self.getArguments(function["sig_in"], name=arg_doc),
"args_no_default": self.get_arguments(function["sig_in"], name=arg_doc),
}
extend_method = getattr(
@ -305,7 +305,7 @@ class Constructor(object):
for env, v in os.environ.items()
if env.startswith(C.ENV_OVERRIDE)
}
template_path = self.getTemplatePath(TEMPLATE)
template_path = self.get_template_path(TEMPLATE)
try:
with open(template_path) as template:
for line in template:
@ -332,9 +332,9 @@ class Constructor(object):
sys.exit(1)
# now we write to final file
self.finalWrite(DEST, bridge)
self.final_write(DEST, bridge)
def finalWrite(self, filename, file_buf):
def final_write(self, filename, file_buf):
"""Write the final generated file in [dest dir]/filename
@param filename: name of the file to generate

View file

@ -32,7 +32,7 @@ __version__ = C.APP_VERSION
class BridgeConstructor(object):
def importConstructors(self):
def import_constructors(self):
constructors_dir = os.path.dirname(constructors.__file__)
self.protocoles = {}
for dir_ in os.listdir(constructors_dir):
@ -120,7 +120,7 @@ class BridgeConstructor(object):
return parser.parse_args()
def go(self):
self.importConstructors()
self.import_constructors()
args = self.parse_args()
template_parser = Parser()
try:

View file

@ -20,7 +20,7 @@ sig_in=s
doc=Connection is finished or lost
doc_param_0=%(doc_profile)s
[newContact]
[contact_new]
type=signal
category=core
sig_in=sa{ss}ass
@ -34,7 +34,7 @@ doc_param_1=attributes: Dictionary of attributes where keys are:
doc_param_2=groups: Roster's groups where the contact is
doc_param_3=%(doc_profile)s
[messageNew]
[message_new]
type=signal
category=core
sig_in=sdssa{ss}a{ss}sss
@ -54,7 +54,7 @@ doc_param_7=extra: extra message information, can have data added by plugins and
- info_type: subtype for info messages
doc_param_8=%(doc_profile)s
[messageEncryptionStarted]
[message_encryption_started]
type=signal
category=core
sig_in=sss
@ -68,7 +68,7 @@ doc_param_1=encryption_data: (JSON_OBJ) data of the encryption algorithm used, e
- directed_devices: list or resource where session is encrypted
doc_param_2=%(doc_profile_key)s
[messageEncryptionStopped]
[message_encryption_stopped]
type=signal
category=core
sig_in=sa{ss}s
@ -79,7 +79,7 @@ doc_param_1=encryption_data: data of the encryption algorithm stopped, has a lea
- namespace: namespace of the encryption plugin
doc_param_2=%(doc_profile_key)s
[presenceUpdate]
[presence_update]
type=signal
category=core
sig_in=ssia{ss}s
@ -99,7 +99,7 @@ doc_param_0=sub_type: Subscription states (see RFC 6121 §3)
doc_param_1=entity_jid: JID from which the subscription is coming
doc_param_2=%(doc_profile)s
[paramUpdate]
[param_update]
type=signal
category=core
sig_in=ssss
@ -109,7 +109,7 @@ doc_param_1=value: New value of the parameter
doc_param_2=category: Category of the updated parameter
doc_param_3=%(doc_profile)s
[contactDeleted]
[contact_deleted]
type=signal
category=core
sig_in=ss
@ -117,7 +117,7 @@ doc=A contact has been supressed from roster
doc_param_0=entity_jid: JID of the contact removed from roster
doc_param_1=%(doc_profile)s
[actionNew]
[action_new]
type=signal
category=core
sig_in=a{ss}sis
@ -137,7 +137,7 @@ doc_param_1=id: action id
doc_param_2=%(doc_security_limit)s
doc_param_3=%(doc_profile)s
[entityDataUpdated]
[entity_data_updated]
type=signal
category=core
sig_in=ssss
@ -147,7 +147,7 @@ doc_param_1=name: Name of the updated value
doc_param_2=value: New value
doc_param_3=%(doc_profile)s
[progressStarted]
[progress_started]
type=signal
category=core
sig_in=sa{ss}s
@ -160,7 +160,7 @@ doc_param_1=metadata: dict of progress metadata, key can be:
C.META_TYPE_FILE: file transfer
doc_param_2=%(doc_profile)s
[progressFinished]
[progress_finished]
type=signal
category=core
sig_in=sa{ss}s
@ -170,11 +170,11 @@ doc_param_1=metadata: dict of progress status metadata, key can be:
- hash: value of the computed hash
- hash_algo: alrorithm used to compute hash
- hash_verified: C.BOOL_TRUE if hash is verified and OK
C.BOOL_FALSE if hash was not received ([progressError] will be used if there is a mismatch)
C.BOOL_FALSE if hash was not received ([progress_error] will be used if there is a mismatch)
- url: url linked to the progression (e.g. download url after a file upload)
doc_param_2=%(doc_profile)s
[progressError]
[progress_error]
type=signal
category=core
sig_in=sss
@ -194,7 +194,7 @@ doc_param_2=%(doc_profile)s
;methods
[getReady]
[ready_get]
async=
type=method
category=core
@ -202,14 +202,14 @@ sig_in=
sig_out=
doc=Return when backend is initialised
[getVersion]
[version_get]
type=method
category=core
sig_in=
sig_out=s
doc=Get "Salut à Toi" full version
[getFeatures]
[features_get]
type=method
category=core
sig_in=s
@ -221,7 +221,7 @@ doc_return=dictionary of available features:
plugin import name is used as key, data is an other dict managed by the plugin
async=
[profileNameGet]
[profile_name_get]
type=method
category=core
sig_in=s
@ -231,7 +231,7 @@ doc=Get real profile name from profile key
doc_param_0=%(doc_profile_key)s
doc_return=Real profile name
[profilesListGet]
[profiles_list_get]
type=method
category=core
sig_in=bb
@ -242,7 +242,7 @@ doc_param_0=clients: get clients profiles
doc_param_1=components: get components profiles
doc=Get list of profiles
[profileSetDefault]
[profile_set_default]
type=method
category=core
sig_in=s
@ -250,7 +250,7 @@ sig_out=
doc_param_0=%(doc_profile)s
doc=Set default profile
[getEntityData]
[entity_data_get]
type=method
category=core
sig_in=sass
@ -262,7 +262,7 @@ doc_param_2=%(doc_profile)s
doc_return=dictionary of asked key,
if key doesn't exist, the resulting dictionary will not have the key
[getEntitiesData]
[entities_data_get]
type=method
category=core
sig_in=asass
@ -275,7 +275,7 @@ doc_return=dictionary with jids as keys and dictionary of asked key as values
values are serialised
if key doesn't exist for a jid, the resulting dictionary will not have it
[profileCreate]
[profile_create]
async=
type=method
category=core
@ -293,7 +293,7 @@ errback is called with error constant as parameter:
- CancelError: profile creation canceled
- NotFound: component entry point is not available
[asyncDeleteProfile]
[profile_delete_async]
async=
type=method
category=core
@ -325,7 +325,7 @@ doc_return=a deferred boolean or failure:
- False if the XMPP connection has been initiated (it may still fail)
- failure if the profile authentication failed
[profileStartSession]
[profile_start_session]
async=
type=method
category=core
@ -340,7 +340,7 @@ doc_return=D(bool):
- True if the profile session was already started
- False else
[profileIsSessionStarted]
[profile_is_session_started]
type=method
category=core
sig_in=s
@ -359,7 +359,7 @@ param_0_default="@DEFAULT@"
doc=Disconnect a profile
doc_param_0=%(doc_profile_key)s
[isConnected]
[is_connected]
type=method
category=core
sig_in=s
@ -368,7 +368,7 @@ param_0_default="@DEFAULT@"
doc=Tell if a profile is connected
doc_param_0=%(doc_profile_key)s
[contactGet]
[contact_get]
async=
type=method
category=core
@ -378,10 +378,10 @@ param_1_default="@DEFAULT@"
doc=Return informations in roster about a contact
doc_param_1=%(doc_profile_key)s
doc_return=tuple with the following values:
- list of attributes as in [newContact]
- list of attributes as in [contact_new]
- groups where the contact is
[getContacts]
[contacts_get]
async=
type=method
category=core
@ -392,10 +392,10 @@ doc=Return information about all contacts (the roster)
doc_param_0=%(doc_profile_key)s
doc_return=array of tuples with the following values:
- JID of the contact
- list of attributes as in [newContact]
- list of attributes as in [contact_new]
- groups where the contact is
[getContactsFromGroup]
[contacts_get_from_group]
type=method
category=core
sig_in=ss
@ -406,7 +406,7 @@ doc_param_0=group: name of the group to check
doc_param_1=%(doc_profile_key)s
doc_return=array of jids
[getMainResource]
[main_resource_get]
type=method
category=core
sig_in=ss
@ -417,7 +417,7 @@ doc_param_0=contact_jid: jid of the contact
doc_param_1=%(doc_profile_key)s
doc_return=the resource connected of the contact with highest priority, or ""
[getPresenceStatuses]
[presence_statuses_get]
type=method
category=core
sig_in=s
@ -426,9 +426,9 @@ param_0_default="@DEFAULT@"
doc=Return presence information of all contacts
doc_param_0=%(doc_profile_key)s
doc_return=Dict of presence with bare JID of contact as key, and value as follow:
A dict where key is the resource and the value is a tuple with (show, priority, statuses) as for [presenceUpdate]
A dict where key is the resource and the value is a tuple with (show, priority, statuses) as for [presence_update]
[getWaitingSub]
[sub_waiting_get]
type=method
category=core
sig_in=s
@ -438,7 +438,7 @@ doc=Get subscription requests in queue
doc_param_0=%(doc_profile_key)s
doc_return=Dict where contact JID is the key, and value is the subscription type
[messageSend]
[message_send]
async=
type=method
category=core
@ -458,7 +458,7 @@ doc_param_3=mess_type: Type of the message (cf RFC 6121 §5.2.2) or "auto" for a
doc_param_4=extra: (serialised) optional data that can be used by a plugin to build more specific messages
doc_param_5=%(doc_profile_key)s
[messageEncryptionStart]
[message_encryption_start]
async=
type=method
category=core
@ -474,7 +474,7 @@ doc_param_2=replace: if True and an encryption session already exists, it will b
else a ConflictError will be raised
doc_param_3=%(doc_profile_key)s
[messageEncryptionStop]
[message_encryption_stop]
async=
type=method
category=core
@ -484,7 +484,7 @@ doc=Stop an encryption session
doc_param_0=to_jid: JID of the recipient (full jid if encryption must be stopped for one device only)
doc_param_1=%(doc_profile_key)s
[messageEncryptionGet]
[message_encryption_get]
type=method
category=core
sig_in=ss
@ -499,21 +499,21 @@ doc_return=(JSON_OBJ) empty string if session is unencrypted, else a json encode
following key can be present if suitable:
- directed_devices: list or resource where session is encrypted
[encryptionNamespaceGet]
[encryption_namespace_get]
type=method
category=core
sig_in=s
sig_out=s
doc=Get algorithm namespace from its name
[encryptionPluginsGet]
[encryption_plugins_get]
type=method
category=core
sig_in=
sig_out=s
doc=Retrieve registered plugins for encryption
[encryptionTrustUIGet]
[encryption_trust_ui_get]
async=
type=method
category=core
@ -525,7 +525,7 @@ doc_param_1=namespace: namespace of the algorithm to manage
doc_param_2=%(doc_profile_key)s
doc_return=(XMLUI) UI of the trust management
[setPresence]
[presence_set]
type=method
category=core
sig_in=ssa{ss}s
@ -536,8 +536,8 @@ param_2_default={}
param_3_default="@DEFAULT@"
doc=Set presence information for the profile
doc_param_0=to_jid: the JID to who we send the presence data (emtpy string for broadcast)
doc_param_1=show: as for [presenceUpdate]
doc_param_2=statuses: as for [presenceUpdate]
doc_param_1=show: as for [presence_update]
doc_param_2=statuses: as for [presence_update]
doc_param_3=%(doc_profile_key)s
[subscription]
@ -551,7 +551,7 @@ doc_param_0=sub_type: as for [subscribe]
doc_param_1=entity: as for [subscribe]
doc_param_2=%(doc_profile_key)s
[getConfig]
[config_get]
type=method
category=core
sig_in=ss
@ -560,7 +560,7 @@ doc=get main configuration option
doc_param_0=section: section of the configuration file (empty string for DEFAULT)
doc_param_1=name: name of the option
[setParam]
[param_set]
type=method
category=core
sig_in=sssis
@ -574,7 +574,7 @@ doc_param_2=category: Category of the parameter to change
doc_param_3=%(doc_security_limit)s
doc_param_4=%(doc_profile_key)s
[getParamA]
[param_get_a]
type=method
category=core
sig_in=ssss
@ -582,12 +582,12 @@ sig_out=s
param_2_default="value"
param_3_default="@DEFAULT@"
doc=Helper method to get a parameter's attribute *when profile is connected*
doc_param_0=name: as for [setParam]
doc_param_1=category: as for [setParam]
doc_param_0=name: as for [param_set]
doc_param_1=category: as for [param_set]
doc_param_2=attribute: Name of the attribute
doc_param_3=%(doc_profile_key)s
[privateDataGet]
[private_data_get]
async=
type=method
category=core
@ -599,7 +599,7 @@ doc_param_1=key: key of the data to set
doc_param_2=%(doc_profile_key)s
doc_return=serialised data
[privateDataSet]
[private_data_set]
async=
type=method
category=core
@ -611,7 +611,7 @@ doc_param_1=key: key of the data to set
doc_param_2=data: serialised data
doc_param_3=%(doc_profile_key)s
[privateDataDelete]
[private_data_delete]
async=
type=method
category=core
@ -622,7 +622,7 @@ doc_param_0=namespace: unique namespace to use
doc_param_1=key: key of the data to delete
doc_param_3=%(doc_profile_key)s
[asyncGetParamA]
[param_get_a_async]
async=
type=method
category=core
@ -632,13 +632,13 @@ param_2_default="value"
param_3_default=-1
param_4_default="@DEFAULT@"
doc=Helper method to get a parameter's attribute
doc_param_0=name: as for [setParam]
doc_param_1=category: as for [setParam]
doc_param_0=name: as for [param_set]
doc_param_1=category: as for [param_set]
doc_param_2=attribute: Name of the attribute
doc_param_3=%(doc_security_limit)s
doc_param_4=%(doc_profile_key)s
[asyncGetParamsValuesFromCategory]
[params_values_from_category_get_async]
async=
type=method
category=code
@ -649,13 +649,13 @@ param_2_default=""
param_3_default=""
param_4_default="@DEFAULT@"
doc=Get "attribute" for all params of a category
doc_param_0=category: as for [setParam]
doc_param_0=category: as for [param_set]
doc_param_1=%(doc_security_limit)s
doc_param_2=app: name of the frontend requesting the parameters, or '' to get all parameters
doc_param_3=extra: extra options/filters
doc_param_4=%(doc_profile_key)s
[getParamsUI]
[param_ui_get]
async=
type=method
category=core
@ -671,7 +671,7 @@ doc_param_1=app: name of the frontend requesting the parameters, or '' to get al
doc_param_2=extra: extra options/filters
doc_param_3=%(doc_profile_key)s
[getParamsCategories]
[params_categories_get]
type=method
category=core
sig_in=
@ -679,7 +679,7 @@ sig_out=as
doc=Get all categories currently existing in parameters
doc_return=list of categories
[paramsRegisterApp]
[params_register_app]
type=method
category=core
sig_in=sis
@ -691,7 +691,7 @@ doc_param_0=xml: XML definition of the parameters to be added
doc_param_1=%(doc_security_limit)s
doc_param_2=app: name of the frontend registering the parameters
[historyGet]
[history_get]
async=
type=method
category=core
@ -712,9 +712,9 @@ doc_param_4=filters: patterns to filter the history results, can be:
- not_types: type must not be one of those, values are separated by spaces
- before_uid: check only message received before message with given uid
doc_param_5=%(doc_profile)s
doc_return=Ordered list (by timestamp) of data as in [messageNew] (without final profile)
doc_return=Ordered list (by timestamp) of data as in [message_new] (without final profile)
[addContact]
[contact_add]
type=method
category=core
sig_in=ss
@ -724,7 +724,7 @@ doc=Add a contact to profile's roster
doc_param_0=entity_jid: JID to add to roster
doc_param_1=%(doc_profile_key)s
[updateContact]
[contact_update]
type=method
category=core
sig_in=ssass
@ -736,7 +736,7 @@ doc_param_1=name: roster's name for the entity
doc_param_2=groups: list of group where the entity is
doc_param_3=%(doc_profile_key)s
[delContact]
[contact_del]
async=
type=method
category=core
@ -747,7 +747,7 @@ doc=Remove a contact from profile's roster
doc_param_0=entity_jid: JID to remove from roster
doc_param_1=%(doc_profile_key)s
[rosterResync]
[roster_resync]
async=
type=method
category=core
@ -757,7 +757,7 @@ param_0_default="@DEFAULT@"
doc=Do a full resynchronisation of roster with server
doc_param_0=%(doc_profile_key)s
[launchAction]
[action_launch]
async=
type=method
category=core
@ -771,7 +771,7 @@ doc_param_2=%(doc_profile_key)s
doc_return=dict where key can be:
- xmlui: a XMLUI need to be displayed
[actionsGet]
[actions_get]
type=method
category=core
sig_in=s
@ -779,9 +779,9 @@ sig_out=a(a{ss}si)
param_0_default="@DEFAULT@"
doc=Get all not yet answered actions
doc_param_0=%(doc_profile_key)s
doc_return=list of data as for [actionNew] (without the profile)
doc_return=list of data as for [action_new] (without the profile)
[progressGet]
[progress_get]
type=method
category=core
sig_in=ss
@ -794,7 +794,7 @@ doc_return=dict with progress informations:
- size: end position (optional if not known)
other metadata may be present
[progressGetAllMetadata]
[progress_get_all_metadata]
type=method
category=core
sig_in=s
@ -803,9 +803,9 @@ doc=Get all active progress informations
doc_param_0=%(doc_profile)s or C.PROF_KEY_ALL for all profiles
doc_return= a dict which map profile to progress_dict
progress_dict map progress_id to progress_metadata
progress_metadata is the same dict as sent by [progressStarted]
progress_metadata is the same dict as sent by [progress_started]
[progressGetAll]
[progress_get_all]
type=method
category=core
sig_in=s
@ -814,9 +814,9 @@ doc=Get all active progress informations
doc_param_0=%(doc_profile)s or C.PROF_KEY_ALL for all profiles
doc_return= a dict which map profile to progress_dict
progress_dict map progress_id to progress_data
progress_data is the same dict as returned by [progressGet]
progress_data is the same dict as returned by [progress_get]
[menusGet]
[menus_get]
type=method
category=core
sig_in=si
@ -832,7 +832,7 @@ doc_return=list of tuple with the following value:
- menu_path_i18n: translated path of the menu
- extra: extra data, like icon name
[menuLaunch]
[menu_launch]
async=
type=method
category=core
@ -847,7 +847,7 @@ doc_param_4=%(doc_profile_key)s
doc_return=dict where key can be:
- xmlui: a XMLUI need to be displayed
[menuHelpGet]
[menu_help_get]
type=method
category=core
sig_in=ss
@ -858,7 +858,7 @@ doc_param_0=menu_id: id of the menu (same as callback_id)
doc_param_1=language: language in which the menu should be translated (empty string for default)
doc_return=Translated help string
[discoInfos]
[disco_infos]
async=
type=method
category=core
@ -884,7 +884,7 @@ doc_return=discovery data:
* desc
- list of values
[discoItems]
[disco_items]
async=
type=method
category=core
@ -900,7 +900,7 @@ doc_param_2=use_cache: use cached data if available
doc_param_3=%(doc_profile_key)s
doc_return=array of tuple (entity, node identifier, name)
[discoFindByFeatures]
[disco_find_by_features]
async=
type=method
category=core
@ -927,7 +927,7 @@ doc_return=tuple of maps of found entities full jids to their identities. Maps a
- own entities (i.e. entities linked to profile's jid)
- roster entities
[saveParamsTemplate]
[params_template_save]
type=method
category=core
sig_in=s
@ -936,7 +936,7 @@ doc=Save parameters template to xml file
doc_param_0=filename: output filename
doc_return=boolean (True in case of success)
[loadParamsTemplate]
[params_template_load]
type=method
category=core
sig_in=s
@ -945,7 +945,7 @@ doc=Load parameters template from xml file
doc_param_0=filename: input filename
doc_return=boolean (True in case of success)
[sessionInfosGet]
[session_infos_get]
async=
type=method
category=core
@ -957,7 +957,7 @@ doc_return=session informations, with at least the following keys:
jid: current full jid
started: date of creation of the session (Epoch time)
[devicesInfosGet]
[devices_infos_get]
async=
type=method
category=core
@ -970,7 +970,7 @@ doc_param_1=%(doc_profile_key)s
doc_return=list of known devices, where each item is a dict with a least following keys:
resource: device resource
[namespacesGet]
[namespaces_get]
type=method
category=core
sig_in=
@ -978,7 +978,7 @@ sig_out=a{ss}
doc=Get a dict to short name => whole namespaces
doc_return=namespaces mapping
[imageCheck]
[image_check]
type=method
category=core
sig_in=s
@ -986,7 +986,7 @@ sig_out=s
doc=Analyze an image a return a report
doc_return=serialized report
[imageResize]
[image_resize]
async=
type=method
category=core
@ -999,7 +999,7 @@ doc_param_2=height: height of the new image
doc_return=path of the new image with desired size
the image must be deleted once not needed anymore
[imageGeneratePreview]
[image_generate_preview]
async=
type=method
category=core
@ -1010,7 +1010,7 @@ doc_param_0=image_path: path of the original image
doc_param_1=%(doc_profile_key)s
doc_return=path to the preview in cache
[imageConvert]
[image_convert]
async=
type=method
category=core

View file

@ -38,9 +38,9 @@ class DbusXmlConstructor(base_constructor.Constructor):
"a{sa{s(sia{ss})}}": "PresenceStatusT",
}
def generateCoreSide(self):
def generate_core_side(self):
try:
doc = minidom.parse(self.getTemplatePath(self.template))
doc = minidom.parse(self.get_template_path(self.template))
interface_elt = doc.getElementsByTagName("interface")[0]
except IOError:
print("Can't access template")
@ -60,8 +60,8 @@ class DbusXmlConstructor(base_constructor.Constructor):
new_elt.setAttribute("name", section)
idx = 0
args_doc = self.getArgumentsDoc(section)
for arg in self.argumentsParser(function["sig_in"] or ""):
args_doc = self.get_arguments_doc(section)
for arg in self.arguments_parser(function["sig_in"] or ""):
arg_elt = doc.createElement("arg")
arg_elt.setAttribute(
"name", args_doc[idx][0] if idx in args_doc else "arg_%i" % idx
@ -99,4 +99,4 @@ class DbusXmlConstructor(base_constructor.Constructor):
interface_elt.appendChild(new_elt)
# now we write to final file
self.finalWrite(self.core_dest, [doc.toprettyxml()])
self.final_write(self.core_dest, [doc.toprettyxml()])

View file

@ -81,7 +81,7 @@ class DbusConstructor(base_constructor.Constructor):
"debug": ""
if not self.args.debug
else 'log.debug ("%s")\n%s' % (completion["name"], 8 * " "),
"args_result": self.getArguments(function["sig_in"], name=arg_doc),
"args_result": self.get_arguments(function["sig_in"], name=arg_doc),
"async_args": "callback=None, errback=None",
"async_comma": ", " if function["sig_in"] else "",
"error_handler": """if callback is None:

View file

@ -30,8 +30,8 @@ from txdbus.interface import DBusInterface, Method, Signal
log = getLogger(__name__)
# Interface prefix
const_INT_PREFIX = config.getConfig(
config.parseMainConf(),
const_INT_PREFIX = config.config_get(
config.parse_main_conf(),
"",
"bridge_dbus_int_prefix",
"org.libervia.Libervia")
@ -118,13 +118,13 @@ class DBusObject(objects.DBusObject):
##METHODS_PART##
class Bridge:
class bridge:
def __init__(self):
log.info("Init DBus...")
self._obj = DBusObject(const_OBJ_PATH)
async def postInit(self):
async def post_init(self):
try:
conn = await client.connect(reactor)
except error.DBusException as e:
@ -145,13 +145,13 @@ class Bridge:
log.debug(f"registering DBus bridge method [{name}]")
self._obj.register_method(name, callback)
def emitSignal(self, name, *args):
def emit_signal(self, name, *args):
self._obj.emitSignal(name, *args)
def addMethod(
def add_method(
self, name, int_suffix, in_sign, out_sign, method, async_=False, doc={}
):
"""Dynamically add a method to D-Bus Bridge"""
"""Dynamically add a method to D-Bus bridge"""
# FIXME: doc parameter is kept only temporary, the time to remove it from calls
log.debug(f"Adding method {name!r} to D-Bus bridge")
self._obj.plugin_iface.addMethod(
@ -164,8 +164,8 @@ class Bridge:
setattr(self._obj, f"dbus_{name}", MethodType(caller, self._obj))
self.register_method(name, method)
def addSignal(self, name, int_suffix, signature, doc={}):
"""Dynamically add a signal to D-Bus Bridge"""
def add_signal(self, name, int_suffix, signature, doc={}):
"""Dynamically add a signal to D-Bus bridge"""
log.debug(f"Adding signal {name!r} to D-Bus bridge")
self._obj.plugin_iface.addSignal(Signal(name, signature))
setattr(Bridge, name, partialmethod(Bridge.emitSignal, name))
setattr(bridge, name, partialmethod(bridge.emit_signal, name))

View file

@ -32,8 +32,8 @@ log = getLogger(__name__)
# Interface prefix
const_INT_PREFIX = config.getConfig(
config.parseMainConf(),
const_INT_PREFIX = config.config_get(
config.parse_main_conf(),
"",
"bridge_dbus_int_prefix",
"org.libervia.Libervia")
@ -66,9 +66,9 @@ def dbus_to_bridge_exception(dbus_e):
return BridgeException(name, message, condition)
class Bridge:
class bridge:
def bridgeConnect(self, callback, errback):
def bridge_connect(self, callback, errback):
try:
self.sessions_bus = dbus.SessionBus()
self.db_object = self.sessions_bus.get_object(const_INT_PREFIX,
@ -105,7 +105,7 @@ class Bridge:
except AttributeError:
# The attribute is not found, we try the plugin proxy to find the requested method
def getPluginMethod(*args, **kwargs):
def get_plugin_method(*args, **kwargs):
# We first check if we have an async call. We detect this in two ways:
# - if we have the 'callback' and 'errback' keyword arguments
# - or if the last two arguments are callable
@ -156,11 +156,11 @@ class Bridge:
return self.db_plugin_iface.get_dbus_method(name)(*args, **kwargs)
raise e
return getPluginMethod
return get_plugin_method
##METHODS_PART##
class AIOBridge(Bridge):
class AIOBridge(bridge):
def register_signal(self, functionName, handler, iface="core"):
loop = asyncio.get_running_loop()
@ -173,7 +173,7 @@ class AIOBridge(Bridge):
return object.__getattribute__(self, name)
except AttributeError:
# The attribute is not found, we try the plugin proxy to find the requested method
def getPluginMethod(*args, **kwargs):
def get_plugin_method(*args, **kwargs):
loop = asyncio.get_running_loop()
fut = loop.create_future()
method = getattr(self.db_plugin_iface, name)
@ -191,7 +191,7 @@ class AIOBridge(Bridge):
)
except ValueError as e:
if e.args[0].startswith("Unable to guess signature"):
# same hack as for Bridge.__getattribute__
# same hack as for bridge.__getattribute__
log.warning("using hack to work around inspection issue")
proxy = self.db_plugin_iface.proxy_object
IN_PROGRESS = proxy.INTROSPECT_STATE_INTROSPECT_IN_PROGRESS
@ -209,12 +209,12 @@ class AIOBridge(Bridge):
raise e
return fut
return getPluginMethod
return get_plugin_method
def bridgeConnect(self):
def bridge_connect(self):
loop = asyncio.get_running_loop()
fut = loop.create_future()
super().bridgeConnect(
super().bridge_connect(
callback=lambda: loop.call_soon_threadsafe(fut.set_result, None),
errback=lambda e: loop.call_soon_threadsafe(fut.set_exception, e)
)

View file

@ -51,7 +51,7 @@ class EmbeddedConstructor(base_constructor.Constructor):
"debug": ""
if not self.args.debug
else 'log.debug ("%s")\n%s' % (completion["name"], 8 * " "),
"args_result": self.getArguments(function["sig_in"], name=arg_doc),
"args_result": self.get_arguments(function["sig_in"], name=arg_doc),
"args_comma": ", " if function["sig_in"] else "",
}
)
@ -96,5 +96,5 @@ class EmbeddedConstructor(base_constructor.Constructor):
def core_completion_signal(self, completion, function, default, arg_doc, async_):
completion.update(
{"args_result": self.getArguments(function["sig_in"], name=arg_doc)}
{"args_result": self.get_arguments(function["sig_in"], name=arg_doc)}
)

View file

@ -17,4 +17,4 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from sat.bridge.embedded import Bridge
from sat.bridge.embedded import bridge

View file

@ -29,7 +29,7 @@ class _Bridge(object):
self._methods_cbs = {}
self._signals_cbs = {"core": {}, "plugin": {}}
def bridgeConnect(self, callback, errback):
def bridge_connect(self, callback, errback):
callback()
def register_method(self, name, callback):
@ -85,7 +85,7 @@ class _Bridge(object):
else:
cb(*args, **kwargs)
def addMethod(self, name, int_suffix, in_sign, out_sign, method, async_=False, doc={}):
def add_method(self, name, int_suffix, in_sign, out_sign, method, async_=False, doc={}):
# FIXME: doc parameter is kept only temporary, the time to remove it from calls
log.debug("Adding method [{}] to embedded bridge".format(name))
self.register_method(name, method)
@ -97,7 +97,7 @@ class _Bridge(object):
),
)
def addSignal(self, name, int_suffix, signature, doc={}):
def add_signal(self, name, int_suffix, signature, doc={}):
setattr(
self.__class__,
name,
@ -116,7 +116,7 @@ class _Bridge(object):
bridge = None
def Bridge():
def bridge():
global bridge
if bridge is None:
bridge = _Bridge()

View file

@ -29,7 +29,7 @@ class MediawikiConstructor(base_constructor.Constructor):
self.core_template = "mediawiki_template.tpl"
self.core_dest = "mediawiki.wiki"
def _addTextDecorations(self, text):
def _add_text_decorations(self, text):
"""Add text decorations like coloration or shortcuts"""
def anchor_link(match):
@ -42,43 +42,43 @@ class MediawikiConstructor(base_constructor.Constructor):
return re.sub(r"\[(\w+)\]", anchor_link, text)
def _wikiParameter(self, name, sig_in):
def _wiki_parameter(self, name, sig_in):
"""Format parameters with the wiki syntax
@param name: name of the function
@param sig_in: signature in
@return: string of the formated parameters"""
arg_doc = self.getArgumentsDoc(name)
arg_default = self.getDefault(name)
args_str = self.getArguments(sig_in)
arg_doc = self.get_arguments_doc(name)
arg_default = self.get_default(name)
args_str = self.get_arguments(sig_in)
args = args_str.split(", ") if args_str else [] # ugly but it works :)
wiki = []
for i in range(len(args)):
if i in arg_doc:
name, doc = arg_doc[i]
doc = "\n:".join(doc.rstrip("\n").split("\n"))
wiki.append("; %s: %s" % (name, self._addTextDecorations(doc)))
wiki.append("; %s: %s" % (name, self._add_text_decorations(doc)))
else:
wiki.append("; arg_%d: " % i)
if i in arg_default:
wiki.append(":''DEFAULT: %s''" % arg_default[i])
return "\n".join(wiki)
def _wikiReturn(self, name):
def _wiki_return(self, name):
"""Format return doc with the wiki syntax
@param name: name of the function
"""
arg_doc = self.getArgumentsDoc(name)
arg_doc = self.get_arguments_doc(name)
wiki = []
if "return" in arg_doc:
wiki.append("\n|-\n! scope=row | return value\n|")
wiki.append(
"<br />\n".join(
self._addTextDecorations(arg_doc["return"]).rstrip("\n").split("\n")
self._add_text_decorations(arg_doc["return"]).rstrip("\n").split("\n")
)
)
return "\n".join(wiki)
def generateCoreSide(self):
def generate_core_side(self):
signals_part = []
methods_part = []
sections = self.bridge_template.sections()
@ -114,13 +114,13 @@ class MediawikiConstructor(base_constructor.Constructor):
"sig_out": function["sig_out"] or "",
"category": function["category"],
"name": section,
"doc": self.getDoc(section) or "FIXME: No description available",
"doc": self.get_doc(section) or "FIXME: No description available",
"async": async_msg if "async" in self.getFlags(section) else "",
"deprecated": deprecated_msg
if "deprecated" in self.getFlags(section)
else "",
"parameters": self._wikiParameter(section, function["sig_in"]),
"return": self._wikiReturn(section)
"parameters": self._wiki_parameter(section, function["sig_in"]),
"return": self._wiki_return(section)
if function["type"] == "method"
else "",
}
@ -148,7 +148,7 @@ class MediawikiConstructor(base_constructor.Constructor):
# at this point, signals_part, and methods_part should be filled,
# we just have to place them in the right part of the template
core_bridge = []
template_path = self.getTemplatePath(self.core_template)
template_path = self.get_template_path(self.core_template)
try:
with open(template_path) as core_template:
for line in core_template:
@ -165,4 +165,4 @@ class MediawikiConstructor(base_constructor.Constructor):
sys.exit(1)
# now we write to final file
self.finalWrite(self.core_dest, core_bridge)
self.final_write(self.core_dest, core_bridge)

View file

@ -26,7 +26,7 @@ class pbConstructor(base_constructor.Constructor):
CORE_FORMATS = {
"signals": """\
def {name}(self, {args}):
{debug}self.sendSignal("{name}", {args_no_def})\n"""
{debug}self.send_signal("{name}", {args_no_def})\n"""
}
FRONTEND_TEMPLATE = "pb_frontend_template.py"
@ -49,7 +49,7 @@ class pbConstructor(base_constructor.Constructor):
}
def core_completion_signal(self, completion, function, default, arg_doc, async_):
completion["args_no_def"] = self.getArguments(function["sig_in"], name=arg_doc)
completion["args_no_def"] = self.get_arguments(function["sig_in"], name=arg_doc)
completion["debug"] = (
""
if not self.args.debug
@ -60,7 +60,7 @@ class pbConstructor(base_constructor.Constructor):
completion.update(
{
"args_comma": ", " if function["sig_in"] else "",
"args_no_def": self.getArguments(function["sig_in"], name=arg_doc),
"args_no_def": self.get_arguments(function["sig_in"], name=arg_doc),
"callback": "callback"
if function["sig_out"]
else "lambda __: callback()",

View file

@ -55,17 +55,17 @@ class PBRoot(pb.Root):
def __init__(self):
self.signals_handlers = []
def remote_initBridge(self, signals_handler):
def remote_init_bridge(self, signals_handler):
self.signals_handlers.append(HandlerWrapper(signals_handler))
log.info("registered signal handler")
def sendSignalEb(self, failure_, signal_name):
def send_signal_eb(self, failure_, signal_name):
if not failure_.check(pb.PBConnectionLost):
log.error(
f"Error while sending signal {signal_name}: {failure_}",
)
def sendSignal(self, name, args, kwargs):
def send_signal(self, name, args, kwargs):
to_remove = []
for wrapper in self.signals_handlers:
handler = wrapper.handler
@ -74,13 +74,13 @@ class PBRoot(pb.Root):
except pb.DeadReferenceError:
to_remove.append(wrapper)
else:
d.addErrback(self.sendSignalEb, name)
d.addErrback(self.send_signal_eb, name)
if to_remove:
for wrapper in to_remove:
log.debug("Removing signal handler for dead frontend")
self.signals_handlers.remove(wrapper)
def _bridgeDeactivateSignals(self):
def _bridge_deactivate_signals(self):
if hasattr(self, "signals_paused"):
log.warning("bridge signals already deactivated")
if self.signals_handler:
@ -90,7 +90,7 @@ class PBRoot(pb.Root):
self.signals_handlers = []
log.debug("bridge signals have been deactivated")
def _bridgeReactivateSignals(self):
def _bridge_reactivate_signals(self):
try:
self.signals_handlers = self.signals_paused
except AttributeError:
@ -102,31 +102,31 @@ class PBRoot(pb.Root):
##METHODS_PART##
class Bridge(object):
class bridge(object):
def __init__(self):
log.info("Init Perspective Broker...")
self.root = PBRoot()
conf = config.parseMainConf()
getConf = partial(config.getConf, conf, "bridge_pb", "")
conn_type = getConf("connection_type", "unix_socket")
conf = config.parse_main_conf()
get_conf = partial(config.get_conf, conf, "bridge_pb", "")
conn_type = get_conf("connection_type", "unix_socket")
if conn_type == "unix_socket":
local_dir = Path(config.getConfig(conf, "", "local_dir")).resolve()
local_dir = Path(config.config_get(conf, "", "local_dir")).resolve()
socket_path = local_dir / "bridge_pb"
log.info(f"using UNIX Socket at {socket_path}")
reactor.listenUNIX(
str(socket_path), pb.PBServerFactory(self.root), mode=0o600
)
elif conn_type == "socket":
port = int(getConf("port", 8789))
port = int(get_conf("port", 8789))
log.info(f"using TCP Socket at port {port}")
reactor.listenTCP(port, pb.PBServerFactory(self.root))
else:
raise ValueError(f"Unknown pb connection type: {conn_type!r}")
def sendSignal(self, name, *args, **kwargs):
self.root.sendSignal(name, args, kwargs)
def send_signal(self, name, *args, **kwargs):
self.root.send_signal(name, args, kwargs)
def remote_initBridge(self, signals_handler):
def remote_init_bridge(self, signals_handler):
self.signals_handlers.append(signals_handler)
log.info("registered signal handler")
@ -135,32 +135,32 @@ class Bridge(object):
setattr(self.root, "remote_" + name, callback)
#  self.root.register_method(name, callback)
def addMethod(
def add_method(
self, name, int_suffix, in_sign, out_sign, method, async_=False, doc={}
):
"""Dynamically add a method to PB Bridge"""
"""Dynamically add a method to PB bridge"""
# FIXME: doc parameter is kept only temporary, the time to remove it from calls
log.debug("Adding method {name} to PB bridge".format(name=name))
self.register_method(name, method)
def addSignal(self, name, int_suffix, signature, doc={}):
def add_signal(self, name, int_suffix, signature, doc={}):
log.debug("Adding signal {name} to PB bridge".format(name=name))
setattr(
self, name, lambda *args, **kwargs: self.sendSignal(name, *args, **kwargs)
self, name, lambda *args, **kwargs: self.send_signal(name, *args, **kwargs)
)
def bridgeDeactivateSignals(self):
def bridge_deactivate_signals(self):
"""Stop sending signals to bridge
Mainly used for mobile frontends, when the frontend is paused
"""
self.root._bridgeDeactivateSignals()
self.root._bridge_deactivate_signals()
def bridgeReactivateSignals(self):
def bridge_reactivate_signals(self):
"""Send again signals to bridge
Should only be used after bridgeDeactivateSignals has been called
Should only be used after bridge_deactivate_signals has been called
"""
self.root._bridgeReactivateSignals()
self.root._bridge_reactivate_signals()
##SIGNALS_PART##

View file

@ -55,7 +55,7 @@ class SignalsHandler(pb.Referenceable):
setattr(self, method_name, handler)
class Bridge(object):
class bridge(object):
def __init__(self):
self.signals_handler = SignalsHandler()
@ -75,7 +75,7 @@ class Bridge(object):
)
)
def remoteCallback(self, result, callback):
def remote_callback(self, result, callback):
"""call callback with argument or None
if result is not None not argument is used,
@ -112,11 +112,11 @@ class Bridge(object):
callback = args.pop()
d = self.root.callRemote(name, *args, **kwargs)
if callback is not None:
d.addCallback(self.remoteCallback, callback)
d.addCallback(self.remote_callback, callback)
if errback is not None:
d.addErrback(errback)
def _initBridgeEb(self, failure_):
def _init_bridge_eb(self, failure_):
log.error("Can't init bridge: {msg}".format(msg=failure_))
return failure_
@ -127,28 +127,28 @@ class Bridge(object):
"""
self.root = root
d = root.callRemote("initBridge", self.signals_handler)
d.addErrback(self._initBridgeEb)
d.addErrback(self._init_bridge_eb)
return d
def getRootObjectEb(self, failure_):
def get_root_object_eb(self, failure_):
"""Call errback with appropriate bridge error"""
if failure_.check(ConnectionRefusedError, ConnectError):
raise exceptions.BridgeExceptionNoService
else:
raise failure_
def bridgeConnect(self, callback, errback):
def bridge_connect(self, callback, errback):
factory = pb.PBClientFactory()
conf = config.parseMainConf()
getConf = partial(config.getConf, conf, "bridge_pb", "")
conn_type = getConf("connection_type", "unix_socket")
conf = config.parse_main_conf()
get_conf = partial(config.get_conf, conf, "bridge_pb", "")
conn_type = get_conf("connection_type", "unix_socket")
if conn_type == "unix_socket":
local_dir = Path(config.getConfig(conf, "", "local_dir")).resolve()
local_dir = Path(config.config_get(conf, "", "local_dir")).resolve()
socket_path = local_dir / "bridge_pb"
reactor.connectUNIX(str(socket_path), factory)
elif conn_type == "socket":
host = getConf("host", "localhost")
port = int(getConf("port", 8789))
host = get_conf("host", "localhost")
port = int(get_conf("port", 8789))
reactor.connectTCP(host, port, factory)
else:
raise ValueError(f"Unknown pb connection type: {conn_type!r}")
@ -156,7 +156,7 @@ class Bridge(object):
d.addCallback(self._set_root)
if callback is not None:
d.addCallback(lambda __: callback())
d.addErrback(self.getRootObjectEb)
d.addErrback(self.get_root_object_eb)
if errback is not None:
d.addErrback(lambda failure_: errback(failure_.value))
return d
@ -175,7 +175,7 @@ class AIOSignalsHandler(SignalsHandler):
return super().register_signal(name, async_handler, iface)
class AIOBridge(Bridge):
class AIOBridge(bridge):
def __init__(self):
self.signals_handler = AIOSignalsHandler()
@ -192,8 +192,8 @@ class AIOBridge(Bridge):
d.addErrback(self._errback)
return d.asFuture(asyncio.get_event_loop())
async def bridgeConnect(self):
d = super().bridgeConnect(callback=None, errback=None)
async def bridge_connect(self):
d = super().bridge_connect(callback=None, errback=None)
return await d.asFuture(asyncio.get_event_loop())
##ASYNC_METHODS_PART##

View file

@ -30,8 +30,8 @@ from txdbus.interface import DBusInterface, Method, Signal
log = getLogger(__name__)
# Interface prefix
const_INT_PREFIX = config.getConfig(
config.parseMainConf(),
const_INT_PREFIX = config.config_get(
config.parse_main_conf(),
"",
"bridge_dbus_int_prefix",
"org.libervia.Libervia")
@ -88,87 +88,87 @@ class DBusObject(objects.DBusObject):
core_iface = DBusInterface(
const_INT_PREFIX + const_CORE_SUFFIX,
Method('actionsGet', arguments='s', returns='a(a{ss}si)'),
Method('addContact', arguments='ss', returns=''),
Method('asyncDeleteProfile', arguments='s', returns=''),
Method('asyncGetParamA', arguments='sssis', returns='s'),
Method('asyncGetParamsValuesFromCategory', arguments='sisss', returns='a{ss}'),
Method('action_launch', arguments='sa{ss}s', returns='a{ss}'),
Method('actions_get', arguments='s', returns='a(a{ss}si)'),
Method('config_get', arguments='ss', returns='s'),
Method('connect', arguments='ssa{ss}', returns='b'),
Method('contactGet', arguments='ss', returns='(a{ss}as)'),
Method('delContact', arguments='ss', returns=''),
Method('devicesInfosGet', arguments='ss', returns='s'),
Method('discoFindByFeatures', arguments='asa(ss)bbbbbs', returns='(a{sa(sss)}a{sa(sss)}a{sa(sss)})'),
Method('discoInfos', arguments='ssbs', returns='(asa(sss)a{sa(a{ss}as)})'),
Method('discoItems', arguments='ssbs', returns='a(sss)'),
Method('contact_add', arguments='ss', returns=''),
Method('contact_del', arguments='ss', returns=''),
Method('contact_get', arguments='ss', returns='(a{ss}as)'),
Method('contact_update', arguments='ssass', returns=''),
Method('contacts_get', arguments='s', returns='a(sa{ss}as)'),
Method('contacts_get_from_group', arguments='ss', returns='as'),
Method('devices_infos_get', arguments='ss', returns='s'),
Method('disco_find_by_features', arguments='asa(ss)bbbbbs', returns='(a{sa(sss)}a{sa(sss)}a{sa(sss)})'),
Method('disco_infos', arguments='ssbs', returns='(asa(sss)a{sa(a{ss}as)})'),
Method('disco_items', arguments='ssbs', returns='a(sss)'),
Method('disconnect', arguments='s', returns=''),
Method('encryptionNamespaceGet', arguments='s', returns='s'),
Method('encryptionPluginsGet', arguments='', returns='s'),
Method('encryptionTrustUIGet', arguments='sss', returns='s'),
Method('getConfig', arguments='ss', returns='s'),
Method('getContacts', arguments='s', returns='a(sa{ss}as)'),
Method('getContactsFromGroup', arguments='ss', returns='as'),
Method('getEntitiesData', arguments='asass', returns='a{sa{ss}}'),
Method('getEntityData', arguments='sass', returns='a{ss}'),
Method('getFeatures', arguments='s', returns='a{sa{ss}}'),
Method('getMainResource', arguments='ss', returns='s'),
Method('getParamA', arguments='ssss', returns='s'),
Method('getParamsCategories', arguments='', returns='as'),
Method('getParamsUI', arguments='isss', returns='s'),
Method('getPresenceStatuses', arguments='s', returns='a{sa{s(sia{ss})}}'),
Method('getReady', arguments='', returns=''),
Method('getVersion', arguments='', returns='s'),
Method('getWaitingSub', arguments='s', returns='a{ss}'),
Method('historyGet', arguments='ssiba{ss}s', returns='a(sdssa{ss}a{ss}ss)'),
Method('imageCheck', arguments='s', returns='s'),
Method('imageConvert', arguments='ssss', returns='s'),
Method('imageGeneratePreview', arguments='ss', returns='s'),
Method('imageResize', arguments='sii', returns='s'),
Method('isConnected', arguments='s', returns='b'),
Method('launchAction', arguments='sa{ss}s', returns='a{ss}'),
Method('loadParamsTemplate', arguments='s', returns='b'),
Method('menuHelpGet', arguments='ss', returns='s'),
Method('menuLaunch', arguments='sasa{ss}is', returns='a{ss}'),
Method('menusGet', arguments='si', returns='a(ssasasa{ss})'),
Method('messageEncryptionGet', arguments='ss', returns='s'),
Method('messageEncryptionStart', arguments='ssbs', returns=''),
Method('messageEncryptionStop', arguments='ss', returns=''),
Method('messageSend', arguments='sa{ss}a{ss}sss', returns=''),
Method('namespacesGet', arguments='', returns='a{ss}'),
Method('paramsRegisterApp', arguments='sis', returns=''),
Method('privateDataDelete', arguments='sss', returns=''),
Method('privateDataGet', arguments='sss', returns='s'),
Method('privateDataSet', arguments='ssss', returns=''),
Method('profileCreate', arguments='sss', returns=''),
Method('profileIsSessionStarted', arguments='s', returns='b'),
Method('profileNameGet', arguments='s', returns='s'),
Method('profileSetDefault', arguments='s', returns=''),
Method('profileStartSession', arguments='ss', returns='b'),
Method('profilesListGet', arguments='bb', returns='as'),
Method('progressGet', arguments='ss', returns='a{ss}'),
Method('progressGetAll', arguments='s', returns='a{sa{sa{ss}}}'),
Method('progressGetAllMetadata', arguments='s', returns='a{sa{sa{ss}}}'),
Method('rosterResync', arguments='s', returns=''),
Method('saveParamsTemplate', arguments='s', returns='b'),
Method('sessionInfosGet', arguments='s', returns='a{ss}'),
Method('setParam', arguments='sssis', returns=''),
Method('setPresence', arguments='ssa{ss}s', returns=''),
Method('encryption_namespace_get', arguments='s', returns='s'),
Method('encryption_plugins_get', arguments='', returns='s'),
Method('encryption_trust_ui_get', arguments='sss', returns='s'),
Method('entities_data_get', arguments='asass', returns='a{sa{ss}}'),
Method('entity_data_get', arguments='sass', returns='a{ss}'),
Method('features_get', arguments='s', returns='a{sa{ss}}'),
Method('history_get', arguments='ssiba{ss}s', returns='a(sdssa{ss}a{ss}ss)'),
Method('image_check', arguments='s', returns='s'),
Method('image_convert', arguments='ssss', returns='s'),
Method('image_generate_preview', arguments='ss', returns='s'),
Method('image_resize', arguments='sii', returns='s'),
Method('is_connected', arguments='s', returns='b'),
Method('main_resource_get', arguments='ss', returns='s'),
Method('menu_help_get', arguments='ss', returns='s'),
Method('menu_launch', arguments='sasa{ss}is', returns='a{ss}'),
Method('menus_get', arguments='si', returns='a(ssasasa{ss})'),
Method('message_encryption_get', arguments='ss', returns='s'),
Method('message_encryption_start', arguments='ssbs', returns=''),
Method('message_encryption_stop', arguments='ss', returns=''),
Method('message_send', arguments='sa{ss}a{ss}sss', returns=''),
Method('namespaces_get', arguments='', returns='a{ss}'),
Method('param_get_a', arguments='ssss', returns='s'),
Method('param_get_a_async', arguments='sssis', returns='s'),
Method('param_set', arguments='sssis', returns=''),
Method('param_ui_get', arguments='isss', returns='s'),
Method('params_categories_get', arguments='', returns='as'),
Method('params_register_app', arguments='sis', returns=''),
Method('params_template_load', arguments='s', returns='b'),
Method('params_template_save', arguments='s', returns='b'),
Method('params_values_from_category_get_async', arguments='sisss', returns='a{ss}'),
Method('presence_set', arguments='ssa{ss}s', returns=''),
Method('presence_statuses_get', arguments='s', returns='a{sa{s(sia{ss})}}'),
Method('private_data_delete', arguments='sss', returns=''),
Method('private_data_get', arguments='sss', returns='s'),
Method('private_data_set', arguments='ssss', returns=''),
Method('profile_create', arguments='sss', returns=''),
Method('profile_delete_async', arguments='s', returns=''),
Method('profile_is_session_started', arguments='s', returns='b'),
Method('profile_name_get', arguments='s', returns='s'),
Method('profile_set_default', arguments='s', returns=''),
Method('profile_start_session', arguments='ss', returns='b'),
Method('profiles_list_get', arguments='bb', returns='as'),
Method('progress_get', arguments='ss', returns='a{ss}'),
Method('progress_get_all', arguments='s', returns='a{sa{sa{ss}}}'),
Method('progress_get_all_metadata', arguments='s', returns='a{sa{sa{ss}}}'),
Method('ready_get', arguments='', returns=''),
Method('roster_resync', arguments='s', returns=''),
Method('session_infos_get', arguments='s', returns='a{ss}'),
Method('sub_waiting_get', arguments='s', returns='a{ss}'),
Method('subscription', arguments='sss', returns=''),
Method('updateContact', arguments='ssass', returns=''),
Method('version_get', arguments='', returns='s'),
Signal('_debug', 'sa{ss}s'),
Signal('actionNew', 'a{ss}sis'),
Signal('action_new', 'a{ss}sis'),
Signal('connected', 'ss'),
Signal('contactDeleted', 'ss'),
Signal('contact_deleted', 'ss'),
Signal('contact_new', 'sa{ss}ass'),
Signal('disconnected', 's'),
Signal('entityDataUpdated', 'ssss'),
Signal('messageEncryptionStarted', 'sss'),
Signal('messageEncryptionStopped', 'sa{ss}s'),
Signal('messageNew', 'sdssa{ss}a{ss}sss'),
Signal('newContact', 'sa{ss}ass'),
Signal('paramUpdate', 'ssss'),
Signal('presenceUpdate', 'ssia{ss}s'),
Signal('progressError', 'sss'),
Signal('progressFinished', 'sa{ss}s'),
Signal('progressStarted', 'sa{ss}s'),
Signal('entity_data_updated', 'ssss'),
Signal('message_encryption_started', 'sss'),
Signal('message_encryption_stopped', 'sa{ss}s'),
Signal('message_new', 'sdssa{ss}a{ss}sss'),
Signal('param_update', 'ssss'),
Signal('presence_update', 'ssia{ss}s'),
Signal('progress_error', 'sss'),
Signal('progress_finished', 'sa{ss}s'),
Signal('progress_started', 'sa{ss}s'),
Signal('subscribe', 'sss'),
)
plugin_iface = DBusInterface(
@ -196,212 +196,212 @@ class DBusObject(objects.DBusObject):
d.addErrback(GenericException.create_and_raise)
return d
def dbus_actionsGet(self, profile_key="@DEFAULT@"):
return self._callback("actionsGet", profile_key)
def dbus_action_launch(self, callback_id, data, profile_key="@DEFAULT@"):
return self._callback("action_launch", callback_id, data, profile_key)
def dbus_addContact(self, entity_jid, profile_key="@DEFAULT@"):
return self._callback("addContact", entity_jid, profile_key)
def dbus_actions_get(self, profile_key="@DEFAULT@"):
return self._callback("actions_get", profile_key)
def dbus_asyncDeleteProfile(self, profile):
return self._callback("asyncDeleteProfile", profile)
def dbus_asyncGetParamA(self, name, category, attribute="value", security_limit=-1, profile_key="@DEFAULT@"):
return self._callback("asyncGetParamA", name, category, attribute, security_limit, profile_key)
def dbus_asyncGetParamsValuesFromCategory(self, category, security_limit=-1, app="", extra="", profile_key="@DEFAULT@"):
return self._callback("asyncGetParamsValuesFromCategory", category, security_limit, app, extra, profile_key)
def dbus_config_get(self, section, name):
return self._callback("config_get", section, name)
def dbus_connect(self, profile_key="@DEFAULT@", password='', options={}):
return self._callback("connect", profile_key, password, options)
def dbus_contactGet(self, arg_0, profile_key="@DEFAULT@"):
return self._callback("contactGet", arg_0, profile_key)
def dbus_contact_add(self, entity_jid, profile_key="@DEFAULT@"):
return self._callback("contact_add", entity_jid, profile_key)
def dbus_delContact(self, entity_jid, profile_key="@DEFAULT@"):
return self._callback("delContact", entity_jid, profile_key)
def dbus_contact_del(self, entity_jid, profile_key="@DEFAULT@"):
return self._callback("contact_del", entity_jid, profile_key)
def dbus_devicesInfosGet(self, bare_jid, profile_key):
return self._callback("devicesInfosGet", bare_jid, profile_key)
def dbus_contact_get(self, arg_0, profile_key="@DEFAULT@"):
return self._callback("contact_get", arg_0, profile_key)
def dbus_discoFindByFeatures(self, namespaces, identities, bare_jid=False, service=True, roster=True, own_jid=True, local_device=False, profile_key="@DEFAULT@"):
return self._callback("discoFindByFeatures", namespaces, identities, bare_jid, service, roster, own_jid, local_device, profile_key)
def dbus_contact_update(self, entity_jid, name, groups, profile_key="@DEFAULT@"):
return self._callback("contact_update", entity_jid, name, groups, profile_key)
def dbus_discoInfos(self, entity_jid, node=u'', use_cache=True, profile_key="@DEFAULT@"):
return self._callback("discoInfos", entity_jid, node, use_cache, profile_key)
def dbus_contacts_get(self, profile_key="@DEFAULT@"):
return self._callback("contacts_get", profile_key)
def dbus_discoItems(self, entity_jid, node=u'', use_cache=True, profile_key="@DEFAULT@"):
return self._callback("discoItems", entity_jid, node, use_cache, profile_key)
def dbus_contacts_get_from_group(self, group, profile_key="@DEFAULT@"):
return self._callback("contacts_get_from_group", group, profile_key)
def dbus_devices_infos_get(self, bare_jid, profile_key):
return self._callback("devices_infos_get", bare_jid, profile_key)
def dbus_disco_find_by_features(self, namespaces, identities, bare_jid=False, service=True, roster=True, own_jid=True, local_device=False, profile_key="@DEFAULT@"):
return self._callback("disco_find_by_features", namespaces, identities, bare_jid, service, roster, own_jid, local_device, profile_key)
def dbus_disco_infos(self, entity_jid, node=u'', use_cache=True, profile_key="@DEFAULT@"):
return self._callback("disco_infos", entity_jid, node, use_cache, profile_key)
def dbus_disco_items(self, entity_jid, node=u'', use_cache=True, profile_key="@DEFAULT@"):
return self._callback("disco_items", entity_jid, node, use_cache, profile_key)
def dbus_disconnect(self, profile_key="@DEFAULT@"):
return self._callback("disconnect", profile_key)
def dbus_encryptionNamespaceGet(self, arg_0):
return self._callback("encryptionNamespaceGet", arg_0)
def dbus_encryption_namespace_get(self, arg_0):
return self._callback("encryption_namespace_get", arg_0)
def dbus_encryptionPluginsGet(self, ):
return self._callback("encryptionPluginsGet", )
def dbus_encryption_plugins_get(self, ):
return self._callback("encryption_plugins_get", )
def dbus_encryptionTrustUIGet(self, to_jid, namespace, profile_key):
return self._callback("encryptionTrustUIGet", to_jid, namespace, profile_key)
def dbus_encryption_trust_ui_get(self, to_jid, namespace, profile_key):
return self._callback("encryption_trust_ui_get", to_jid, namespace, profile_key)
def dbus_getConfig(self, section, name):
return self._callback("getConfig", section, name)
def dbus_entities_data_get(self, jids, keys, profile):
return self._callback("entities_data_get", jids, keys, profile)
def dbus_getContacts(self, profile_key="@DEFAULT@"):
return self._callback("getContacts", profile_key)
def dbus_entity_data_get(self, jid, keys, profile):
return self._callback("entity_data_get", jid, keys, profile)
def dbus_getContactsFromGroup(self, group, profile_key="@DEFAULT@"):
return self._callback("getContactsFromGroup", group, profile_key)
def dbus_features_get(self, profile_key):
return self._callback("features_get", profile_key)
def dbus_getEntitiesData(self, jids, keys, profile):
return self._callback("getEntitiesData", jids, keys, profile)
def dbus_history_get(self, from_jid, to_jid, limit, between=True, filters='', profile="@NONE@"):
return self._callback("history_get", from_jid, to_jid, limit, between, filters, profile)
def dbus_getEntityData(self, jid, keys, profile):
return self._callback("getEntityData", jid, keys, profile)
def dbus_image_check(self, arg_0):
return self._callback("image_check", arg_0)
def dbus_getFeatures(self, profile_key):
return self._callback("getFeatures", profile_key)
def dbus_image_convert(self, source, dest, arg_2, extra):
return self._callback("image_convert", source, dest, arg_2, extra)
def dbus_getMainResource(self, contact_jid, profile_key="@DEFAULT@"):
return self._callback("getMainResource", contact_jid, profile_key)
def dbus_image_generate_preview(self, image_path, profile_key):
return self._callback("image_generate_preview", image_path, profile_key)
def dbus_getParamA(self, name, category, attribute="value", profile_key="@DEFAULT@"):
return self._callback("getParamA", name, category, attribute, profile_key)
def dbus_image_resize(self, image_path, width, height):
return self._callback("image_resize", image_path, width, height)
def dbus_getParamsCategories(self, ):
return self._callback("getParamsCategories", )
def dbus_is_connected(self, profile_key="@DEFAULT@"):
return self._callback("is_connected", profile_key)
def dbus_getParamsUI(self, security_limit=-1, app='', extra='', profile_key="@DEFAULT@"):
return self._callback("getParamsUI", security_limit, app, extra, profile_key)
def dbus_main_resource_get(self, contact_jid, profile_key="@DEFAULT@"):
return self._callback("main_resource_get", contact_jid, profile_key)
def dbus_getPresenceStatuses(self, profile_key="@DEFAULT@"):
return self._callback("getPresenceStatuses", profile_key)
def dbus_menu_help_get(self, menu_id, language):
return self._callback("menu_help_get", menu_id, language)
def dbus_getReady(self, ):
return self._callback("getReady", )
def dbus_menu_launch(self, menu_type, path, data, security_limit, profile_key):
return self._callback("menu_launch", menu_type, path, data, security_limit, profile_key)
def dbus_getVersion(self, ):
return self._callback("getVersion", )
def dbus_menus_get(self, language, security_limit):
return self._callback("menus_get", language, security_limit)
def dbus_getWaitingSub(self, profile_key="@DEFAULT@"):
return self._callback("getWaitingSub", profile_key)
def dbus_message_encryption_get(self, to_jid, profile_key):
return self._callback("message_encryption_get", to_jid, profile_key)
def dbus_historyGet(self, from_jid, to_jid, limit, between=True, filters='', profile="@NONE@"):
return self._callback("historyGet", from_jid, to_jid, limit, between, filters, profile)
def dbus_message_encryption_start(self, to_jid, namespace='', replace=False, profile_key="@NONE@"):
return self._callback("message_encryption_start", to_jid, namespace, replace, profile_key)
def dbus_imageCheck(self, arg_0):
return self._callback("imageCheck", arg_0)
def dbus_message_encryption_stop(self, to_jid, profile_key):
return self._callback("message_encryption_stop", to_jid, profile_key)
def dbus_imageConvert(self, source, dest, arg_2, extra):
return self._callback("imageConvert", source, dest, arg_2, extra)
def dbus_message_send(self, to_jid, message, subject={}, mess_type="auto", extra={}, profile_key="@NONE@"):
return self._callback("message_send", to_jid, message, subject, mess_type, extra, profile_key)
def dbus_imageGeneratePreview(self, image_path, profile_key):
return self._callback("imageGeneratePreview", image_path, profile_key)
def dbus_namespaces_get(self, ):
return self._callback("namespaces_get", )
def dbus_imageResize(self, image_path, width, height):
return self._callback("imageResize", image_path, width, height)
def dbus_param_get_a(self, name, category, attribute="value", profile_key="@DEFAULT@"):
return self._callback("param_get_a", name, category, attribute, profile_key)
def dbus_isConnected(self, profile_key="@DEFAULT@"):
return self._callback("isConnected", profile_key)
def dbus_param_get_a_async(self, name, category, attribute="value", security_limit=-1, profile_key="@DEFAULT@"):
return self._callback("param_get_a_async", name, category, attribute, security_limit, profile_key)
def dbus_launchAction(self, callback_id, data, profile_key="@DEFAULT@"):
return self._callback("launchAction", callback_id, data, profile_key)
def dbus_param_set(self, name, value, category, security_limit=-1, profile_key="@DEFAULT@"):
return self._callback("param_set", name, value, category, security_limit, profile_key)
def dbus_loadParamsTemplate(self, filename):
return self._callback("loadParamsTemplate", filename)
def dbus_param_ui_get(self, security_limit=-1, app='', extra='', profile_key="@DEFAULT@"):
return self._callback("param_ui_get", security_limit, app, extra, profile_key)
def dbus_menuHelpGet(self, menu_id, language):
return self._callback("menuHelpGet", menu_id, language)
def dbus_params_categories_get(self, ):
return self._callback("params_categories_get", )
def dbus_menuLaunch(self, menu_type, path, data, security_limit, profile_key):
return self._callback("menuLaunch", menu_type, path, data, security_limit, profile_key)
def dbus_params_register_app(self, xml, security_limit=-1, app=''):
return self._callback("params_register_app", xml, security_limit, app)
def dbus_menusGet(self, language, security_limit):
return self._callback("menusGet", language, security_limit)
def dbus_params_template_load(self, filename):
return self._callback("params_template_load", filename)
def dbus_messageEncryptionGet(self, to_jid, profile_key):
return self._callback("messageEncryptionGet", to_jid, profile_key)
def dbus_params_template_save(self, filename):
return self._callback("params_template_save", filename)
def dbus_messageEncryptionStart(self, to_jid, namespace='', replace=False, profile_key="@NONE@"):
return self._callback("messageEncryptionStart", to_jid, namespace, replace, profile_key)
def dbus_params_values_from_category_get_async(self, category, security_limit=-1, app="", extra="", profile_key="@DEFAULT@"):
return self._callback("params_values_from_category_get_async", category, security_limit, app, extra, profile_key)
def dbus_messageEncryptionStop(self, to_jid, profile_key):
return self._callback("messageEncryptionStop", to_jid, profile_key)
def dbus_presence_set(self, to_jid='', show='', statuses={}, profile_key="@DEFAULT@"):
return self._callback("presence_set", to_jid, show, statuses, profile_key)
def dbus_messageSend(self, to_jid, message, subject={}, mess_type="auto", extra={}, profile_key="@NONE@"):
return self._callback("messageSend", to_jid, message, subject, mess_type, extra, profile_key)
def dbus_presence_statuses_get(self, profile_key="@DEFAULT@"):
return self._callback("presence_statuses_get", profile_key)
def dbus_namespacesGet(self, ):
return self._callback("namespacesGet", )
def dbus_private_data_delete(self, namespace, key, arg_2):
return self._callback("private_data_delete", namespace, key, arg_2)
def dbus_paramsRegisterApp(self, xml, security_limit=-1, app=''):
return self._callback("paramsRegisterApp", xml, security_limit, app)
def dbus_private_data_get(self, namespace, key, profile_key):
return self._callback("private_data_get", namespace, key, profile_key)
def dbus_privateDataDelete(self, namespace, key, arg_2):
return self._callback("privateDataDelete", namespace, key, arg_2)
def dbus_private_data_set(self, namespace, key, data, profile_key):
return self._callback("private_data_set", namespace, key, data, profile_key)
def dbus_privateDataGet(self, namespace, key, profile_key):
return self._callback("privateDataGet", namespace, key, profile_key)
def dbus_profile_create(self, profile, password='', component=''):
return self._callback("profile_create", profile, password, component)
def dbus_privateDataSet(self, namespace, key, data, profile_key):
return self._callback("privateDataSet", namespace, key, data, profile_key)
def dbus_profile_delete_async(self, profile):
return self._callback("profile_delete_async", profile)
def dbus_profileCreate(self, profile, password='', component=''):
return self._callback("profileCreate", profile, password, component)
def dbus_profile_is_session_started(self, profile_key="@DEFAULT@"):
return self._callback("profile_is_session_started", profile_key)
def dbus_profileIsSessionStarted(self, profile_key="@DEFAULT@"):
return self._callback("profileIsSessionStarted", profile_key)
def dbus_profile_name_get(self, profile_key="@DEFAULT@"):
return self._callback("profile_name_get", profile_key)
def dbus_profileNameGet(self, profile_key="@DEFAULT@"):
return self._callback("profileNameGet", profile_key)
def dbus_profile_set_default(self, profile):
return self._callback("profile_set_default", profile)
def dbus_profileSetDefault(self, profile):
return self._callback("profileSetDefault", profile)
def dbus_profile_start_session(self, password='', profile_key="@DEFAULT@"):
return self._callback("profile_start_session", password, profile_key)
def dbus_profileStartSession(self, password='', profile_key="@DEFAULT@"):
return self._callback("profileStartSession", password, profile_key)
def dbus_profiles_list_get(self, clients=True, components=False):
return self._callback("profiles_list_get", clients, components)
def dbus_profilesListGet(self, clients=True, components=False):
return self._callback("profilesListGet", clients, components)
def dbus_progress_get(self, id, profile):
return self._callback("progress_get", id, profile)
def dbus_progressGet(self, id, profile):
return self._callback("progressGet", id, profile)
def dbus_progress_get_all(self, profile):
return self._callback("progress_get_all", profile)
def dbus_progressGetAll(self, profile):
return self._callback("progressGetAll", profile)
def dbus_progress_get_all_metadata(self, profile):
return self._callback("progress_get_all_metadata", profile)
def dbus_progressGetAllMetadata(self, profile):
return self._callback("progressGetAllMetadata", profile)
def dbus_ready_get(self, ):
return self._callback("ready_get", )
def dbus_rosterResync(self, profile_key="@DEFAULT@"):
return self._callback("rosterResync", profile_key)
def dbus_roster_resync(self, profile_key="@DEFAULT@"):
return self._callback("roster_resync", profile_key)
def dbus_saveParamsTemplate(self, filename):
return self._callback("saveParamsTemplate", filename)
def dbus_session_infos_get(self, profile_key):
return self._callback("session_infos_get", profile_key)
def dbus_sessionInfosGet(self, profile_key):
return self._callback("sessionInfosGet", profile_key)
def dbus_setParam(self, name, value, category, security_limit=-1, profile_key="@DEFAULT@"):
return self._callback("setParam", name, value, category, security_limit, profile_key)
def dbus_setPresence(self, to_jid='', show='', statuses={}, profile_key="@DEFAULT@"):
return self._callback("setPresence", to_jid, show, statuses, profile_key)
def dbus_sub_waiting_get(self, profile_key="@DEFAULT@"):
return self._callback("sub_waiting_get", profile_key)
def dbus_subscription(self, sub_type, entity, profile_key="@DEFAULT@"):
return self._callback("subscription", sub_type, entity, profile_key)
def dbus_updateContact(self, entity_jid, name, groups, profile_key="@DEFAULT@"):
return self._callback("updateContact", entity_jid, name, groups, profile_key)
def dbus_version_get(self, ):
return self._callback("version_get", )
class Bridge:
class bridge:
def __init__(self):
log.info("Init DBus...")
self._obj = DBusObject(const_OBJ_PATH)
async def postInit(self):
async def post_init(self):
try:
conn = await client.connect(reactor)
except error.DBusException as e:
@ -420,47 +420,47 @@ class Bridge:
def _debug(self, action, params, profile):
self._obj.emitSignal("_debug", action, params, profile)
def actionNew(self, action_data, id, security_limit, profile):
self._obj.emitSignal("actionNew", action_data, id, security_limit, profile)
def action_new(self, action_data, id, security_limit, profile):
self._obj.emitSignal("action_new", action_data, id, security_limit, profile)
def connected(self, jid_s, profile):
self._obj.emitSignal("connected", jid_s, profile)
def contactDeleted(self, entity_jid, profile):
self._obj.emitSignal("contactDeleted", entity_jid, profile)
def contact_deleted(self, entity_jid, profile):
self._obj.emitSignal("contact_deleted", entity_jid, profile)
def contact_new(self, contact_jid, attributes, groups, profile):
self._obj.emitSignal("contact_new", contact_jid, attributes, groups, profile)
def disconnected(self, profile):
self._obj.emitSignal("disconnected", profile)
def entityDataUpdated(self, jid, name, value, profile):
self._obj.emitSignal("entityDataUpdated", jid, name, value, profile)
def entity_data_updated(self, jid, name, value, profile):
self._obj.emitSignal("entity_data_updated", jid, name, value, profile)
def messageEncryptionStarted(self, to_jid, encryption_data, profile_key):
self._obj.emitSignal("messageEncryptionStarted", to_jid, encryption_data, profile_key)
def message_encryption_started(self, to_jid, encryption_data, profile_key):
self._obj.emitSignal("message_encryption_started", to_jid, encryption_data, profile_key)
def messageEncryptionStopped(self, to_jid, encryption_data, profile_key):
self._obj.emitSignal("messageEncryptionStopped", to_jid, encryption_data, profile_key)
def message_encryption_stopped(self, to_jid, encryption_data, profile_key):
self._obj.emitSignal("message_encryption_stopped", to_jid, encryption_data, profile_key)
def messageNew(self, uid, timestamp, from_jid, to_jid, message, subject, mess_type, extra, profile):
self._obj.emitSignal("messageNew", uid, timestamp, from_jid, to_jid, message, subject, mess_type, extra, profile)
def message_new(self, uid, timestamp, from_jid, to_jid, message, subject, mess_type, extra, profile):
self._obj.emitSignal("message_new", uid, timestamp, from_jid, to_jid, message, subject, mess_type, extra, profile)
def newContact(self, contact_jid, attributes, groups, profile):
self._obj.emitSignal("newContact", contact_jid, attributes, groups, profile)
def param_update(self, name, value, category, profile):
self._obj.emitSignal("param_update", name, value, category, profile)
def paramUpdate(self, name, value, category, profile):
self._obj.emitSignal("paramUpdate", name, value, category, profile)
def presence_update(self, entity_jid, show, priority, statuses, profile):
self._obj.emitSignal("presence_update", entity_jid, show, priority, statuses, profile)
def presenceUpdate(self, entity_jid, show, priority, statuses, profile):
self._obj.emitSignal("presenceUpdate", entity_jid, show, priority, statuses, profile)
def progress_error(self, id, error, profile):
self._obj.emitSignal("progress_error", id, error, profile)
def progressError(self, id, error, profile):
self._obj.emitSignal("progressError", id, error, profile)
def progress_finished(self, id, metadata, profile):
self._obj.emitSignal("progress_finished", id, metadata, profile)
def progressFinished(self, id, metadata, profile):
self._obj.emitSignal("progressFinished", id, metadata, profile)
def progressStarted(self, id, metadata, profile):
self._obj.emitSignal("progressStarted", id, metadata, profile)
def progress_started(self, id, metadata, profile):
self._obj.emitSignal("progress_started", id, metadata, profile)
def subscribe(self, sub_type, entity_jid, profile):
self._obj.emitSignal("subscribe", sub_type, entity_jid, profile)
@ -469,13 +469,13 @@ class Bridge:
log.debug(f"registering DBus bridge method [{name}]")
self._obj.register_method(name, callback)
def emitSignal(self, name, *args):
def emit_signal(self, name, *args):
self._obj.emitSignal(name, *args)
def addMethod(
def add_method(
self, name, int_suffix, in_sign, out_sign, method, async_=False, doc={}
):
"""Dynamically add a method to D-Bus Bridge"""
"""Dynamically add a method to D-Bus bridge"""
# FIXME: doc parameter is kept only temporary, the time to remove it from calls
log.debug(f"Adding method {name!r} to D-Bus bridge")
self._obj.plugin_iface.addMethod(
@ -488,8 +488,8 @@ class Bridge:
setattr(self._obj, f"dbus_{name}", MethodType(caller, self._obj))
self.register_method(name, method)
def addSignal(self, name, int_suffix, signature, doc={}):
"""Dynamically add a signal to D-Bus Bridge"""
def add_signal(self, name, int_suffix, signature, doc={}):
"""Dynamically add a signal to D-Bus bridge"""
log.debug(f"Adding signal {name!r} to D-Bus bridge")
self._obj.plugin_iface.addSignal(Signal(name, signature))
setattr(Bridge, name, partialmethod(Bridge.emitSignal, name))
setattr(bridge, name, partialmethod(bridge.emit_signal, name))

View file

@ -55,17 +55,17 @@ class PBRoot(pb.Root):
def __init__(self):
self.signals_handlers = []
def remote_initBridge(self, signals_handler):
def remote_init_bridge(self, signals_handler):
self.signals_handlers.append(HandlerWrapper(signals_handler))
log.info("registered signal handler")
def sendSignalEb(self, failure_, signal_name):
def send_signal_eb(self, failure_, signal_name):
if not failure_.check(pb.PBConnectionLost):
log.error(
f"Error while sending signal {signal_name}: {failure_}",
)
def sendSignal(self, name, args, kwargs):
def send_signal(self, name, args, kwargs):
to_remove = []
for wrapper in self.signals_handlers:
handler = wrapper.handler
@ -74,13 +74,13 @@ class PBRoot(pb.Root):
except pb.DeadReferenceError:
to_remove.append(wrapper)
else:
d.addErrback(self.sendSignalEb, name)
d.addErrback(self.send_signal_eb, name)
if to_remove:
for wrapper in to_remove:
log.debug("Removing signal handler for dead frontend")
self.signals_handlers.remove(wrapper)
def _bridgeDeactivateSignals(self):
def _bridge_deactivate_signals(self):
if hasattr(self, "signals_paused"):
log.warning("bridge signals already deactivated")
if self.signals_handler:
@ -90,7 +90,7 @@ class PBRoot(pb.Root):
self.signals_handlers = []
log.debug("bridge signals have been deactivated")
def _bridgeReactivateSignals(self):
def _bridge_reactivate_signals(self):
try:
self.signals_handlers = self.signals_paused
except AttributeError:
@ -102,31 +102,31 @@ class PBRoot(pb.Root):
##METHODS_PART##
class Bridge(object):
class bridge(object):
def __init__(self):
log.info("Init Perspective Broker...")
self.root = PBRoot()
conf = config.parseMainConf()
getConf = partial(config.getConf, conf, "bridge_pb", "")
conn_type = getConf("connection_type", "unix_socket")
conf = config.parse_main_conf()
get_conf = partial(config.get_conf, conf, "bridge_pb", "")
conn_type = get_conf("connection_type", "unix_socket")
if conn_type == "unix_socket":
local_dir = Path(config.getConfig(conf, "", "local_dir")).resolve()
local_dir = Path(config.config_get(conf, "", "local_dir")).resolve()
socket_path = local_dir / "bridge_pb"
log.info(f"using UNIX Socket at {socket_path}")
reactor.listenUNIX(
str(socket_path), pb.PBServerFactory(self.root), mode=0o600
)
elif conn_type == "socket":
port = int(getConf("port", 8789))
port = int(get_conf("port", 8789))
log.info(f"using TCP Socket at port {port}")
reactor.listenTCP(port, pb.PBServerFactory(self.root))
else:
raise ValueError(f"Unknown pb connection type: {conn_type!r}")
def sendSignal(self, name, *args, **kwargs):
self.root.sendSignal(name, args, kwargs)
def send_signal(self, name, *args, **kwargs):
self.root.send_signal(name, args, kwargs)
def remote_initBridge(self, signals_handler):
def remote_init_bridge(self, signals_handler):
self.signals_handlers.append(signals_handler)
log.info("registered signal handler")
@ -135,78 +135,78 @@ class Bridge(object):
setattr(self.root, "remote_" + name, callback)
#  self.root.register_method(name, callback)
def addMethod(
def add_method(
self, name, int_suffix, in_sign, out_sign, method, async_=False, doc={}
):
"""Dynamically add a method to PB Bridge"""
"""Dynamically add a method to PB bridge"""
# FIXME: doc parameter is kept only temporary, the time to remove it from calls
log.debug("Adding method {name} to PB bridge".format(name=name))
self.register_method(name, method)
def addSignal(self, name, int_suffix, signature, doc={}):
def add_signal(self, name, int_suffix, signature, doc={}):
log.debug("Adding signal {name} to PB bridge".format(name=name))
setattr(
self, name, lambda *args, **kwargs: self.sendSignal(name, *args, **kwargs)
self, name, lambda *args, **kwargs: self.send_signal(name, *args, **kwargs)
)
def bridgeDeactivateSignals(self):
def bridge_deactivate_signals(self):
"""Stop sending signals to bridge
Mainly used for mobile frontends, when the frontend is paused
"""
self.root._bridgeDeactivateSignals()
self.root._bridge_deactivate_signals()
def bridgeReactivateSignals(self):
def bridge_reactivate_signals(self):
"""Send again signals to bridge
Should only be used after bridgeDeactivateSignals has been called
Should only be used after bridge_deactivate_signals has been called
"""
self.root._bridgeReactivateSignals()
self.root._bridge_reactivate_signals()
def _debug(self, action, params, profile):
self.sendSignal("_debug", action, params, profile)
self.send_signal("_debug", action, params, profile)
def actionNew(self, action_data, id, security_limit, profile):
self.sendSignal("actionNew", action_data, id, security_limit, profile)
def action_new(self, action_data, id, security_limit, profile):
self.send_signal("action_new", action_data, id, security_limit, profile)
def connected(self, jid_s, profile):
self.sendSignal("connected", jid_s, profile)
self.send_signal("connected", jid_s, profile)
def contactDeleted(self, entity_jid, profile):
self.sendSignal("contactDeleted", entity_jid, profile)
def contact_deleted(self, entity_jid, profile):
self.send_signal("contact_deleted", entity_jid, profile)
def contact_new(self, contact_jid, attributes, groups, profile):
self.send_signal("contact_new", contact_jid, attributes, groups, profile)
def disconnected(self, profile):
self.sendSignal("disconnected", profile)
self.send_signal("disconnected", profile)
def entityDataUpdated(self, jid, name, value, profile):
self.sendSignal("entityDataUpdated", jid, name, value, profile)
def entity_data_updated(self, jid, name, value, profile):
self.send_signal("entity_data_updated", jid, name, value, profile)
def messageEncryptionStarted(self, to_jid, encryption_data, profile_key):
self.sendSignal("messageEncryptionStarted", to_jid, encryption_data, profile_key)
def message_encryption_started(self, to_jid, encryption_data, profile_key):
self.send_signal("message_encryption_started", to_jid, encryption_data, profile_key)
def messageEncryptionStopped(self, to_jid, encryption_data, profile_key):
self.sendSignal("messageEncryptionStopped", to_jid, encryption_data, profile_key)
def message_encryption_stopped(self, to_jid, encryption_data, profile_key):
self.send_signal("message_encryption_stopped", to_jid, encryption_data, profile_key)
def messageNew(self, uid, timestamp, from_jid, to_jid, message, subject, mess_type, extra, profile):
self.sendSignal("messageNew", uid, timestamp, from_jid, to_jid, message, subject, mess_type, extra, profile)
def message_new(self, uid, timestamp, from_jid, to_jid, message, subject, mess_type, extra, profile):
self.send_signal("message_new", uid, timestamp, from_jid, to_jid, message, subject, mess_type, extra, profile)
def newContact(self, contact_jid, attributes, groups, profile):
self.sendSignal("newContact", contact_jid, attributes, groups, profile)
def param_update(self, name, value, category, profile):
self.send_signal("param_update", name, value, category, profile)
def paramUpdate(self, name, value, category, profile):
self.sendSignal("paramUpdate", name, value, category, profile)
def presence_update(self, entity_jid, show, priority, statuses, profile):
self.send_signal("presence_update", entity_jid, show, priority, statuses, profile)
def presenceUpdate(self, entity_jid, show, priority, statuses, profile):
self.sendSignal("presenceUpdate", entity_jid, show, priority, statuses, profile)
def progress_error(self, id, error, profile):
self.send_signal("progress_error", id, error, profile)
def progressError(self, id, error, profile):
self.sendSignal("progressError", id, error, profile)
def progress_finished(self, id, metadata, profile):
self.send_signal("progress_finished", id, metadata, profile)
def progressFinished(self, id, metadata, profile):
self.sendSignal("progressFinished", id, metadata, profile)
def progressStarted(self, id, metadata, profile):
self.sendSignal("progressStarted", id, metadata, profile)
def progress_started(self, id, metadata, profile):
self.send_signal("progress_started", id, metadata, profile)
def subscribe(self, sub_type, entity_jid, profile):
self.sendSignal("subscribe", sub_type, entity_jid, profile)
self.send_signal("subscribe", sub_type, entity_jid, profile)

View file

@ -435,7 +435,7 @@ class Const(object):
return value.lower() in (cls.BOOL_TRUE, "1", "yes", "on")
@classmethod
def boolConst(cls, value: bool) -> str:
def bool_const(cls, value: bool) -> str:
"""@return (str): constant associated to bool value"""
assert isinstance(value, bool)
return cls.BOOL_TRUE if value else cls.BOOL_FALSE

View file

@ -30,7 +30,7 @@ try:
_ = gettext.translation("sat", "i18n", fallback=True).gettext
_translators = {None: gettext.NullTranslations()}
def languageSwitch(lang=None):
def language_switch(lang=None):
if not lang in _translators:
_translators[lang] = gettext.translation(
"sat", languages=[lang], fallback=True
@ -43,7 +43,7 @@ except ImportError:
log.warning("gettext support disabled")
_ = cast(Callable[[str], str], lambda msg: msg) # Libervia doesn't support gettext
def languageSwitch(lang=None):
def language_switch(lang=None):
pass

View file

@ -121,7 +121,7 @@ class Logger:
'levelname': level,
}
try:
if not self.filter_name.dictFilter(record):
if not self.filter_name.dict_filter(record):
raise Filtered
except (AttributeError, TypeError): # XXX: TypeError is here because of a pyjamas bug which need to be fixed (TypeError is raised instead of AttributeError)
if self.filter_name is not None:
@ -133,7 +133,7 @@ class Logger:
except KeyError as e:
if e.args[0] == 'profile':
# XXX: %(profile)s use some magic with introspection, for debugging purpose only *DO NOT* use in production
record['profile'] = configure_cls[backend].getProfile()
record['profile'] = configure_cls[backend].get_profile()
return self.fmt % record
else:
raise e
@ -174,7 +174,7 @@ class FilterName(object):
return 1
return 0
def dictFilter(self, dict_record):
def dict_filter(self, dict_record):
"""Filter using a dictionary record
@param dict_record: dictionary with at list a key "name" with logger name
@ -208,26 +208,26 @@ class ConfigureBase:
@param force_colors: if True ANSI colors are used even if stdout is not a tty
"""
self.backend_data = backend_data
self.preTreatment()
self.configureLevel(level)
self.configureFormat(fmt)
self.configureOutput(output)
self.configureLogger(logger)
self.configureColors(colors, force_colors, levels_taints_dict)
self.postTreatment()
self.updateCurrentLogger()
self.pre_treatment()
self.configure_level(level)
self.configure_format(fmt)
self.configure_output(output)
self.configure_logger(logger)
self.configure_colors(colors, force_colors, levels_taints_dict)
self.post_treatment()
self.update_current_logger()
def updateCurrentLogger(self):
def update_current_logger(self):
"""update existing logger to the class needed for this backend"""
if self.LOGGER_CLASS is None:
return
for name, logger in list(_loggers.items()):
_loggers[name] = self.LOGGER_CLASS(logger)
def preTreatment(self):
def pre_treatment(self):
pass
def configureLevel(self, level):
def configure_level(self, level):
if level is not None:
# we deactivate methods below level
level_idx = C.LOG_LEVELS.index(level)
@ -236,7 +236,7 @@ class ConfigureBase:
for _level in C.LOG_LEVELS[:level_idx]:
setattr(Logger, _level.lower(), dev_null)
def configureFormat(self, fmt):
def configure_format(self, fmt):
if fmt is not None:
if fmt != '%(message)s': # %(message)s is the same as None
Logger.fmt = fmt
@ -246,17 +246,17 @@ class ConfigureBase:
# color_start not followed by an end, we add it
Logger.fmt += COLOR_END
def configureOutput(self, output):
def configure_output(self, output):
if output is not None:
if output != C.LOG_OPT_OUTPUT_SEP + C.LOG_OPT_OUTPUT_DEFAULT:
# TODO: manage other outputs
raise NotImplementedError("Basic backend only manage default output yet")
def configureLogger(self, logger):
def configure_logger(self, logger):
if logger:
Logger.filter_name = FilterName(logger)
def configureColors(self, colors, force_colors, levels_taints_dict):
def configure_colors(self, colors, force_colors, levels_taints_dict):
if colors:
# if color are used, we need to handle levels_taints_dict
for level in list(levels_taints_dict.keys()):
@ -280,10 +280,10 @@ class ConfigureBase:
ansi_list.append(ansi)
taints[level] = ''.join(ansi_list)
def postTreatment(self):
def post_treatment(self):
pass
def manageOutputs(self, outputs_raw):
def manage_outputs(self, outputs_raw):
""" Parse output option in a backend agnostic way, and fill handlers consequently
@param outputs_raw: output option as enterred in environment variable or in configuration
@ -330,7 +330,7 @@ class ConfigureBase:
raise ValueError("options [{options}] are not supported for {handler} output".format(options=options, handler=output))
@staticmethod
def memoryGet(size=None):
def memory_get(size=None):
"""Return buffered logs
@param size: number of logs to return
@ -338,7 +338,7 @@ class ConfigureBase:
raise NotImplementedError
@classmethod
def ansiColors(cls, level, message):
def ansi_colors(cls, level, message):
"""Colorise message depending on level for terminals
@param level: one of C.LOG_LEVELS
@ -358,7 +358,7 @@ class ConfigureBase:
return '%s%s%s' % (start, message, A.RESET)
@staticmethod
def getProfile():
def get_profile():
"""Try to find profile value using introspection"""
raise NotImplementedError
@ -396,10 +396,10 @@ def configure(backend_, **options):
else:
configure_class(**options)
def memoryGet(size=None):
def memory_get(size=None):
if not C.LOG_OPT_OUTPUT_MEMORY in handlers:
raise ValueError('memory output is not used')
return configure_cls[backend].memoryGet(size)
return configure_cls[backend].memory_get(size)
def getLogger(name=C.LOG_BASE_LOGGER) -> Logger:
try:

View file

@ -47,8 +47,8 @@ class TwistedLogger(log.Logger):
class ConfigureBasic(log.ConfigureBase):
def configureColors(self, colors, force_colors, levels_taints_dict):
super(ConfigureBasic, self).configureColors(
def configure_colors(self, colors, force_colors, levels_taints_dict):
super(ConfigureBasic, self).configure_colors(
colors, force_colors, levels_taints_dict
)
if colors:
@ -61,14 +61,14 @@ class ConfigureBasic(log.ConfigureBase):
# FIXME: isatty should be tested on each handler, not globaly
if (force_colors or isatty):
# we need colors
log.Logger.post_treat = lambda logger, level, message: self.ansiColors(
log.Logger.post_treat = lambda logger, level, message: self.ansi_colors(
level, message
)
elif force_colors:
raise ValueError("force_colors can't be used if colors is False")
@staticmethod
def getProfile():
def get_profile():
"""Try to find profile value using introspection"""
import inspect
@ -107,7 +107,7 @@ class ConfigureBasic(log.ConfigureBase):
class ConfigureTwisted(ConfigureBasic):
LOGGER_CLASS = TwistedLogger
def preTreatment(self):
def pre_treatment(self):
from twisted import logger
global logger
self.level_map = {
@ -119,17 +119,17 @@ class ConfigureTwisted(ConfigureBasic):
}
self.LOGGER_CLASS.level_map = self.level_map
def configureLevel(self, level):
def configure_level(self, level):
self.level = self.level_map[level]
def configureOutput(self, output):
def configure_output(self, output):
import sys
from twisted.python import logfile
self.log_publisher = logger.LogPublisher()
if output is None:
output = C.LOG_OPT_OUTPUT_SEP + C.LOG_OPT_OUTPUT_DEFAULT
self.manageOutputs(output)
self.manage_outputs(output)
if C.LOG_OPT_OUTPUT_DEFAULT in log.handlers:
if self.backend_data is None:
@ -139,11 +139,11 @@ class ConfigureTwisted(ConfigureBasic):
options = self.backend_data
log_file = logfile.LogFile.fromFullPath(options['logfile'])
self.log_publisher.addObserver(
logger.FileLogObserver(log_file, self.textFormatter))
logger.FileLogObserver(log_file, self.text_formatter))
# we also want output to stdout if we are in debug or nodaemon mode
if options.get("nodaemon", False) or options.get("debug", False):
self.log_publisher.addObserver(
logger.FileLogObserver(sys.stdout, self.textFormatter))
logger.FileLogObserver(sys.stdout, self.text_formatter))
if C.LOG_OPT_OUTPUT_FILE in log.handlers:
@ -152,15 +152,15 @@ class ConfigureTwisted(ConfigureBasic):
sys.stdout if path == "-" else logfile.LogFile.fromFullPath(path)
)
self.log_publisher.addObserver(
logger.FileLogObserver(log_file, self.textFormatter))
logger.FileLogObserver(log_file, self.text_formatter))
if C.LOG_OPT_OUTPUT_MEMORY in log.handlers:
raise NotImplementedError(
"Memory observer is not implemented in Twisted backend"
)
def configureColors(self, colors, force_colors, levels_taints_dict):
super(ConfigureTwisted, self).configureColors(
def configure_colors(self, colors, force_colors, levels_taints_dict):
super(ConfigureTwisted, self).configure_colors(
colors, force_colors, levels_taints_dict
)
self.LOGGER_CLASS.colors = colors
@ -168,7 +168,7 @@ class ConfigureTwisted(ConfigureBasic):
if force_colors and not colors:
raise ValueError("colors must be True if force_colors is True")
def postTreatment(self):
def post_treatment(self):
"""Install twistedObserver which manage non SàT logs"""
# from twisted import logger
import sys
@ -180,7 +180,7 @@ class ConfigureTwisted(ConfigureBasic):
)
logger.globalLogBeginner.beginLoggingTo([filtering_obs])
def textFormatter(self, event):
def text_formatter(self, event):
if event.get('sat_logged', False):
timestamp = ''.join([logger.formatTime(event.get("log_time", None)), " "])
return f"{timestamp}{event.get('log_format', '')}\n"
@ -219,7 +219,7 @@ class ConfigureStandard(ConfigureBasic):
backend_data,
)
def preTreatment(self):
def pre_treatment(self):
"""We use logging methods directly, instead of using Logger"""
import logging
@ -230,13 +230,13 @@ class ConfigureStandard(ConfigureBasic):
log.error = logging.error
log.critical = logging.critical
def configureLevel(self, level):
def configure_level(self, level):
if level is None:
level = C.LOG_LVL_DEBUG
self.level = level
def configureFormat(self, fmt):
super(ConfigureStandard, self).configureFormat(fmt)
def configure_format(self, fmt):
super(ConfigureStandard, self).configure_format(fmt)
import logging
class SatFormatter(logging.Formatter):
@ -250,11 +250,11 @@ class ConfigureStandard(ConfigureBasic):
def format(self, record):
if self._with_profile:
record.profile = ConfigureStandard.getProfile()
record.profile = ConfigureStandard.get_profile()
do_color = self.with_colors and (self.can_colors or self.force_colors)
if ConfigureStandard._color_location:
# we copy raw formatting strings for color_*
# as formatting is handled in ansiColors in this case
# as formatting is handled in ansi_colors in this case
if do_color:
record.color_start = log.COLOR_START
record.color_end = log.COLOR_END
@ -262,19 +262,19 @@ class ConfigureStandard(ConfigureBasic):
record.color_start = record.color_end = ""
s = super(SatFormatter, self).format(record)
if do_color:
s = ConfigureStandard.ansiColors(record.levelname, s)
s = ConfigureStandard.ansi_colors(record.levelname, s)
return s
self.formatterClass = SatFormatter
def configureOutput(self, output):
self.manageOutputs(output)
def configure_output(self, output):
self.manage_outputs(output)
def configureLogger(self, logger):
def configure_logger(self, logger):
self.name_filter = log.FilterName(logger) if logger else None
def configureColors(self, colors, force_colors, levels_taints_dict):
super(ConfigureStandard, self).configureColors(
def configure_colors(self, colors, force_colors, levels_taints_dict):
super(ConfigureStandard, self).configure_colors(
colors, force_colors, levels_taints_dict
)
self.formatterClass.with_colors = colors
@ -282,14 +282,14 @@ class ConfigureStandard(ConfigureBasic):
if not colors and force_colors:
raise ValueError("force_colors can't be used if colors is False")
def _addHandler(self, root_logger, hdlr, can_colors=False):
def _add_handler(self, root_logger, hdlr, can_colors=False):
hdlr.setFormatter(self.formatterClass(can_colors))
root_logger.addHandler(hdlr)
root_logger.setLevel(self.level)
if self.name_filter is not None:
hdlr.addFilter(self.name_filter)
def postTreatment(self):
def post_treatment(self):
import logging
root_logger = logging.getLogger()
@ -301,7 +301,7 @@ class ConfigureStandard(ConfigureBasic):
can_colors = hdlr.stream.isatty()
except AttributeError:
can_colors = False
self._addHandler(root_logger, hdlr, can_colors=can_colors)
self._add_handler(root_logger, hdlr, can_colors=can_colors)
elif handler == C.LOG_OPT_OUTPUT_MEMORY:
from logging.handlers import BufferingHandler
@ -315,20 +315,20 @@ class ConfigureStandard(ConfigureBasic):
] = (
hdlr
) # we keep a reference to the handler to read the buffer later
self._addHandler(root_logger, hdlr, can_colors=False)
self._add_handler(root_logger, hdlr, can_colors=False)
elif handler == C.LOG_OPT_OUTPUT_FILE:
import os.path
for path in options:
hdlr = logging.FileHandler(os.path.expanduser(path))
self._addHandler(root_logger, hdlr, can_colors=False)
self._add_handler(root_logger, hdlr, can_colors=False)
else:
raise ValueError("Unknown handler type")
else:
root_logger.warning("Handlers already set on root logger")
@staticmethod
def memoryGet(size=None):
def memory_get(size=None):
"""Return buffered logs
@param size: number of logs to return
@ -355,7 +355,7 @@ def configure(backend, **options):
return log.configure(backend, **options)
def _parseOptions(options):
def _parse_options(options):
"""Parse string options as given in conf or environment variable, and return expected python value
@param options (dict): options with (key: name, value: string value)
@ -378,7 +378,7 @@ def _parseOptions(options):
options[LEVEL] = level
def satConfigure(backend=C.LOG_BACKEND_STANDARD, const=None, backend_data=None):
def sat_configure(backend=C.LOG_BACKEND_STANDARD, const=None, backend_data=None):
"""Configure logging system for SàT, can be used by frontends
logs conf is read in SàT conf, then in environment variables. It must be done before Memory init
@ -396,16 +396,16 @@ def satConfigure(backend=C.LOG_BACKEND_STANDARD, const=None, backend_data=None):
import os
log_conf = {}
sat_conf = config.parseMainConf()
sat_conf = config.parse_main_conf()
for opt_name, opt_default in C.LOG_OPTIONS():
try:
log_conf[opt_name] = os.environ[
"".join((C.ENV_PREFIX, C.LOG_OPT_PREFIX.upper(), opt_name.upper()))
]
except KeyError:
log_conf[opt_name] = config.getConfig(
log_conf[opt_name] = config.config_get(
sat_conf, C.LOG_OPT_SECTION, C.LOG_OPT_PREFIX + opt_name, opt_default
)
_parseOptions(log_conf)
_parse_options(log_conf)
configure(backend, backend_data=backend_data, **log_conf)

View file

@ -71,7 +71,7 @@ class XmlStream(xmlstream.XmlStream):
self._onElementHooks = []
self._sendHooks = []
def addHook(self, hook_type, callback):
def add_hook(self, hook_type, callback):
"""Add a send or receive hook"""
conflict_msg = f"Hook conflict: can't add {hook_type} hook {callback}"
if hook_type == C.STREAM_HOOK_RECEIVE:

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -45,9 +45,9 @@ class Cache(object):
if None, the cache will be common for all profiles
"""
self.profile = profile
path_elts = [host.memory.getConfig("", "local_dir"), C.CACHE_DIR]
path_elts = [host.memory.config_get("", "local_dir"), C.CACHE_DIR]
if profile:
path_elts.extend(["profiles", regex.pathEscape(profile)])
path_elts.extend(["profiles", regex.path_escape(profile)])
else:
path_elts.append("common")
self.cache_dir = Path(*path_elts)
@ -121,14 +121,14 @@ class Cache(object):
raise exceptions.DataError("Invalid char found")
return self.cache_dir / filename
def getMetadata(self, uid: str, update_eol: bool = True) -> Optional[Dict[str, Any]]:
def get_metadata(self, uid: str, update_eol: bool = True) -> Optional[Dict[str, Any]]:
"""Retrieve metadata for cached data
@param uid(unicode): unique identifier of file
@param update_eol(bool): True if eol must extended
if True, max_age will be added to eol (only if it is not already expired)
@return (dict, None): metadata with following keys:
see [cacheData] for data details, an additional "path" key is the full path to
see [cache_data] for data details, an additional "path" key is the full path to
cached file.
None if file is not in cache (or cache is invalid)
"""
@ -176,23 +176,23 @@ class Cache(object):
cache_data["path"] = self.getPath(cache_data["filename"])
return cache_data
def getFilePath(self, uid: str) -> Path:
def get_file_path(self, uid: str) -> Path:
"""Retrieve absolute path to file
@param uid(unicode): unique identifier of file
@return (unicode, None): absolute path to cached file
None if file is not in cache (or cache is invalid)
"""
metadata = self.getMetadata(uid)
metadata = self.get_metadata(uid)
if metadata is not None:
return metadata["path"]
def removeFromCache(self, uid, metadata=None):
def remove_from_cache(self, uid, metadata=None):
"""Remove data from cache
@param uid(unicode): unique identifier cache file
"""
cache_data = self.getMetadata(uid, update_eol=False)
cache_data = self.get_metadata(uid, update_eol=False)
if cache_data is None:
log.debug(f"cache with uid {uid!r} has already expired or been removed")
return
@ -215,7 +215,7 @@ class Cache(object):
cache_file.unlink()
log.debug(f"cache with uid {uid!r} has been removed")
def cacheData(
def cache_data(
self,
source: str,
uid: str,

View file

@ -47,7 +47,7 @@ class BlockCipher:
"""
if leave_empty and text == "":
return ""
iv = BlockCipher.getRandomKey()
iv = BlockCipher.get_random_key()
key = key.encode()
key = (
key[: BlockCipher.MAX_KEY_SIZE]
@ -91,7 +91,7 @@ class BlockCipher:
return BlockCipher.unpad(decrypted)
@staticmethod
def getRandomKey(size=None, base64=False):
def get_random_key(size=None, base64=False):
"""Return a random key suitable for block cipher encryption.
Note: a good value for the key length is to make it as long as the block size.

View file

@ -87,7 +87,7 @@ class HashManager(object):
return self.hashes.__contains__(hash_)
def load(self):
def fillHashes(hashes):
def fill_hashes(hashes):
for hash_, xml in hashes.items():
element = xml_tools.ElementParser()(xml)
disco_info = disco.DiscoInfo.fromElement(element)
@ -106,7 +106,7 @@ class HashManager(object):
log.info("Disco hashes loaded")
d = self.persistent.load()
d.addCallback(fillHashes)
d.addCallback(fill_hashes)
return d
@ -131,11 +131,11 @@ class Discovery(object):
@param node(unicode): optional node to use for disco request
@return: a Deferred which fire a boolean (True if feature is available)
"""
disco_infos = yield self.getInfos(client, jid_, node)
disco_infos = yield self.get_infos(client, jid_, node)
defer.returnValue(feature in disco_infos.features)
@defer.inlineCallbacks
def checkFeature(self, client, feature, jid_=None, node=""):
def check_feature(self, client, feature, jid_=None, node=""):
"""Like hasFeature, but raise an exception is feature is not Found
@param feature: feature namespace
@ -144,13 +144,13 @@ class Discovery(object):
@raise: exceptions.FeatureNotFound
"""
disco_infos = yield self.getInfos(client, jid_, node)
disco_infos = yield self.get_infos(client, jid_, node)
if not feature in disco_infos.features:
raise failure.Failure(exceptions.FeatureNotFound())
@defer.inlineCallbacks
def checkFeatures(self, client, features, jid_=None, identity=None, node=""):
"""Like checkFeature, but check several features at once, and check also identity
def check_features(self, client, features, jid_=None, identity=None, node=""):
"""Like check_feature, but check several features at once, and check also identity
@param features(iterable[unicode]): features to check
@param jid_(jid.JID): jid of the target, or None for profile's server
@ -159,14 +159,14 @@ class Discovery(object):
@raise: exceptions.FeatureNotFound
"""
disco_infos = yield self.getInfos(client, jid_, node)
disco_infos = yield self.get_infos(client, jid_, node)
if not set(features).issubset(disco_infos.features):
raise failure.Failure(exceptions.FeatureNotFound())
if identity is not None and identity not in disco_infos.identities:
raise failure.Failure(exceptions.FeatureNotFound())
async def hasIdentity(
async def has_identity(
self,
client: SatXMPPEntity,
category: str,
@ -182,10 +182,10 @@ class Discovery(object):
@param node(unicode): optional node to use for disco request
@return: True if the entity has the given identity
"""
disco_infos = await self.getInfos(client, jid_, node)
disco_infos = await self.get_infos(client, jid_, node)
return (category, type_) in disco_infos.identities
def getInfos(self, client, jid_=None, node="", use_cache=True):
def get_infos(self, client, jid_=None, node="", use_cache=True):
"""get disco infos from jid_, filling capability hash if needed
@param jid_: jid of the target, or None for profile's server
@ -199,13 +199,13 @@ class Discovery(object):
if not use_cache:
# we ignore cache, so we pretend we haven't found it
raise KeyError
cap_hash = self.host.memory.getEntityData(
cap_hash = self.host.memory.entity_data_get(
client, jid_, [C.ENTITY_CAP_HASH]
)[C.ENTITY_CAP_HASH]
except (KeyError, exceptions.UnknownEntityError):
# capability hash is not available, we'll compute one
def infosCb(disco_infos):
cap_hash = self.generateHash(disco_infos)
def infos_cb(disco_infos):
cap_hash = self.generate_hash(disco_infos)
for ext_form in disco_infos.extensions.values():
# wokkel doesn't call typeCheck on reception, so we do it here
# to avoid ending up with incorrect types. We have to do it after
@ -213,12 +213,12 @@ class Discovery(object):
# hash)
ext_form.typeCheck()
self.hashes[cap_hash] = disco_infos
self.host.memory.updateEntityData(
self.host.memory.update_entity_data(
client, jid_, C.ENTITY_CAP_HASH, cap_hash
)
return disco_infos
def infosEb(fail):
def infos_eb(fail):
if fail.check(defer.CancelledError):
reason = "request time-out"
fail = failure.Failure(exceptions.TimeOutError(str(fail.value)))
@ -236,21 +236,21 @@ class Discovery(object):
# XXX we set empty disco in cache, to avoid getting an error or waiting
# for a timeout again the next time
self.host.memory.updateEntityData(
self.host.memory.update_entity_data(
client, jid_, C.ENTITY_CAP_HASH, CAP_HASH_ERROR
)
raise fail
d = client.disco.requestInfo(jid_, nodeIdentifier=node)
d.addCallback(infosCb)
d.addErrback(infosEb)
d.addCallback(infos_cb)
d.addErrback(infos_eb)
return d
else:
disco_infos = self.hashes[cap_hash]
return defer.succeed(disco_infos)
@defer.inlineCallbacks
def getItems(self, client, jid_=None, node="", use_cache=True):
def get_items(self, client, jid_=None, node="", use_cache=True):
"""get disco items from jid_, cache them for our own server
@param jid_(jid.JID): jid of the target, or None for profile's server
@ -264,7 +264,7 @@ class Discovery(object):
if jid_ == client.server_jid and not node:
# we cache items only for our own server and if node is not set
try:
items = self.host.memory.getEntityData(
items = self.host.memory.entity_data_get(
client, jid_, ["DISCO_ITEMS"]
)["DISCO_ITEMS"]
log.debug("[%s] disco items are in cache" % jid_.full())
@ -274,7 +274,7 @@ class Discovery(object):
except (KeyError, exceptions.UnknownEntityError):
log.debug("Caching [%s] disco items" % jid_.full())
items = yield client.disco.requestItems(jid_, nodeIdentifier=node)
self.host.memory.updateEntityData(
self.host.memory.update_entity_data(
client, jid_, "DISCO_ITEMS", items
)
else:
@ -290,24 +290,24 @@ class Discovery(object):
defer.returnValue(items)
def _infosEb(self, failure_, entity_jid):
def _infos_eb(self, failure_, entity_jid):
failure_.trap(StanzaError)
log.warning(
_("Error while requesting [%(jid)s]: %(error)s")
% {"jid": entity_jid.full(), "error": failure_.getErrorMessage()}
)
def findServiceEntity(self, client, category, type_, jid_=None):
"""Helper method to find first available entity from findServiceEntities
def find_service_entity(self, client, category, type_, jid_=None):
"""Helper method to find first available entity from find_service_entities
args are the same as for [findServiceEntities]
args are the same as for [find_service_entities]
@return (jid.JID, None): found entity
"""
d = self.host.findServiceEntities(client, category, type_)
d = self.host.find_service_entities(client, category, type_)
d.addCallback(lambda entities: entities.pop() if entities else None)
return d
def findServiceEntities(self, client, category, type_, jid_=None):
def find_service_entities(self, client, category, type_, jid_=None):
"""Return all available items of an entity which correspond to (category, type_)
@param category: identity's category
@ -318,29 +318,29 @@ class Discovery(object):
"""
found_entities = set()
def infosCb(infos, entity_jid):
def infos_cb(infos, entity_jid):
if (category, type_) in infos.identities:
found_entities.add(entity_jid)
def gotItems(items):
def got_items(items):
defers_list = []
for item in items:
info_d = self.getInfos(client, item.entity)
info_d = self.get_infos(client, item.entity)
info_d.addCallbacks(
infosCb, self._infosEb, [item.entity], None, [item.entity]
infos_cb, self._infos_eb, [item.entity], None, [item.entity]
)
defers_list.append(info_d)
return defer.DeferredList(defers_list)
d = self.getItems(client, jid_)
d.addCallback(gotItems)
d = self.get_items(client, jid_)
d.addCallback(got_items)
d.addCallback(lambda __: found_entities)
reactor.callLater(
TIMEOUT, d.cancel
) # FIXME: one bad service make a general timeout
return d
def findFeaturesSet(self, client, features, identity=None, jid_=None):
def find_features_set(self, client, features, identity=None, jid_=None):
"""Return entities (including jid_ and its items) offering features
@param features: iterable of features which must be present
@ -355,7 +355,7 @@ class Discovery(object):
features = set(features)
found_entities = set()
def infosCb(infos, entity):
def infos_cb(infos, entity):
if entity is None:
log.warning(_("received an item without jid"))
return
@ -364,23 +364,23 @@ class Discovery(object):
if features.issubset(infos.features):
found_entities.add(entity)
def gotItems(items):
def got_items(items):
defer_list = []
for entity in [jid_] + [item.entity for item in items]:
infos_d = self.getInfos(client, entity)
infos_d.addCallbacks(infosCb, self._infosEb, [entity], None, [entity])
infos_d = self.get_infos(client, entity)
infos_d.addCallbacks(infos_cb, self._infos_eb, [entity], None, [entity])
defer_list.append(infos_d)
return defer.DeferredList(defer_list)
d = self.getItems(client, jid_)
d.addCallback(gotItems)
d = self.get_items(client, jid_)
d.addCallback(got_items)
d.addCallback(lambda __: found_entities)
reactor.callLater(
TIMEOUT, d.cancel
) # FIXME: one bad service make a general timeout
return d
def generateHash(self, services):
def generate_hash(self, services):
""" Generate a unique hash for given service
hash algorithm is the one described in XEP-0115
@ -433,7 +433,7 @@ class Discovery(object):
return cap_hash
@defer.inlineCallbacks
def _discoInfos(
def _disco_infos(
self, entity_jid_s, node="", use_cache=True, profile_key=C.PROF_KEY_NONE
):
"""Discovery method for the bridge
@ -443,9 +443,9 @@ class Discovery(object):
@return: list of tuples
"""
client = self.host.getClient(profile_key)
client = self.host.get_client(profile_key)
entity = jid.JID(entity_jid_s)
disco_infos = yield self.getInfos(client, entity, node, use_cache)
disco_infos = yield self.get_infos(client, entity, node, use_cache)
extensions = {}
# FIXME: should extensions be serialised using tools.common.data_format?
for form_type, form in list(disco_infos.extensions.items()):
@ -459,7 +459,7 @@ class Discovery(object):
values = [field.value] if field.value is not None else field.values
if field.fieldType == "boolean":
values = [C.boolConst(v) for v in values]
values = [C.bool_const(v) for v in values]
fields.append((data, values))
extensions[form_type or ""] = fields
@ -483,7 +483,7 @@ class Discovery(object):
yield (item.entity.full(), item.nodeIdentifier or "", item.name or "")
@defer.inlineCallbacks
def _discoItems(
def _disco_items(
self, entity_jid_s, node="", use_cache=True, profile_key=C.PROF_KEY_NONE
):
""" Discovery method for the bridge
@ -492,8 +492,8 @@ class Discovery(object):
@param node(unicode): optional node to use
@param use_cache(bool): if True, use cached data if available
@return: list of tuples"""
client = self.host.getClient(profile_key)
client = self.host.get_client(profile_key)
entity = jid.JID(entity_jid_s)
disco_items = yield self.getItems(client, entity, node, use_cache)
disco_items = yield self.get_items(client, entity, node, use_cache)
ret = list(self.items2tuples(disco_items))
defer.returnValue(ret)

View file

@ -50,7 +50,7 @@ class EncryptionHandler:
def host(self):
return self.client.host_app
async def loadSessions(self):
async def load_sessions(self):
"""Load persistent sessions"""
await self._stored_session.load()
start_d_list = []
@ -69,18 +69,18 @@ class EncryptionHandler:
log.info(_("encryption sessions restored"))
@classmethod
def registerPlugin(cls, plg_instance, name, namespace, priority=0, directed=False):
def register_plugin(cls, plg_instance, name, namespace, priority=0, directed=False):
"""Register a plugin handling an encryption algorithm
@param plg_instance(object): instance of the plugin
it must have the following methods:
- getTrustUI(entity): return a XMLUI for trust management
- get_trust_ui(entity): return a XMLUI for trust management
entity(jid.JID): entity to manage
The returned XMLUI must be a form
if may have the following methods:
- startEncryption(entity): start encrypted session
- start_encryption(entity): start encrypted session
entity(jid.JID): entity to start encrypted session with
- stopEncryption(entity): start encrypted session
- stop_encryption(entity): start encrypted session
entity(jid.JID): entity to stop encrypted session with
if they don't exists, those 2 methods will be ignored.
@ -115,7 +115,7 @@ class EncryptionHandler:
return cls.plugins
@classmethod
def getPlugin(cls, namespace):
def get_plugin(cls, namespace):
try:
return next(p for p in cls.plugins if p.namespace == namespace)
except StopIteration:
@ -124,12 +124,12 @@ class EncryptionHandler:
namespace=namespace))
@classmethod
def getNamespaces(cls):
def get_namespaces(cls):
"""Get available plugin namespaces"""
return {p.namespace for p in cls.getPlugins()}
@classmethod
def getNSFromName(cls, name):
def get_ns_from_name(cls, name):
"""Retrieve plugin namespace from its name
@param name(unicode): name of the plugin (case insensitive)
@ -143,7 +143,7 @@ class EncryptionHandler:
"Can't find a plugin with the name \"{name}\".".format(
name=name)))
def getBridgeData(self, session):
def get_bridge_data(self, session):
"""Retrieve session data serialized for bridge.
@param session(dict): encryption session
@ -159,7 +159,7 @@ class EncryptionHandler:
return data_format.serialise(bridge_data)
async def _startEncryption(self, plugin, entity):
async def _start_encryption(self, plugin, entity):
"""Start encryption with a plugin
This method must be called just before adding a plugin session.
@ -168,14 +168,14 @@ class EncryptionHandler:
if not plugin.directed:
await self._stored_session.aset(entity.userhost(), plugin.namespace)
try:
start_encryption = plugin.instance.startEncryption
start_encryption = plugin.instance.start_encryption
except AttributeError:
log.debug(f"No startEncryption method found for {plugin.namespace}")
log.debug(f"No start_encryption method found for {plugin.namespace}")
else:
# we copy entity to avoid having the resource changed by stop_encryption
await utils.asDeferred(start_encryption, self.client, copy.copy(entity))
await utils.as_deferred(start_encryption, self.client, copy.copy(entity))
async def _stopEncryption(self, plugin, entity):
async def _stop_encryption(self, plugin, entity):
"""Stop encryption with a plugin
This method must be called just before removing a plugin session.
@ -186,12 +186,12 @@ class EncryptionHandler:
except KeyError:
pass
try:
stop_encryption = plugin.instance.stopEncryption
stop_encryption = plugin.instance.stop_encryption
except AttributeError:
log.debug(f"No stopEncryption method found for {plugin.namespace}")
log.debug(f"No stop_encryption method found for {plugin.namespace}")
else:
# we copy entity to avoid having the resource changed by stop_encryption
return utils.asDeferred(stop_encryption, self.client, copy.copy(entity))
return utils.as_deferred(stop_encryption, self.client, copy.copy(entity))
async def start(self, entity, namespace=None, replace=False):
"""Start an encryption session with an entity
@ -211,7 +211,7 @@ class EncryptionHandler:
if namespace is None:
plugin = self.plugins[0]
else:
plugin = self.getPlugin(namespace)
plugin = self.get_plugin(namespace)
bare_jid = entity.userhostJID()
if bare_jid in self._sessions:
@ -227,7 +227,7 @@ class EncryptionHandler:
# there is a conflict, but replacement is requested
# so we stop previous encryption to use new one
del self._sessions[bare_jid]
await self._stopEncryption(former_plugin, entity)
await self._stop_encryption(former_plugin, entity)
else:
msg = (_("Session with {bare_jid} is already encrypted with {name}. "
"Please stop encryption session before changing algorithm.")
@ -238,7 +238,7 @@ class EncryptionHandler:
data = {"plugin": plugin}
if plugin.directed:
if not entity.resource:
entity.resource = self.host.memory.getMainResource(self.client, entity)
entity.resource = self.host.memory.main_resource_get(self.client, entity)
if not entity.resource:
raise exceptions.NotFound(
_("No resource found for {destinee}, can't encrypt with {name}")
@ -251,14 +251,14 @@ class EncryptionHandler:
elif entity.resource:
raise ValueError(_("{name} encryption must be used with bare jids."))
await self._startEncryption(plugin, entity)
await self._start_encryption(plugin, entity)
self._sessions[entity.userhostJID()] = data
log.info(_("Encryption session has been set for {entity_jid} with "
"{encryption_name}").format(
entity_jid=entity.full(), encryption_name=plugin.name))
self.host.bridge.messageEncryptionStarted(
self.host.bridge.message_encryption_started(
entity.full(),
self.getBridgeData(data),
self.get_bridge_data(data),
self.client.profile)
msg = D_("Encryption session started: your messages with {destinee} are "
"now end to end encrypted using {name} algorithm.").format(
@ -312,16 +312,16 @@ class EncryptionHandler:
# we stop the whole session
# see comment below for deleting session before stopping encryption
del self._sessions[entity.userhostJID()]
await self._stopEncryption(plugin, entity)
await self._stop_encryption(plugin, entity)
else:
# plugin's stopEncryption may call stop again (that's the case with OTR)
# so we need to remove plugin from session before calling self._stopEncryption
# plugin's stop_encryption may call stop again (that's the case with OTR)
# so we need to remove plugin from session before calling self._stop_encryption
del self._sessions[entity.userhostJID()]
await self._stopEncryption(plugin, entity)
await self._stop_encryption(plugin, entity)
log.info(_("encryption session stopped with entity {entity}").format(
entity=entity.full()))
self.host.bridge.messageEncryptionStopped(
self.host.bridge.message_encryption_stopped(
entity.full(),
{'name': plugin.name,
'namespace': plugin.namespace,
@ -358,7 +358,7 @@ class EncryptionHandler:
return None
return session["plugin"].namespace
def getTrustUI(self, entity_jid, namespace=None):
def get_trust_ui(self, entity_jid, namespace=None):
"""Retrieve encryption UI
@param entity_jid(jid.JID): get the UI for this entity
@ -379,53 +379,53 @@ class EncryptionHandler:
.format(entity_jid=entity_jid.full()))
plugin = session['plugin']
else:
plugin = self.getPlugin(namespace)
plugin = self.get_plugin(namespace)
try:
get_trust_ui = plugin.instance.getTrustUI
get_trust_ui = plugin.instance.get_trust_ui
except AttributeError:
raise NotImplementedError(
"Encryption plugin doesn't handle trust management UI")
else:
return utils.asDeferred(get_trust_ui, self.client, entity_jid)
return utils.as_deferred(get_trust_ui, self.client, entity_jid)
## Menus ##
@classmethod
def _importMenus(cls, host):
host.importMenu(
def _import_menus(cls, host):
host.import_menu(
(D_("Encryption"), D_("unencrypted (plain text)")),
partial(cls._onMenuUnencrypted, host=host),
partial(cls._on_menu_unencrypted, host=host),
security_limit=0,
help_string=D_("End encrypted session"),
type_=C.MENU_SINGLE,
)
for plg in cls.getPlugins():
host.importMenu(
host.import_menu(
(D_("Encryption"), plg.name),
partial(cls._onMenuName, host=host, plg=plg),
partial(cls._on_menu_name, host=host, plg=plg),
security_limit=0,
help_string=D_("Start {name} session").format(name=plg.name),
type_=C.MENU_SINGLE,
)
host.importMenu(
host.import_menu(
(D_("Encryption"), D_("⛨ {name} trust").format(name=plg.name)),
partial(cls._onMenuTrust, host=host, plg=plg),
partial(cls._on_menu_trust, host=host, plg=plg),
security_limit=0,
help_string=D_("Manage {name} trust").format(name=plg.name),
type_=C.MENU_SINGLE,
)
@classmethod
def _onMenuUnencrypted(cls, data, host, profile):
client = host.getClient(profile)
def _on_menu_unencrypted(cls, data, host, profile):
client = host.get_client(profile)
peer_jid = jid.JID(data['jid']).userhostJID()
d = defer.ensureDeferred(client.encryption.stop(peer_jid))
d.addCallback(lambda __: {})
return d
@classmethod
def _onMenuName(cls, data, host, plg, profile):
client = host.getClient(profile)
def _on_menu_name(cls, data, host, plg, profile):
client = host.get_client(profile)
peer_jid = jid.JID(data['jid'])
if not plg.directed:
peer_jid = peer_jid.userhostJID()
@ -436,15 +436,15 @@ class EncryptionHandler:
@classmethod
@defer.inlineCallbacks
def _onMenuTrust(cls, data, host, plg, profile):
client = host.getClient(profile)
def _on_menu_trust(cls, data, host, plg, profile):
client = host.get_client(profile)
peer_jid = jid.JID(data['jid']).userhostJID()
ui = yield client.encryption.getTrustUI(peer_jid, plg.namespace)
ui = yield client.encryption.get_trust_ui(peer_jid, plg.namespace)
defer.returnValue({'xmlui': ui.toXml()})
## Triggers ##
def setEncryptionFlag(self, mess_data):
def set_encryption_flag(self, mess_data):
"""Set "encryption" key in mess_data if session with destinee is encrypted"""
to_jid = mess_data['to']
encryption = self._sessions.get(to_jid.userhostJID())
@ -455,11 +455,11 @@ class EncryptionHandler:
f"encryption flag must not be set for groupchat if encryption algorithm "
f"({encryption['plugin'].name}) is directed!")
mess_data[C.MESS_KEY_ENCRYPTION] = encryption
self.markAsEncrypted(mess_data, plugin.namespace)
self.mark_as_encrypted(mess_data, plugin.namespace)
## Misc ##
def markAsEncrypted(self, mess_data, namespace):
def mark_as_encrypted(self, mess_data, namespace):
"""Helper method to mark a message as having been e2e encrypted.
This should be used in the post_treat workflow of messageReceived trigger of
@ -483,7 +483,7 @@ class EncryptionHandler:
return mess_data
def isEncryptionRequested(
def is_encryption_requested(
self,
mess_data: MessageData,
namespace: Optional[str] = None
@ -513,7 +513,7 @@ class EncryptionHandler:
return mess_data['extra'].get(C.MESS_KEY_ENCRYPTED, False)
def markAsTrusted(self, mess_data):
def mark_as_trusted(self, mess_data):
"""Helper methor to mark a message as sent from a trusted entity.
This should be used in the post_treat workflow of messageReceived trigger of
@ -523,7 +523,7 @@ class EncryptionHandler:
mess_data[C.MESS_KEY_TRUSTED] = True
return mess_data
def markAsUntrusted(self, mess_data):
def mark_as_untrusted(self, mess_data):
"""Helper methor to mark a message as sent from an untrusted entity.
This should be used in the post_treat workflow of messageReceived trigger of

File diff suppressed because it is too large Load diff

View file

@ -38,7 +38,7 @@ def run_migrations_offline():
script output.
"""
db_config = sqla_config.getDbConfig()
db_config = sqla_config.get_db_config()
context.configure(
url=db_config["url"],
target_metadata=target_metadata,
@ -76,7 +76,7 @@ async def run_migrations_online():
and associate a connection with the context.
"""
db_config = sqla_config.getDbConfig()
db_config = sqla_config.get_db_config()
engine = create_async_engine(
db_config["url"],
poolclass=pool.NullPool,

View file

@ -29,7 +29,7 @@ from twisted.internet import defer
from twisted.python.failure import Failure
from twisted.words.xish import domish
from twisted.words.protocols.jabber import jid
from sat.tools.xml_tools import paramsXML2XMLUI, getText
from sat.tools.xml_tools import params_xml_2_xmlui, get_text
from sat.tools.common import data_format
from xml.sax.saxutils import quoteattr
@ -38,7 +38,7 @@ from xml.sax.saxutils import quoteattr
# this need an overall simplification to make maintenance easier
def createJidElts(jids):
def create_jid_elts(jids):
"""Generator which return <jid/> elements from jids
@param jids(iterable[id.jID]): jids to use
@ -101,18 +101,18 @@ class Params(object):
def load_default_params(self):
self.dom = minidom.parseString(Params.default_xml.encode("utf-8"))
def _mergeParams(self, source_node, dest_node):
def _merge_params(self, source_node, dest_node):
"""Look for every node in source_node and recursively copy them to dest if they don't exists"""
def getNodesMap(children):
def get_nodes_map(children):
ret = {}
for child in children:
if child.nodeType == child.ELEMENT_NODE:
ret[(child.tagName, child.getAttribute("name"))] = child
return ret
source_map = getNodesMap(source_node.childNodes)
dest_map = getNodesMap(dest_node.childNodes)
source_map = get_nodes_map(source_node.childNodes)
dest_map = get_nodes_map(dest_node.childNodes)
source_set = set(source_map.keys())
dest_set = set(dest_map.keys())
to_add = source_set.difference(dest_set)
@ -122,22 +122,22 @@ class Params(object):
to_recurse = source_set - to_add
for node_key in to_recurse:
self._mergeParams(source_map[node_key], dest_map[node_key])
self._merge_params(source_map[node_key], dest_map[node_key])
def load_xml(self, xml_file):
"""Load parameters template from xml file"""
self.dom = minidom.parse(xml_file)
default_dom = minidom.parseString(Params.default_xml.encode("utf-8"))
self._mergeParams(default_dom.documentElement, self.dom.documentElement)
self._merge_params(default_dom.documentElement, self.dom.documentElement)
def loadGenParams(self):
def load_gen_params(self):
"""Load general parameters data from storage
@return: deferred triggered once params are loaded
"""
return self.storage.loadGenParams(self.params_gen)
return self.storage.load_gen_params(self.params_gen)
def loadIndParams(self, profile, cache=None):
def load_ind_params(self, profile, cache=None):
"""Load individual parameters
set self.params cache or a temporary cache
@ -147,11 +147,11 @@ class Params(object):
"""
if cache is None:
self.params[profile] = {}
return self.storage.loadIndParams(
return self.storage.load_ind_params(
self.params[profile] if cache is None else cache, profile
)
def purgeProfile(self, profile):
def purge_profile(self, profile):
"""Remove cache data of a profile
@param profile: %(doc_profile)s
@ -176,7 +176,7 @@ class Params(object):
self.params = {}
self.params_gen = {}
def createProfile(self, profile, component):
def create_profile(self, profile, component):
"""Create a new profile
@param profile(unicode): name of the profile
@ -184,14 +184,14 @@ class Params(object):
@param callback: called when the profile actually exists in database and memory
@return: a Deferred instance
"""
if self.storage.hasProfile(profile):
if self.storage.has_profile(profile):
log.info(_("The profile name already exists"))
return defer.fail(exceptions.ConflictError())
if not self.host.trigger.point("ProfileCreation", profile):
return defer.fail(exceptions.CancelError())
return self.storage.createProfile(profile, component or None)
return self.storage.create_profile(profile, component or None)
def asyncDeleteProfile(self, profile, force=False):
def profile_delete_async(self, profile, force=False):
"""Delete an existing profile
@param profile: name of the profile
@ -199,18 +199,18 @@ class Params(object):
To be used for direct calls only (not through the bridge).
@return: a Deferred instance
"""
if not self.storage.hasProfile(profile):
if not self.storage.has_profile(profile):
log.info(_("Trying to delete an unknown profile"))
return defer.fail(Failure(exceptions.ProfileUnknownError(profile)))
if self.host.isConnected(profile):
if self.host.is_connected(profile):
if force:
self.host.disconnect(profile)
else:
log.info(_("Trying to delete a connected profile"))
return defer.fail(Failure(exceptions.ProfileConnected))
return self.storage.deleteProfile(profile)
return self.storage.delete_profile(profile)
def getProfileName(self, profile_key, return_profile_keys=False):
def get_profile_name(self, profile_key, return_profile_keys=False):
"""return profile according to profile_key
@param profile_key: profile name or key which can be
@ -229,7 +229,7 @@ class Params(object):
try:
default = self.host.memory.memory_data[
"Profile_default"
] = self.storage.getProfilesList()[0]
] = self.storage.get_profiles_list()[0]
except IndexError:
log.info(_("No profile exist yet"))
raise exceptions.ProfileUnknownError(profile_key)
@ -240,7 +240,7 @@ class Params(object):
raise exceptions.ProfileNotSetError
elif return_profile_keys and profile_key in [C.PROF_KEY_ALL]:
return profile_key # this value must be managed by the caller
if not self.storage.hasProfile(profile_key):
if not self.storage.has_profile(profile_key):
log.error(_("Trying to access an unknown profile (%s)") % profile_key)
raise exceptions.ProfileUnknownError(profile_key)
return profile_key
@ -260,7 +260,7 @@ class Params(object):
# the node is new
return None
def updateParams(self, xml, security_limit=C.NO_SECURITY_LIMIT, app=""):
def update_params(self, xml, security_limit=C.NO_SECURITY_LIMIT, app=""):
"""import xml in parameters, update if the param already exists
If security_limit is specified and greater than -1, the parameters
@ -287,7 +287,7 @@ class Params(object):
0
) # count the params to be removed from current category
for node in cat_node.childNodes:
if node.nodeName != "param" or not self.checkSecurityLimit(
if node.nodeName != "param" or not self.check_security_limit(
node, security_limit
):
to_remove.append(node)
@ -324,7 +324,7 @@ class Params(object):
pre_process_app_node(src_parent, security_limit, app)
import_node(self.dom.documentElement, src_parent)
def paramsRegisterApp(self, xml, security_limit, app):
def params_register_app(self, xml, security_limit, app):
"""Register frontend's specific parameters
If security_limit is specified and greater than -1, the parameters
@ -351,12 +351,12 @@ class Params(object):
)
return
self.frontends_cache.append(app)
self.updateParams(xml, security_limit, app)
self.update_params(xml, security_limit, app)
log.debug("Frontends parameters registered for %(app)s" % {"app": app})
def __default_ok(self, value, name, category):
# FIXME: will not work with individual parameters
self.setParam(name, value, category)
self.param_set(name, value, category)
def __default_ko(self, failure, name, category):
log.error(
@ -364,7 +364,7 @@ class Params(object):
% {"category": category, "name": name, "reason": str(failure.value)}
)
def setDefault(self, name, category, callback, errback=None):
def set_default(self, name, category, callback, errback=None):
"""Set default value of parameter
'default_cb' attibute of parameter must be set to 'yes'
@ -376,10 +376,10 @@ class Params(object):
# TODO: send signal param update if value changed
# TODO: manage individual paramaters
log.debug(
"setDefault called for %(category)s/%(name)s"
"set_default called for %(category)s/%(name)s"
% {"category": category, "name": name}
)
node = self._getParamNode(name, category, "@ALL@")
node = self._get_param_node(name, category, "@ALL@")
if not node:
log.error(
_(
@ -390,15 +390,15 @@ class Params(object):
return
if node[1].getAttribute("default_cb") == "yes":
# del node[1].attributes['default_cb'] # default_cb is not used anymore as a flag to know if we have to set the default value,
# and we can still use it later e.g. to call a generic setDefault method
value = self._getParam(category, name, C.GENERAL)
# and we can still use it later e.g. to call a generic set_default method
value = self._get_param(category, name, C.GENERAL)
if value is None: # no value set by the user: we have the default value
log.debug("Default value to set, using callback")
d = defer.maybeDeferred(callback)
d.addCallback(self.__default_ok, name, category)
d.addErrback(errback or self.__default_ko, name, category)
def _getAttr_internal(self, node, attr, value):
def _get_attr_internal(self, node, attr, value):
"""Get attribute value.
/!\ This method would return encrypted password values.
@ -464,7 +464,7 @@ class Params(object):
"\t"
) # FIXME: it's not good to use tabs as separator !
else: # no user defined value, take default value from the XML
jids = [getText(jid_) for jid_ in node.getElementsByTagName("jid")]
jids = [get_text(jid_) for jid_ in node.getElementsByTagName("jid")]
to_delete = []
for idx, value in enumerate(jids):
try:
@ -480,7 +480,7 @@ class Params(object):
return value_to_use
return node.getAttribute(attr)
def _getAttr(self, node, attr, value):
def _get_attr(self, node, attr, value):
"""Get attribute value (synchronous).
/!\ This method can not be used to retrieve password values.
@ -491,11 +491,11 @@ class Params(object):
"""
if attr == "value" and node.getAttribute("type") == "password":
raise exceptions.InternalError(
"To retrieve password values, use _asyncGetAttr instead of _getAttr"
"To retrieve password values, use _async_get_attr instead of _get_attr"
)
return self._getAttr_internal(node, attr, value)
return self._get_attr_internal(node, attr, value)
def _asyncGetAttr(self, node, attr, value, profile=None):
def _async_get_attr(self, node, attr, value, profile=None):
"""Get attribute value.
Profile passwords are returned hashed (if not empty),
@ -506,7 +506,7 @@ class Params(object):
@param profile: %(doc_profile)s
@return (unicode, bool, int, list): Deferred value to retrieve
"""
value = self._getAttr_internal(node, attr, value)
value = self._get_attr_internal(node, attr, value)
if attr != "value" or node.getAttribute("type") != "password":
return defer.succeed(value)
param_cat = node.parentNode.getAttribute("name")
@ -519,7 +519,7 @@ class Params(object):
raise exceptions.ProfileNotSetError(
"The profile is needed to decrypt a password"
)
password = self.host.memory.decryptValue(value, profile)
password = self.host.memory.decrypt_value(value, profile)
if password is None:
raise exceptions.InternalError("password should never be None")
@ -528,25 +528,25 @@ class Params(object):
def _type_to_str(self, result):
"""Convert result to string, according to its type """
if isinstance(result, bool):
return C.boolConst(result)
return C.bool_const(result)
elif isinstance(result, (list, set, tuple)):
return ', '.join(self._type_to_str(r) for r in result)
else:
return str(result)
def getStringParamA(self, name, category, attr="value", profile_key=C.PROF_KEY_NONE):
""" Same as getParamA but for bridge: convert non string value to string """
def get_string_param_a(self, name, category, attr="value", profile_key=C.PROF_KEY_NONE):
""" Same as param_get_a but for bridge: convert non string value to string """
return self._type_to_str(
self.getParamA(name, category, attr, profile_key=profile_key)
self.param_get_a(name, category, attr, profile_key=profile_key)
)
def getParamA(
def param_get_a(
self, name, category, attr="value", use_default=True, profile_key=C.PROF_KEY_NONE
):
"""Helper method to get a specific attribute.
/!\ This method would return encrypted password values,
to get the plain values you have to use asyncGetParamA.
to get the plain values you have to use param_get_a_async.
@param name: name of the parameter
@param category: category of the parameter
@param attr: name of the attribute (default: "value")
@ -557,7 +557,7 @@ class Params(object):
"""
# FIXME: looks really dirty and buggy, need to be reviewed/refactored
# FIXME: security_limit is not managed here !
node = self._getParamNode(name, category)
node = self._get_param_node(name, category)
if not node:
log.error(
_(
@ -569,18 +569,18 @@ class Params(object):
if attr == "value" and node[1].getAttribute("type") == "password":
raise exceptions.InternalError(
"To retrieve password values, use asyncGetParamA instead of getParamA"
"To retrieve password values, use param_get_a_async instead of param_get_a"
)
if node[0] == C.GENERAL:
value = self._getParam(category, name, C.GENERAL)
value = self._get_param(category, name, C.GENERAL)
if value is None and attr == "value" and not use_default:
return value
return self._getAttr(node[1], attr, value)
return self._get_attr(node[1], attr, value)
assert node[0] == C.INDIVIDUAL
profile = self.getProfileName(profile_key)
profile = self.get_profile_name(profile_key)
if not profile:
log.error(_("Requesting a param for an non-existant profile"))
raise exceptions.ProfileUnknownError(profile_key)
@ -590,19 +590,19 @@ class Params(object):
raise exceptions.ProfileNotConnected(profile)
if attr == "value":
value = self._getParam(category, name, profile=profile)
value = self._get_param(category, name, profile=profile)
if value is None and attr == "value" and not use_default:
return value
return self._getAttr(node[1], attr, value)
return self._get_attr(node[1], attr, value)
async def asyncGetStringParamA(
async def async_get_string_param_a(
self, name, category, attr="value", security_limit=C.NO_SECURITY_LIMIT,
profile=C.PROF_KEY_NONE):
value = await self.asyncGetParamA(
value = await self.param_get_a_async(
name, category, attr, security_limit, profile_key=profile)
return self._type_to_str(value)
def asyncGetParamA(
def param_get_a_async(
self,
name,
category,
@ -618,7 +618,7 @@ class Params(object):
@param profile: owner of the param (@ALL@ for everyone)
@return (defer.Deferred): parameter value, with corresponding type (bool, int, list, etc)
"""
node = self._getParamNode(name, category)
node = self._get_param_node(name, category)
if not node:
log.error(
_(
@ -628,7 +628,7 @@ class Params(object):
)
raise ValueError("Requested param doesn't exist")
if not self.checkSecurityLimit(node[1], security_limit):
if not self.check_security_limit(node[1], security_limit):
log.warning(
_(
"Trying to get parameter '%(param)s' in category '%(cat)s' without authorization!!!"
@ -638,12 +638,12 @@ class Params(object):
raise exceptions.PermissionError
if node[0] == C.GENERAL:
value = self._getParam(category, name, C.GENERAL)
return self._asyncGetAttr(node[1], attr, value)
value = self._get_param(category, name, C.GENERAL)
return self._async_get_attr(node[1], attr, value)
assert node[0] == C.INDIVIDUAL
profile = self.getProfileName(profile_key)
profile = self.get_profile_name(profile_key)
if not profile:
raise exceptions.InternalError(
_("Requesting a param for a non-existant profile")
@ -652,23 +652,23 @@ class Params(object):
if attr != "value":
return defer.succeed(node[1].getAttribute(attr))
try:
value = self._getParam(category, name, profile=profile)
return self._asyncGetAttr(node[1], attr, value, profile)
value = self._get_param(category, name, profile=profile)
return self._async_get_attr(node[1], attr, value, profile)
except exceptions.ProfileNotInCacheError:
# We have to ask data to the storage manager
d = self.storage.getIndParam(category, name, profile)
d = self.storage.get_ind_param(category, name, profile)
return d.addCallback(
lambda value: self._asyncGetAttr(node[1], attr, value, profile)
lambda value: self._async_get_attr(node[1], attr, value, profile)
)
def _getParamsValuesFromCategory(
def _get_params_values_from_category(
self, category, security_limit, app, extra_s, profile_key):
client = self.host.getClient(profile_key)
client = self.host.get_client(profile_key)
extra = data_format.deserialise(extra_s)
return defer.ensureDeferred(self.getParamsValuesFromCategory(
return defer.ensureDeferred(self.get_params_values_from_category(
client, category, security_limit, app, extra))
async def getParamsValuesFromCategory(
async def get_params_values_from_category(
self, client, category, security_limit, app='', extra=None):
"""Get all parameters "attribute" for a category
@ -676,14 +676,14 @@ class Params(object):
@param security_limit(int): NO_SECURITY_LIMIT (-1) to return all the params.
Otherwise sole the params which have a security level defined *and*
lower or equal to the specified value are returned.
@param app(str): see [getParams]
@param extra(dict): see [getParams]
@param app(str): see [get_params]
@param extra(dict): see [get_params]
@return (dict): key: param name, value: param value (converted to string if needed)
"""
# TODO: manage category of general type (without existant profile)
if extra is None:
extra = {}
prof_xml = await self._constructProfileXml(client, security_limit, app, extra)
prof_xml = await self._construct_profile_xml(client, security_limit, app, extra)
ret = {}
for category_node in prof_xml.getElementsByTagName("category"):
if category_node.getAttribute("name") == category:
@ -696,7 +696,7 @@ class Params(object):
)
)
continue
value = await self.asyncGetStringParamA(
value = await self.async_get_string_param_a(
name, category, security_limit=security_limit,
profile=client.profile)
@ -706,7 +706,7 @@ class Params(object):
prof_xml.unlink()
return ret
def _getParam(
def _get_param(
self, category, name, type_=C.INDIVIDUAL, cache=None, profile=C.PROF_KEY_NONE
):
"""Return the param, or None if it doesn't exist
@ -736,7 +736,7 @@ class Params(object):
return None
return cache[(category, name)]
async def _constructProfileXml(self, client, security_limit, app, extra):
async def _construct_profile_xml(self, client, security_limit, app, extra):
"""Construct xml for asked profile, filling values when needed
/!\ as noticed in doc, don't forget to unlink the minidom.Document
@ -749,18 +749,18 @@ class Params(object):
"""
profile = client.profile
def checkNode(node):
def check_node(node):
"""Check the node against security_limit, app and extra"""
return (self.checkSecurityLimit(node, security_limit)
and self.checkApp(node, app)
and self.checkExtra(node, extra))
return (self.check_security_limit(node, security_limit)
and self.check_app(node, app)
and self.check_extra(node, extra))
if profile in self.params:
profile_cache = self.params[profile]
else:
# profile is not in cache, we load values in a short time cache
profile_cache = {}
await self.loadIndParams(profile, profile_cache)
await self.load_ind_params(profile, profile_cache)
# init the result document
prof_xml = minidom.parseString("<params/>")
@ -782,7 +782,7 @@ class Params(object):
for node in dest_cat.childNodes:
if node.nodeName != "param":
continue
if not checkNode(node):
if not check_node(node):
to_remove.append(node)
continue
dest_params[node.getAttribute("name")] = node
@ -799,14 +799,14 @@ class Params(object):
# we have to merge new params (we are parsing individual parameters, we have to add them
# to the previously parsed general ones)
name = param_node.getAttribute("name")
if not checkNode(param_node):
if not check_node(param_node):
continue
if name not in dest_params:
# this is reached when a previous category exists
dest_params[name] = param_node.cloneNode(True)
dest_cat.appendChild(dest_params[name])
profile_value = self._getParam(
profile_value = self._get_param(
category,
name,
type_node.nodeName,
@ -867,12 +867,12 @@ class Params(object):
return prof_xml
def _getParamsUI(self, security_limit, app, extra_s, profile_key):
client = self.host.getClient(profile_key)
def _get_params_ui(self, security_limit, app, extra_s, profile_key):
client = self.host.get_client(profile_key)
extra = data_format.deserialise(extra_s)
return defer.ensureDeferred(self.getParamsUI(client, security_limit, app, extra))
return defer.ensureDeferred(self.param_ui_get(client, security_limit, app, extra))
async def getParamsUI(self, client, security_limit, app, extra=None):
async def param_ui_get(self, client, security_limit, app, extra=None):
"""Get XMLUI to handle parameters
@param security_limit: NO_SECURITY_LIMIT (-1) to return all the params.
@ -883,10 +883,10 @@ class Params(object):
- ignore: list of (category/name) values to remove from parameters
@return(str): a SàT XMLUI for parameters
"""
param_xml = await self.getParams(client, security_limit, app, extra)
return paramsXML2XMLUI(param_xml)
param_xml = await self.get_params(client, security_limit, app, extra)
return params_xml_2_xmlui(param_xml)
async def getParams(self, client, security_limit, app, extra=None):
async def get_params(self, client, security_limit, app, extra=None):
"""Construct xml for asked profile, take params xml as skeleton
@param security_limit: NO_SECURITY_LIMIT (-1) to return all the params.
@ -900,12 +900,12 @@ class Params(object):
"""
if extra is None:
extra = {}
prof_xml = await self._constructProfileXml(client, security_limit, app, extra)
prof_xml = await self._construct_profile_xml(client, security_limit, app, extra)
return_xml = prof_xml.toxml()
prof_xml.unlink()
return "\n".join((line for line in return_xml.split("\n") if line))
def _getParamNode(self, name, category, type_="@ALL@"): # FIXME: is type_ useful ?
def _get_param_node(self, name, category, type_="@ALL@"): # FIXME: is type_ useful ?
"""Return a node from the param_xml
@param name: name of the node
@param category: category of the node
@ -931,7 +931,7 @@ class Params(object):
return (type_node.nodeName, param)
return None
def getParamsCategories(self):
def params_categories_get(self):
"""return the categories availables"""
categories = []
for cat in self.dom.getElementsByTagName("category"):
@ -940,7 +940,7 @@ class Params(object):
categories.append(cat.getAttribute("name"))
return categories
def setParam(self, name, value, category, security_limit=C.NO_SECURITY_LIMIT,
def param_set(self, name, value, category, security_limit=C.NO_SECURITY_LIMIT,
profile_key=C.PROF_KEY_NONE):
"""Set a parameter, return None if the parameter is not in param xml.
@ -955,14 +955,14 @@ class Params(object):
@param profile_key (str): %(doc_profile_key)s
@return: a deferred None value when everything is done
"""
# FIXME: setParam should accept the right type for value, not only str !
# FIXME: param_set should accept the right type for value, not only str !
if profile_key != C.PROF_KEY_NONE:
profile = self.getProfileName(profile_key)
profile = self.get_profile_name(profile_key)
if not profile:
log.error(_("Trying to set parameter for an unknown profile"))
raise exceptions.ProfileUnknownError(profile_key)
node = self._getParamNode(name, category, "@ALL@")
node = self._get_param_node(name, category, "@ALL@")
if not node:
log.error(
_("Requesting an unknown parameter (%(category)s/%(name)s)")
@ -970,7 +970,7 @@ class Params(object):
)
return defer.succeed(None)
if not self.checkSecurityLimit(node[1], security_limit):
if not self.check_security_limit(node[1], security_limit):
msg = _(
"{profile!r} is trying to set parameter {name!r} in category "
"{category!r} without authorization!!!").format(
@ -1018,12 +1018,12 @@ class Params(object):
if node[0] == C.GENERAL:
self.params_gen[(category, name)] = value
self.storage.setGenParam(category, name, value)
for profile in self.storage.getProfilesList():
if self.host.memory.isSessionStarted(profile):
self.host.bridge.paramUpdate(name, value, category, profile)
self.storage.set_gen_param(category, name, value)
for profile in self.storage.get_profiles_list():
if self.host.memory.is_session_started(profile):
self.host.bridge.param_update(name, value, category, profile)
self.host.trigger.point(
"paramUpdateTrigger", name, value, category, node[0], profile
"param_update_trigger", name, value, category, node[0], profile
)
return defer.succeed(None)
@ -1035,7 +1035,7 @@ class Params(object):
return defer.succeed(None)
elif type_ == "password":
try:
personal_key = self.host.memory.auth_sessions.profileGetUnique(profile)[
personal_key = self.host.memory.auth_sessions.profile_get_unique(profile)[
C.MEMORY_CRYPTO_KEY
]
except TypeError:
@ -1044,7 +1044,7 @@ class Params(object):
)
if (category, name) == C.PROFILE_PASS_PATH:
# using 'value' as the encryption key to encrypt another encryption key... could be confusing!
d = self.host.memory.encryptPersonalData(
d = self.host.memory.encrypt_personal_data(
data_key=C.MEMORY_CRYPTO_KEY,
data_value=personal_key,
crypto_key=value,
@ -1060,21 +1060,21 @@ class Params(object):
else:
d = defer.succeed(value)
def gotFinalValue(value):
if self.host.memory.isSessionStarted(profile):
def got_final_value(value):
if self.host.memory.is_session_started(profile):
self.params[profile][(category, name)] = value
self.host.bridge.paramUpdate(name, value, category, profile)
self.host.bridge.param_update(name, value, category, profile)
self.host.trigger.point(
"paramUpdateTrigger", name, value, category, node[0], profile
"param_update_trigger", name, value, category, node[0], profile
)
return self.storage.setIndParam(category, name, value, profile)
return self.storage.set_ind_param(category, name, value, profile)
else:
raise exceptions.ProfileNotConnected
d.addCallback(gotFinalValue)
d.addCallback(got_final_value)
return d
def _getNodesOfTypes(self, attr_type, node_type="@ALL@"):
def _get_nodes_of_types(self, attr_type, node_type="@ALL@"):
"""Return all the nodes matching the given types.
TODO: using during the dev but not anymore... remove if not needed
@ -1105,7 +1105,7 @@ class Params(object):
ret[(cat, param.getAttribute("name"))] = param
return ret
def checkSecurityLimit(self, node, security_limit):
def check_security_limit(self, node, security_limit):
"""Check the given node against the given security limit.
The value NO_SECURITY_LIMIT (-1) means that everything is allowed.
@return: True if this node can be accessed with the given security limit.
@ -1117,7 +1117,7 @@ class Params(object):
return True
return False
def checkApp(self, node, app):
def check_app(self, node, app):
"""Check the given node against the given app.
@param node: parameter node
@ -1128,7 +1128,7 @@ class Params(object):
return True
return node.getAttribute("app") == app
def checkExtra(self, node, extra):
def check_extra(self, node, extra):
"""Check the given node against the extra filters.
@param node: parameter node
@ -1147,7 +1147,7 @@ class Params(object):
return True
def makeOptions(options, selected=None):
def make_options(options, selected=None):
"""Create option XML form dictionary
@param options(dict): option's name => option's label map

View file

@ -51,7 +51,7 @@ class PersistentDict:
self.namespace = namespace
self.profile = profile
def _setCache(self, data):
def _set_cache(self, data):
self._cache = data
def load(self):
@ -60,10 +60,10 @@ class PersistentDict:
need to be called before any other operation
@return: defers the PersistentDict instance itself
"""
d = defer.ensureDeferred(self.storage.getPrivates(
d = defer.ensureDeferred(self.storage.get_privates(
self.namespace, binary=self.binary, profile=self.profile
))
d.addCallback(self._setCache)
d.addCallback(self._set_cache)
d.addCallback(lambda __: self)
return d
@ -117,20 +117,20 @@ class PersistentDict:
def __setitem__(self, key, value):
defer.ensureDeferred(
self.storage.setPrivateValue(
self.storage.set_private_value(
self.namespace, key, value, self.binary, self.profile
)
)
return self._cache.__setitem__(key, value)
def __delitem__(self, key):
self.storage.delPrivateValue(self.namespace, key, self.binary, self.profile)
self.storage.del_private_value(self.namespace, key, self.binary, self.profile)
return self._cache.__delitem__(key)
def clear(self):
"""Delete all values from this namespace"""
self._cache.clear()
return self.storage.delPrivateNamespace(self.namespace, self.binary, self.profile)
return self.storage.del_private_namespace(self.namespace, self.binary, self.profile)
def get(self, key, default=None):
return self._cache.get(key, default)
@ -139,7 +139,7 @@ class PersistentDict:
"""Async set, return a Deferred fired when value is actually stored"""
self._cache.__setitem__(key, value)
return defer.ensureDeferred(
self.storage.setPrivateValue(
self.storage.set_private_value(
self.namespace, key, value, self.binary, self.profile
)
)
@ -147,7 +147,7 @@ class PersistentDict:
def adel(self, key):
"""Async del, return a Deferred fired when value is actually deleted"""
self._cache.__delitem__(key)
return self.storage.delPrivateValue(
return self.storage.del_private_value(
self.namespace, key, self.binary, self.profile)
def setdefault(self, key, default):
@ -163,7 +163,7 @@ class PersistentDict:
@return: deferred fired when data is actually saved
"""
return defer.ensureDeferred(
self.storage.setPrivateValue(
self.storage.set_private_value(
self.namespace, name, self._cache[name], self.binary, self.profile
)
)
@ -192,14 +192,14 @@ class LazyPersistentBinaryDict(PersistentBinaryDict):
raise NotImplementedError
def items(self):
d = defer.ensureDeferred(self.storage.getPrivates(
d = defer.ensureDeferred(self.storage.get_privates(
self.namespace, binary=self.binary, profile=self.profile
))
d.addCallback(lambda data_dict: data_dict.items())
return d
def all(self):
return defer.ensureDeferred(self.storage.getPrivates(
return defer.ensureDeferred(self.storage.get_privates(
self.namespace, binary=self.binary, profile=self.profile
))
@ -252,7 +252,7 @@ class LazyPersistentBinaryDict(PersistentBinaryDict):
def __getitem__(self, key):
"""get the value as a Deferred"""
d = defer.ensureDeferred(self.storage.getPrivates(
d = defer.ensureDeferred(self.storage.get_privates(
self.namespace, keys=[key], binary=self.binary, profile=self.profile
))
d.addCallback(self._data2value, key)
@ -260,21 +260,21 @@ class LazyPersistentBinaryDict(PersistentBinaryDict):
def __setitem__(self, key, value):
defer.ensureDeferred(
self.storage.setPrivateValue(
self.storage.set_private_value(
self.namespace, key, value, self.binary, self.profile
)
)
def __delitem__(self, key):
self.storage.delPrivateValue(self.namespace, key, self.binary, self.profile)
self.storage.del_private_value(self.namespace, key, self.binary, self.profile)
def _defaultOrException(self, failure_, default):
def _default_or_exception(self, failure_, default):
failure_.trap(KeyError)
return default
def get(self, key, default=None):
d = self.__getitem__(key)
d.addErrback(self._defaultOrException, default=default)
d.addErrback(self._default_or_exception, default=default)
return d
def aset(self, key, value):
@ -282,7 +282,7 @@ class LazyPersistentBinaryDict(PersistentBinaryDict):
# FIXME: redundant with force, force must be removed
# XXX: similar as PersistentDict.aset, but doesn't use cache
return defer.ensureDeferred(
self.storage.setPrivateValue(
self.storage.set_private_value(
self.namespace, key, value, self.binary, self.profile
)
)
@ -290,7 +290,7 @@ class LazyPersistentBinaryDict(PersistentBinaryDict):
def adel(self, key):
"""Async del, return a Deferred fired when value is actually deleted"""
# XXX: similar as PersistentDict.adel, but doesn't use cache
return self.storage.delPrivateValue(
return self.storage.del_private_value(
self.namespace, key, self.binary, self.profile)
def setdefault(self, key, default):
@ -303,7 +303,7 @@ class LazyPersistentBinaryDict(PersistentBinaryDict):
@return: deferred fired when data is actually saved
"""
return defer.ensureDeferred(
self.storage.setPrivateValue(
self.storage.set_private_value(
self.namespace, name, value, self.binary, self.profile
)
)
@ -314,4 +314,4 @@ class LazyPersistentBinaryDict(PersistentBinaryDict):
@param key(unicode): key to delete
@return (D): A deferred fired when delete is done
"""
return self.storage.delPrivateValue(self.namespace, key, self.binary, self.profile)
return self.storage.del_private_value(self.namespace, key, self.binary, self.profile)

View file

@ -122,10 +122,10 @@ class Storage:
# profile id to component entry point
self.components: Dict[int, str] = {}
def getProfileById(self, profile_id):
def get_profile_by_id(self, profile_id):
return self.profiles.get(profile_id)
async def migrateApply(self, *args: str, log_output: bool = False) -> None:
async def migrate_apply(self, *args: str, log_output: bool = False) -> None:
"""Do a migration command
Commands are applied by running Alembic in a subprocess.
@ -167,7 +167,7 @@ class Storage:
await conn.run_sync(Base.metadata.create_all)
log.debug("stamping the database")
await self.migrateApply("stamp", "head")
await self.migrate_apply("stamp", "head")
log.debug("stamping done")
def _check_db_is_up_to_date(self, conn: Connection) -> bool:
@ -193,14 +193,14 @@ class Storage:
else:
log.info("Database needs to be updated")
log.info("updating…")
await self.migrateApply("upgrade", "head", log_output=True)
await self.migrate_apply("upgrade", "head", log_output=True)
log.info("Database is now up-to-date")
@aio
async def initialise(self) -> None:
log.info(_("Connecting database"))
db_config = sqla_config.getDbConfig()
db_config = sqla_config.get_db_config()
engine = create_async_engine(
db_config["url"],
future=True,
@ -288,31 +288,31 @@ class Storage:
## Profiles
def getProfilesList(self) -> List[str]:
def get_profiles_list(self) -> List[str]:
""""Return list of all registered profiles"""
return list(self.profiles.keys())
def hasProfile(self, profile_name: str) -> bool:
def has_profile(self, profile_name: str) -> bool:
"""return True if profile_name exists
@param profile_name: name of the profile to check
"""
return profile_name in self.profiles
def profileIsComponent(self, profile_name: str) -> bool:
def profile_is_component(self, profile_name: str) -> bool:
try:
return self.profiles[profile_name] in self.components
except KeyError:
raise exceptions.NotFound("the requested profile doesn't exists")
def getEntryPoint(self, profile_name: str) -> str:
def get_entry_point(self, profile_name: str) -> str:
try:
return self.components[self.profiles[profile_name]]
except KeyError:
raise exceptions.NotFound("the requested profile doesn't exists or is not a component")
@aio
async def createProfile(self, name: str, component_ep: Optional[str] = None) -> None:
async def create_profile(self, name: str, component_ep: Optional[str] = None) -> None:
"""Create a new profile
@param name: name of the profile
@ -331,7 +331,7 @@ class Storage:
return profile
@aio
async def deleteProfile(self, name: str) -> None:
async def delete_profile(self, name: str) -> None:
"""Delete profile
@param name: name of the profile
@ -349,7 +349,7 @@ class Storage:
## Params
@aio
async def loadGenParams(self, params_gen: dict) -> None:
async def load_gen_params(self, params_gen: dict) -> None:
"""Load general parameters
@param params_gen: dictionary to fill
@ -361,7 +361,7 @@ class Storage:
params_gen[(p.category, p.name)] = p.value
@aio
async def loadIndParams(self, params_ind: dict, profile: str) -> None:
async def load_ind_params(self, params_ind: dict, profile: str) -> None:
"""Load individual parameters
@param params_ind: dictionary to fill
@ -376,7 +376,7 @@ class Storage:
params_ind[(p.category, p.name)] = p.value
@aio
async def getIndParam(self, category: str, name: str, profile: str) -> Optional[str]:
async def get_ind_param(self, category: str, name: str, profile: str) -> Optional[str]:
"""Ask database for the value of one specific individual parameter
@param category: category of the parameter
@ -395,7 +395,7 @@ class Storage:
return result.scalar_one_or_none()
@aio
async def getIndParamValues(self, category: str, name: str) -> Dict[str, str]:
async def get_ind_param_values(self, category: str, name: str) -> Dict[str, str]:
"""Ask database for the individual values of a parameter for all profiles
@param category: category of the parameter
@ -414,7 +414,7 @@ class Storage:
return {param.profile.name: param.value for param in result.scalars()}
@aio
async def setGenParam(self, category: str, name: str, value: Optional[str]) -> None:
async def set_gen_param(self, category: str, name: str, value: Optional[str]) -> None:
"""Save the general parameters in database
@param category: category of the parameter
@ -436,7 +436,7 @@ class Storage:
await session.commit()
@aio
async def setIndParam(
async def set_ind_param(
self,
category:str,
name: str,
@ -489,7 +489,7 @@ class Storage:
return History.source == jid_.userhost()
@aio
async def historyGet(
async def history_get(
self,
from_jid: Optional[jid.JID],
to_jid: Optional[jid.JID],
@ -509,7 +509,7 @@ class Storage:
- None for unlimited
@param between: confound source and dest (ignore the direction)
@param filters: pattern to filter the history results
@return: list of messages as in [messageNew], minus the profile which is already
@return: list of messages as in [message_new], minus the profile which is already
known.
"""
# we have to set a default value to profile because it's last argument
@ -634,7 +634,7 @@ class Storage:
return [h.as_tuple() for h in result]
@aio
async def addToHistory(self, data: dict, profile: str) -> None:
async def add_to_history(self, data: dict, profile: str) -> None:
"""Store a new message in history
@param data: message data as build by SatMessageProtocol.onMessage
@ -682,7 +682,7 @@ class Storage:
## Private values
def _getPrivateClass(self, binary, profile):
def _get_private_class(self, binary, profile):
"""Get ORM class to use for private values"""
if profile is None:
return PrivateGenBin if binary else PrivateGen
@ -691,7 +691,7 @@ class Storage:
@aio
async def getPrivates(
async def get_privates(
self,
namespace:str,
keys: Optional[Iterable[str]] = None,
@ -714,7 +714,7 @@ class Storage:
f"{' binary' if binary else ''} private values from database for namespace "
f"{namespace}{f' with keys {keys!r}' if keys is not None else ''}"
)
cls = self._getPrivateClass(binary, profile)
cls = self._get_private_class(binary, profile)
stmt = select(cls).filter_by(namespace=namespace)
if keys:
stmt = stmt.where(cls.key.in_(list(keys)))
@ -725,7 +725,7 @@ class Storage:
return {p.key: p.value for p in result.scalars()}
@aio
async def setPrivateValue(
async def set_private_value(
self,
namespace: str,
key:str,
@ -743,7 +743,7 @@ class Storage:
@param profile: profile to use for individual value
if None, it's a general value
"""
cls = self._getPrivateClass(binary, profile)
cls = self._get_private_class(binary, profile)
values = {
"namespace": namespace,
@ -768,7 +768,7 @@ class Storage:
await session.commit()
@aio
async def delPrivateValue(
async def del_private_value(
self,
namespace: str,
key: str,
@ -783,7 +783,7 @@ class Storage:
@param profile: profile to use for individual value
if None, it's a general value
"""
cls = self._getPrivateClass(binary, profile)
cls = self._get_private_class(binary, profile)
stmt = delete(cls).filter_by(namespace=namespace, key=key)
@ -795,7 +795,7 @@ class Storage:
await session.commit()
@aio
async def delPrivateNamespace(
async def del_private_namespace(
self,
namespace: str,
binary: bool = False,
@ -805,9 +805,9 @@ class Storage:
Be really cautious when you use this method, as all data with given namespace are
removed.
Params are the same as for delPrivateValue
Params are the same as for del_private_value
"""
cls = self._getPrivateClass(binary, profile)
cls = self._get_private_class(binary, profile)
stmt = delete(cls).filter_by(namespace=namespace)
@ -821,7 +821,7 @@ class Storage:
## Files
@aio
async def getFiles(
async def get_files(
self,
client: Optional[SatXMPPEntity],
file_id: Optional[str] = None,
@ -852,7 +852,7 @@ class Storage:
@param projection: name of columns to retrieve
None to retrieve all
@param unique: if True will remove duplicates
other params are the same as for [setFile]
other params are the same as for [set_file]
@return: files corresponding to filters
"""
if projection is None:
@ -910,7 +910,7 @@ class Storage:
return [dict(r) for r in result]
@aio
async def setFile(
async def set_file(
self,
client: SatXMPPEntity,
name: str,
@ -987,7 +987,7 @@ class Storage:
))
@aio
async def fileGetUsedSpace(self, client: SatXMPPEntity, owner: jid.JID) -> int:
async def file_get_used_space(self, client: SatXMPPEntity, owner: jid.JID) -> int:
async with self.session() as session:
result = await session.execute(
select(sum_(File.size)).filter_by(
@ -998,7 +998,7 @@ class Storage:
return result.scalar_one_or_none() or 0
@aio
async def fileDelete(self, file_id: str) -> None:
async def file_delete(self, file_id: str) -> None:
"""Delete file metadata from the database
@param file_id: id of the file to delete
@ -1010,7 +1010,7 @@ class Storage:
await session.commit()
@aio
async def fileUpdate(
async def file_update(
self,
file_id: str,
column: str,
@ -1068,7 +1068,7 @@ class Storage:
)
@aio
async def getPubsubNode(
async def get_pubsub_node(
self,
client: SatXMPPEntity,
service: jid.JID,
@ -1085,7 +1085,7 @@ class Storage:
@param with_items: retrieve items in the same query
@param with_subscriptions: retrieve subscriptions in the same query
@param create: if the node doesn't exist in DB, create it
@param create_kwargs: keyword arguments to use with ``setPubsubNode`` if the node
@param create_kwargs: keyword arguments to use with ``set_pubsub_node`` if the node
needs to be created.
"""
async with self.session() as session:
@ -1112,15 +1112,15 @@ class Storage:
if create_kwargs is None:
create_kwargs = {}
try:
return await as_future(self.setPubsubNode(
return await as_future(self.set_pubsub_node(
client, service, name, **create_kwargs
))
except IntegrityError as e:
if "unique" in str(e.orig).lower():
# the node may already exist, if it has been created just after
# getPubsubNode above
# get_pubsub_node above
log.debug("ignoring UNIQUE constraint error")
cached_node = await as_future(self.getPubsubNode(
cached_node = await as_future(self.get_pubsub_node(
client,
service,
name,
@ -1133,7 +1133,7 @@ class Storage:
return ret
@aio
async def setPubsubNode(
async def set_pubsub_node(
self,
client: SatXMPPEntity,
service: jid.JID,
@ -1159,7 +1159,7 @@ class Storage:
return node
@aio
async def updatePubsubNodeSyncState(
async def update_pubsub_node_sync_state(
self,
node: PubsubNode,
state: SyncState
@ -1176,7 +1176,7 @@ class Storage:
)
@aio
async def deletePubsubNode(
async def delete_pubsub_node(
self,
profiles: Optional[List[str]],
services: Optional[List[jid.JID]],
@ -1207,7 +1207,7 @@ class Storage:
await session.commit()
@aio
async def cachePubsubItems(
async def cache_pubsub_items(
self,
client: SatXMPPEntity,
node: PubsubNode,
@ -1240,7 +1240,7 @@ class Storage:
await session.commit()
@aio
async def deletePubsubItems(
async def delete_pubsub_items(
self,
node: PubsubNode,
items_names: Optional[List[str]] = None
@ -1264,7 +1264,7 @@ class Storage:
await session.commit()
@aio
async def purgePubsubItems(
async def purge_pubsub_items(
self,
services: Optional[List[jid.JID]] = None,
names: Optional[List[str]] = None,
@ -1313,7 +1313,7 @@ class Storage:
await session.commit()
@aio
async def getItems(
async def get_items(
self,
node: PubsubNode,
max_items: Optional[int] = None,
@ -1352,7 +1352,7 @@ class Storage:
metadata = {
"service": node.service,
"node": node.name,
"uri": uri.buildXMPPUri(
"uri": uri.build_xmpp_uri(
"pubsub",
path=node.service.full(),
node=node.name,
@ -1487,7 +1487,7 @@ class Storage:
result.reverse()
return result, metadata
def _getSqlitePath(
def _get_sqlite_path(
self,
path: List[Union[str, int]]
) -> str:
@ -1495,7 +1495,7 @@ class Storage:
return f"${''.join(f'[{p}]' if isinstance(p, int) else f'.{p}' for p in path)}"
@aio
async def searchPubsubItems(
async def search_pubsub_items(
self,
query: dict,
) -> Tuple[List[PubsubItem]]:
@ -1626,7 +1626,7 @@ class Storage:
op_attr = OP_MAP[operator]
except KeyError:
raise ValueError(f"invalid operator: {operator!r}")
sqlite_path = self._getSqlitePath(path)
sqlite_path = self._get_sqlite_path(path)
if operator in ("overlap", "ioverlap", "disjoint", "idisjoint"):
col = literal_column("json_each.value")
if operator[0] == "i":
@ -1683,7 +1683,7 @@ class Storage:
raise NotImplementedError(f"Unknown {order!r} order")
else:
# we have a JSON path
# sqlite_path = self._getSqlitePath(path)
# sqlite_path = self._get_sqlite_path(path)
col = PubsubItem.parsed[path]
direction = order_data.get("direction", "ASC").lower()
if not direction in ("asc", "desc"):

View file

@ -22,15 +22,15 @@ from sat.core.constants import Const as C
from sat.tools import config
def getDbConfig() -> dict:
def get_db_config() -> dict:
"""Get configuration for database
@return: dict with following keys:
- type: only "sqlite" for now
- path: path to the sqlite DB
"""
main_conf = config.parseMainConf()
local_dir = Path(config.getConfig(main_conf, "", "local_dir"))
main_conf = config.parse_main_conf()
local_dir = Path(config.config_get(main_conf, "", "local_dir"))
database_path = (local_dir / C.SAVEFILE_DATABASE).expanduser()
url = f"sqlite+aiosqlite:///{quote(str(database_path))}?timeout=30"
return {

View file

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

View file

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

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -49,8 +49,8 @@ class PubsubAdmin(object):
def __init__(self, host):
self.host = host
host.bridge.addMethod(
"psAdminItemsSend",
host.bridge.add_method(
"ps_admin_items_send",
".plugin",
in_sign="ssasss",
out_sign="as",
@ -60,7 +60,7 @@ class PubsubAdmin(object):
def _publish(self, service, nodeIdentifier, items, extra=None,
profile_key=C.PROF_KEY_NONE):
client = self.host.getClient(profile_key)
client = self.host.get_client(profile_key)
service = None if not service else jid.JID(service)
extra = data_format.deserialise(extra)
items = [generic.parseXml(i.encode('utf-8')) for i in items]
@ -68,7 +68,7 @@ class PubsubAdmin(object):
client, service, nodeIdentifier, items, extra
)
def _sendCb(self, iq_result):
def _send_cb(self, iq_result):
publish_elt = iq_result.admin.pubsub.publish
ids = []
for item_elt in publish_elt.elements(pubsub.NS_PUBSUB, 'item'):
@ -90,5 +90,5 @@ class PubsubAdmin(object):
for item in items:
publish_elt.addChild(item)
d = iq_elt.send()
d.addCallback(self._sendCb)
d.addCallback(self._send_cb)
return d

View file

@ -56,51 +56,51 @@ class PubsubHook(object):
log.info(_("PubSub Hook initialization"))
self.host = host
self.node_hooks = {} # keep track of the number of hooks per node (for all profiles)
host.bridge.addMethod(
"psHookAdd", ".plugin", in_sign="ssssbs", out_sign="", method=self._addHook
host.bridge.add_method(
"ps_hook_add", ".plugin", in_sign="ssssbs", out_sign="", method=self._addHook
)
host.bridge.addMethod(
"psHookRemove",
host.bridge.add_method(
"ps_hook_remove",
".plugin",
in_sign="sssss",
out_sign="i",
method=self._removeHook,
)
host.bridge.addMethod(
"psHookList",
host.bridge.add_method(
"ps_hook_list",
".plugin",
in_sign="s",
out_sign="aa{ss}",
method=self._listHooks,
method=self._list_hooks,
)
@defer.inlineCallbacks
def profileConnected(self, client):
def profile_connected(self, client):
hooks = client._hooks = persistent.PersistentBinaryDict(
NS_PUBSUB_HOOK, client.profile
)
client._hooks_temporary = {}
yield hooks.load()
for node in hooks:
self._installNodeManager(client, node)
self._install_node_manager(client, node)
def profileDisconnected(self, client):
def profile_disconnected(self, client):
for node in client._hooks:
self._removeNodeManager(client, node)
self._remove_node_manager(client, node)
def _installNodeManager(self, client, node):
def _install_node_manager(self, client, node):
if node in self.node_hooks:
log.debug(_("node manager already set for {node}").format(node=node))
self.node_hooks[node] += 1
else:
# first hook on this node
self.host.plugins["XEP-0060"].addManagedNode(
node, items_cb=self._itemsReceived
self.host.plugins["XEP-0060"].add_managed_node(
node, items_cb=self._items_received
)
self.node_hooks[node] = 0
log.info(_("node manager installed on {node}").format(node=node))
def _removeNodeManager(self, client, node):
def _remove_node_manager(self, client, node):
try:
self.node_hooks[node] -= 1
except KeyError:
@ -108,12 +108,12 @@ class PubsubHook(object):
else:
if self.node_hooks[node] == 0:
del self.node_hooks[node]
self.host.plugins["XEP-0060"].removeManagedNode(node, self._itemsReceived)
self.host.plugins["XEP-0060"].remove_managed_node(node, self._items_received)
log.debug(_("hook removed"))
else:
log.debug(_("node still needed for an other hook"))
def installHook(self, client, service, node, hook_type, hook_arg, persistent):
def install_hook(self, client, service, node, hook_type, hook_arg, persistent):
if hook_type not in HOOK_TYPES:
raise exceptions.DataError(
_("{hook_type} is not handled").format(hook_type=hook_type)
@ -124,7 +124,7 @@ class PubsubHook(object):
hook_type=hook_type
)
)
self._installNodeManager(client, node)
self._install_node_manager(client, node)
hook_data = {"service": service, "type": hook_type, "arg": hook_arg}
if persistent:
@ -143,7 +143,7 @@ class PubsubHook(object):
)
)
def _itemsReceived(self, client, itemsEvent):
def _items_received(self, client, itemsEvent):
node = itemsEvent.nodeIdentifier
for hooks in (client._hooks, client._hooks_temporary):
if node not in hooks:
@ -188,9 +188,9 @@ class PubsubHook(object):
)
def _addHook(self, service, node, hook_type, hook_arg, persistent, profile):
client = self.host.getClient(profile)
client = self.host.get_client(profile)
service = jid.JID(service) if service else client.jid.userhostJID()
return self.addHook(
return self.add_hook(
client,
service,
str(node),
@ -199,7 +199,7 @@ class PubsubHook(object):
persistent,
)
def addHook(self, client, service, node, hook_type, hook_arg, persistent):
def add_hook(self, client, service, node, hook_type, hook_arg, persistent):
r"""Add a hook which will be triggered on a pubsub notification
@param service(jid.JID): service of the node
@ -219,21 +219,21 @@ class PubsubHook(object):
can be a module path, file path, python code
"""
assert service is not None
return self.installHook(client, service, node, hook_type, hook_arg, persistent)
return self.install_hook(client, service, node, hook_type, hook_arg, persistent)
def _removeHook(self, service, node, hook_type, hook_arg, profile):
client = self.host.getClient(profile)
client = self.host.get_client(profile)
service = jid.JID(service) if service else client.jid.userhostJID()
return self.removeHook(client, service, node, hook_type or None, hook_arg or None)
return self.remove_hook(client, service, node, hook_type or None, hook_arg or None)
def removeHook(self, client, service, node, hook_type=None, hook_arg=None):
def remove_hook(self, client, service, node, hook_type=None, hook_arg=None):
"""Remove a persistent or temporaty root
@param service(jid.JID): service of the node
@param node(unicode): Pubsub node
@param hook_type(unicode, None): same as for [addHook]
@param hook_type(unicode, None): same as for [add_hook]
match all if None
@param hook_arg(unicode, None): same as for [addHook]
@param hook_arg(unicode, None): same as for [add_hook]
match all if None
@return(int): number of hooks removed
"""
@ -254,20 +254,20 @@ class PubsubHook(object):
if not hooks[node]:
#  no more hooks, we can remove the node
del hooks[node]
self._removeNodeManager(client, node)
self._remove_node_manager(client, node)
else:
if hooks == client._hooks:
hooks.force(node)
return removed
def _listHooks(self, profile):
hooks_list = self.listHooks(self.host.getClient(profile))
def _list_hooks(self, profile):
hooks_list = self.list_hooks(self.host.get_client(profile))
for hook in hooks_list:
hook["service"] = hook["service"].full()
hook["persistent"] = C.boolConst(hook["persistent"])
hook["persistent"] = C.bool_const(hook["persistent"])
return hooks_list
def listHooks(self, client):
def list_hooks(self, client):
"""return list of registered hooks"""
hooks_list = []
for hooks in (client._hooks, client._hooks_temporary):

View file

@ -46,7 +46,7 @@ Importer = collections.namedtuple("Importer", ("callback", "short_desc", "long_d
class ImportPlugin(object):
def __init__(self, host):
log.info(_("plugin Import initialization"))
log.info(_("plugin import initialization"))
self.host = host
def initialize(self, import_handler, name):
@ -54,13 +54,13 @@ class ImportPlugin(object):
@param import_handler(object): specialized import handler instance
must have the following methods:
- importItem: import a single main item (i.e. prepare data for publishing)
- import_item: import a single main item (i.e. prepare data for publishing)
- importSubitems: import sub items (i.e. items linked to main item, e.g. comments).
Must return a dict with kwargs for recursiveImport if items are to be imported recursively.
Must return a dict with kwargs for recursive_import if items are to be imported recursively.
At least "items_import_data", "service" and "node" keys must be provided.
if None is returned, no recursion will be done to import subitems, but import can still be done directly by the method.
- publishItem: actualy publish an item
- itemFilters: modify item according to options
- publish_item: actualy publish an item
- item_filters: modify item according to options
@param name(unicode): import handler name
"""
assert name == name.lower().strip()
@ -71,7 +71,7 @@ class ImportPlugin(object):
import_handler.importers = {}
def _import(name, location, options, pubsub_service, pubsub_node, profile):
return self._doImport(
return self._do_import(
import_handler,
name,
location,
@ -81,40 +81,40 @@ class ImportPlugin(object):
profile,
)
def _importList():
return self.listImporters(import_handler)
def _import_list():
return self.list_importers(import_handler)
def _importDesc(name):
def _import_desc(name):
return self.getDescription(import_handler, name)
self.host.bridge.addMethod(
name + "Import",
self.host.bridge.add_method(
name + "import",
".plugin",
in_sign="ssa{ss}sss",
out_sign="s",
method=_import,
async_=True,
)
self.host.bridge.addMethod(
self.host.bridge.add_method(
name + "ImportList",
".plugin",
in_sign="",
out_sign="a(ss)",
method=_importList,
method=_import_list,
)
self.host.bridge.addMethod(
self.host.bridge.add_method(
name + "ImportDesc",
".plugin",
in_sign="s",
out_sign="(ss)",
method=_importDesc,
method=_import_desc,
)
def getProgress(self, import_handler, progress_id, profile):
client = self.host.getClient(profile)
def get_progress(self, import_handler, progress_id, profile):
client = self.host.get_client(profile)
return client._import[import_handler.name][progress_id]
def listImporters(self, import_handler):
def list_importers(self, import_handler):
importers = list(import_handler.importers.keys())
importers.sort()
return [
@ -139,9 +139,9 @@ class ImportPlugin(object):
else:
return importer.short_desc, importer.long_desc
def _doImport(self, import_handler, name, location, options, pubsub_service="",
def _do_import(self, import_handler, name, location, options, pubsub_service="",
pubsub_node="", profile=C.PROF_KEY_NONE):
client = self.host.getClient(profile)
client = self.host.get_client(profile)
options = {key: str(value) for key, value in options.items()}
for option in import_handler.BOOL_OPTIONS:
try:
@ -158,7 +158,7 @@ class ImportPlugin(object):
_("invalid json option: {option}").format(option=option)
)
pubsub_service = jid.JID(pubsub_service) if pubsub_service else None
return self.doImport(
return self.do_import(
client,
import_handler,
str(name),
@ -169,9 +169,9 @@ class ImportPlugin(object):
)
@defer.inlineCallbacks
def doImport(self, client, import_handler, name, location, options=None,
def do_import(self, client, import_handler, name, location, options=None,
pubsub_service=None, pubsub_node=None,):
"""Import data
"""import data
@param import_handler(object): instance of the import handler
@param name(unicode): name of the importer
@ -221,18 +221,18 @@ class ImportPlugin(object):
"direction": "out",
"type": import_handler.name.upper() + "_IMPORT",
}
self.host.registerProgressCb(
self.host.register_progress_cb(
progress_id,
partial(self.getProgress, import_handler),
partial(self.get_progress, import_handler),
metadata,
profile=client.profile,
)
self.host.bridge.progressStarted(progress_id, metadata, client.profile)
self.host.bridge.progress_started(progress_id, metadata, client.profile)
session = { #  session data, can be used by importers
"root_service": pubsub_service,
"root_node": pubsub_node,
}
self.recursiveImport(
self.recursive_import(
client,
import_handler,
items_import_data,
@ -246,7 +246,7 @@ class ImportPlugin(object):
defer.returnValue(progress_id)
@defer.inlineCallbacks
def recursiveImport(
def recursive_import(
self,
client,
import_handler,
@ -268,7 +268,7 @@ class ImportPlugin(object):
can be used by importer so store any useful data
"root_service" and "root_node" are set to the main pubsub service and node of the import
@param options(dict): import options
@param return_data(dict): data to return on progressFinished
@param return_data(dict): data to return on progress_finished
@param service(jid.JID, None): PubSub service to use
@param node(unicode, None): PubSub node to use
@param depth(int): level of recursion
@ -276,14 +276,14 @@ class ImportPlugin(object):
if return_data is None:
return_data = {}
for idx, item_import_data in enumerate(items_import_data):
item_data = yield import_handler.importItem(
item_data = yield import_handler.import_item(
client, item_import_data, session, options, return_data, service, node
)
yield import_handler.itemFilters(client, item_data, session, options)
recurse_kwargs = yield import_handler.importSubItems(
yield import_handler.item_filters(client, item_data, session, options)
recurse_kwargs = yield import_handler.import_sub_items(
client, item_import_data, item_data, session, options
)
yield import_handler.publishItem(client, item_data, service, node, session)
yield import_handler.publish_item(client, item_data, service, node, session)
if recurse_kwargs is not None:
recurse_kwargs["client"] = client
@ -294,7 +294,7 @@ class ImportPlugin(object):
recurse_kwargs["return_data"] = return_data
recurse_kwargs["depth"] = depth + 1
log.debug(_("uploading subitems"))
yield self.recursiveImport(**recurse_kwargs)
yield self.recursive_import(**recurse_kwargs)
if depth == 0:
client._import[import_handler.name][progress_id]["position"] = str(
@ -302,8 +302,8 @@ class ImportPlugin(object):
)
if depth == 0:
self.host.bridge.progressFinished(progress_id, return_data, client.profile)
self.host.removeProgressCb(progress_id, client.profile)
self.host.bridge.progress_finished(progress_id, return_data, client.profile)
self.host.remove_progress_cb(progress_id, client.profile)
del client._import[import_handler.name][progress_id]
def register(self, import_handler, name, callback, short_desc="", long_desc=""):
@ -311,10 +311,10 @@ class ImportPlugin(object):
@param name(unicode): unique importer name, should indicate the software it can import and always lowercase
@param callback(callable): method to call:
the signature must be (client, location, options) (cf. [doImport])
the signature must be (client, location, options) (cf. [do_import])
the importer must return a tuple with (items_import_data, items_count)
items_import_data(iterable[dict]) data specific to specialized importer
cf. importItem docstring of specialized importer for details
cf. import_item docstring of specialized importer for details
items_count (int, None) indicate the total number of items (without subitems)
useful to display a progress indicator when the iterator is a generator
use None if you can't guess the total number of items

View file

@ -108,72 +108,72 @@ class MiscAccount(object):
def __init__(self, host):
log.info(_("Plugin Account initialization"))
self.host = host
host.bridge.addMethod(
"registerSatAccount",
host.bridge.add_method(
"libervia_account_register",
".plugin",
in_sign="sss",
out_sign="",
method=self._registerAccount,
method=self._register_account,
async_=True,
)
host.bridge.addMethod(
"getNewAccountDomain",
host.bridge.add_method(
"account_domain_new_get",
".plugin",
in_sign="",
out_sign="s",
method=self.getNewAccountDomain,
method=self.account_domain_new_get,
async_=False,
)
host.bridge.addMethod(
"getAccountDialogUI",
host.bridge.add_method(
"account_dialog_ui_get",
".plugin",
in_sign="s",
out_sign="s",
method=self._getAccountDialogUI,
method=self._get_account_dialog_ui,
async_=False,
)
host.bridge.addMethod(
"asyncConnectWithXMPPCredentials",
host.bridge.add_method(
"credentials_xmpp_connect",
".plugin",
in_sign="ss",
out_sign="b",
method=self.asyncConnectWithXMPPCredentials,
method=self.credentials_xmpp_connect,
async_=True,
)
self.fixEmailAdmins()
self.fix_email_admins()
self._sessions = Sessions()
self.__account_cb_id = host.registerCallback(
self._accountDialogCb, with_data=True
self.__account_cb_id = host.register_callback(
self._account_dialog_cb, with_data=True
)
self.__change_password_id = host.registerCallback(
self.__changePasswordCb, with_data=True
self.__change_password_id = host.register_callback(
self.__change_password_cb, with_data=True
)
def deleteBlogCallback(posts, comments):
return lambda data, profile: self.__deleteBlogPostsCb(
def delete_blog_callback(posts, comments):
return lambda data, profile: self.__delete_blog_posts_cb(
posts, comments, data, profile
)
self.__delete_posts_id = host.registerCallback(
deleteBlogCallback(True, False), with_data=True
self.__delete_posts_id = host.register_callback(
delete_blog_callback(True, False), with_data=True
)
self.__delete_comments_id = host.registerCallback(
deleteBlogCallback(False, True), with_data=True
self.__delete_comments_id = host.register_callback(
delete_blog_callback(False, True), with_data=True
)
self.__delete_posts_comments_id = host.registerCallback(
deleteBlogCallback(True, True), with_data=True
self.__delete_posts_comments_id = host.register_callback(
delete_blog_callback(True, True), with_data=True
)
self.__delete_account_id = host.registerCallback(
self.__deleteAccountCb, with_data=True
self.__delete_account_id = host.register_callback(
self.__delete_account_cb, with_data=True
)
# FIXME: remove this after some time, when the deprecated parameter is really abandoned
def fixEmailAdmins(self):
def fix_email_admins(self):
"""Handle deprecated config option "admin_email" to fix the admin emails list"""
admin_email = self.getConfig("admin_email")
admin_email = self.config_get("admin_email")
if not admin_email:
return
log.warning(
@ -182,10 +182,10 @@ class MiscAccount(object):
param_name = "email_admins_list"
try:
section = ""
value = self.host.memory.getConfig(section, param_name, Exception)
value = self.host.memory.config_get(section, param_name, Exception)
except (configparser.NoOptionError, configparser.NoSectionError):
section = CONFIG_SECTION
value = self.host.memory.getConfig(
value = self.host.memory.config_get(
section, param_name, default_conf[param_name]
)
@ -193,13 +193,13 @@ class MiscAccount(object):
value.add(admin_email)
self.host.memory.config.set(section, param_name, ",".join(value))
def getConfig(self, name, section=CONFIG_SECTION):
def config_get(self, name, section=CONFIG_SECTION):
if name.startswith("email_"):
# XXX: email_ parameters were first in [plugin account] section
# but as it make more sense to have them in common with other plugins,
# they can now be in [DEFAULT] section
try:
value = self.host.memory.getConfig(None, name, Exception)
value = self.host.memory.config_get(None, name, Exception)
except (configparser.NoOptionError, configparser.NoSectionError):
pass
else:
@ -209,9 +209,9 @@ class MiscAccount(object):
default = default_conf[name]
else:
default = None
return self.host.memory.getConfig(section, name, default)
return self.host.memory.config_get(section, name, default)
def _registerAccount(self, email, password, profile):
def _register_account(self, email, password, profile):
return self.registerAccount(email, password, None, profile)
def registerAccount(self, email, password, jid_s, profile):
@ -226,11 +226,11 @@ class MiscAccount(object):
@param profile
@return Deferred
"""
d = self.createProfile(password, jid_s, profile)
d.addCallback(lambda __: self.sendEmails(email, profile))
d = self.create_profile(password, jid_s, profile)
d.addCallback(lambda __: self.send_emails(email, profile))
return d
def createProfile(self, password, jid_s, profile):
def create_profile(self, password, jid_s, profile):
"""Register a new profile and its associated XMPP account.
@param password (unicode): password chosen by the user
@ -244,14 +244,14 @@ class MiscAccount(object):
if not password or not profile:
raise exceptions.DataError
if profile.lower() in self.getConfig("reserved_list"):
if profile.lower() in self.config_get("reserved_list"):
return defer.fail(Failure(exceptions.ConflictError))
d = self.host.memory.createProfile(profile, password)
d.addCallback(lambda __: self.profileCreated(password, jid_s, profile))
d = self.host.memory.create_profile(profile, password)
d.addCallback(lambda __: self.profile_created(password, jid_s, profile))
return d
def profileCreated(self, password, jid_s, profile):
def profile_created(self, password, jid_s, profile):
"""Create the XMPP account and set the profile connection parameters.
@param password (unicode): password chosen by the user
@ -265,30 +265,30 @@ class MiscAccount(object):
d = defer.succeed(None)
jid_ = jid.JID(jid_s)
else:
jid_s = profile + "@" + self.getNewAccountDomain()
jid_s = profile + "@" + self.account_domain_new_get()
jid_ = jid.JID(jid_s)
d = self.host.plugins["XEP-0077"].registerNewAccount(jid_, password)
d = self.host.plugins["XEP-0077"].register_new_account(jid_, password)
def setParams(__):
self.host.memory.setParam(
self.host.memory.param_set(
"JabberID", jid_s, "Connection", profile_key=profile
)
d = self.host.memory.setParam(
d = self.host.memory.param_set(
"Password", password, "Connection", profile_key=profile
)
return d
def removeProfile(failure):
self.host.memory.asyncDeleteProfile(profile)
def remove_profile(failure):
self.host.memory.profile_delete_async(profile)
return failure
d.addCallback(lambda __: self.host.memory.startSession(password, profile))
d.addCallback(lambda __: self.host.memory.start_session(password, profile))
d.addCallback(setParams)
d.addCallback(lambda __: self.host.memory.stopSession(profile))
d.addErrback(removeProfile)
d.addCallback(lambda __: self.host.memory.stop_session(profile))
d.addErrback(remove_profile)
return d
def _sendEmailEb(self, failure_, email):
def _send_email_eb(self, failure_, email):
# TODO: return error code to user
log.error(
_("Failed to send account creation confirmation to {email}: {msg}").format(
@ -296,13 +296,13 @@ class MiscAccount(object):
)
)
def sendEmails(self, email, profile):
def send_emails(self, email, profile):
# time to send the email
domain = self.getNewAccountDomain()
domain = self.account_domain_new_get()
# email to the administrators
admins_emails = self.getConfig("email_admins_list")
admins_emails = self.config_get("email_admins_list")
if not admins_emails:
log.warning(
"No known admin email, we can't send email to administrator(s).\n"
@ -313,7 +313,7 @@ class MiscAccount(object):
subject = _("New Libervia account created")
# there is no email when an existing XMPP account is used
body = f"New account created on {domain}: {profile} [{email or '<no email>'}]"
d_admin = sat_email.sendEmail(
d_admin = sat_email.send_email(
self.host.memory.config, admins_emails, subject, body)
admins_emails_txt = ", ".join(["<" + addr + ">" for addr in admins_emails])
@ -333,7 +333,7 @@ class MiscAccount(object):
# TODO: if use register with an existing account, an XMPP message should be sent
return d_admin
jid_s = self.host.memory.getParamA(
jid_s = self.host.memory.param_get_a(
"JabberID", "Connection", profile_key=profile
)
subject = _("Your Libervia account has been created")
@ -342,20 +342,20 @@ class MiscAccount(object):
# XXX: this will not fail when the email address doesn't exist
# FIXME: check email reception to validate email given by the user
# FIXME: delete the profile if the email could not been sent?
d_user = sat_email.sendEmail(self.host.memory.config, [email], subject, body)
d_user = sat_email.send_email(self.host.memory.config, [email], subject, body)
d_user.addCallbacks(
lambda __: log.debug(
"Account creation confirmation sent to <{}>".format(email)
),
self._sendEmailEb,
self._send_email_eb,
errbackArgs=[email]
)
return defer.DeferredList([d_user, d_admin])
def getNewAccountDomain(self):
def account_domain_new_get(self):
"""get the domain that will be set to new account"""
domain = self.getConfig("new_account_domain") or self.getConfig(
domain = self.config_get("new_account_domain") or self.config_get(
"xmpp_domain", None
)
if not domain:
@ -367,7 +367,7 @@ class MiscAccount(object):
return DEFAULT_DOMAIN
return domain
def _getAccountDialogUI(self, profile):
def _get_account_dialog_ui(self, profile):
"""Get the main dialog to manage your account
@param menu_data
@param profile: %(doc_profile)s
@ -381,7 +381,7 @@ class MiscAccount(object):
)
tab_container = form_ui.current_container
tab_container.addTab(
tab_container.add_tab(
"update", D_("Change your password"), container=xml_tools.PairsContainer
)
form_ui.addLabel(D_("Current profile password"))
@ -394,7 +394,7 @@ class MiscAccount(object):
# FIXME: uncomment and fix these features
"""
if 'GROUPBLOG' in self.host.plugins:
tab_container.addTab("delete_posts", D_("Delete your posts"), container=xml_tools.PairsContainer)
tab_container.add_tab("delete_posts", D_("Delete your posts"), container=xml_tools.PairsContainer)
form_ui.addLabel(D_("Current profile password"))
form_ui.addPassword("delete_posts_passwd", value="")
form_ui.addLabel(D_("Delete all your posts and their comments"))
@ -402,7 +402,7 @@ class MiscAccount(object):
form_ui.addLabel(D_("Delete all your comments on other's posts"))
form_ui.addBool("delete_comments_checkbox", "false")
tab_container.addTab("delete", D_("Delete your account"), container=xml_tools.PairsContainer)
tab_container.add_tab("delete", D_("Delete your account"), container=xml_tools.PairsContainer)
form_ui.addLabel(D_("Current profile password"))
form_ui.addPassword("delete_passwd", value="")
form_ui.addLabel(D_("Delete your account"))
@ -412,12 +412,12 @@ class MiscAccount(object):
return form_ui.toXml()
@defer.inlineCallbacks
def _accountDialogCb(self, data, profile):
def _account_dialog_cb(self, data, profile):
"""Called when the user submits the main account dialog
@param data
@param profile
"""
sat_cipher = yield self.host.memory.asyncGetParamA(
sat_cipher = yield self.host.memory.param_get_a_async(
C.PROFILE_PASS_PATH[1], C.PROFILE_PASS_PATH[0], profile_key=profile
)
@ -442,7 +442,7 @@ class MiscAccount(object):
verified = yield verify(delete_passwd)
assert isinstance(verified, bool)
if verified:
defer.returnValue(self.__deleteAccount(profile))
defer.returnValue(self.__delete_account(profile))
defer.returnValue(error_ui())
# check for blog posts deletion
@ -456,7 +456,7 @@ class MiscAccount(object):
verified = yield verify(delete_posts_passwd)
assert isinstance(verified, bool)
if verified:
defer.returnValue(self.__deleteBlogPosts(posts, comments, profile))
defer.returnValue(self.__delete_blog_posts(posts, comments, profile))
defer.returnValue(error_ui())
"""
@ -469,7 +469,7 @@ class MiscAccount(object):
assert isinstance(verified, bool)
if verified:
if new_passwd1 == new_passwd2:
data = yield self.__changePassword(new_passwd1, profile=profile)
data = yield self.__change_password(new_passwd1, profile=profile)
defer.returnValue(data)
else:
defer.returnValue(
@ -481,13 +481,13 @@ class MiscAccount(object):
defer.returnValue({})
def __changePassword(self, password, profile):
def __change_password(self, password, profile):
"""Ask for a confirmation before changing the XMPP account and SàT profile passwords.
@param password (str): the new password
@param profile (str): %(doc_profile)s
"""
session_id, __ = self._sessions.newSession(
session_id, __ = self._sessions.new_session(
{"new_password": password}, profile=profile
)
form_ui = xml_tools.XMLUI(
@ -504,24 +504,24 @@ class MiscAccount(object):
form_ui.addText(D_("Continue with changing the password?"))
return {"xmlui": form_ui.toXml()}
def __changePasswordCb(self, data, profile):
def __change_password_cb(self, data, profile):
"""Actually change the user XMPP account and SàT profile password
@param data (dict)
@profile (str): %(doc_profile)s
"""
client = self.host.getClient(profile)
password = self._sessions.profileGet(data["session_id"], profile)["new_password"]
client = self.host.get_client(profile)
password = self._sessions.profile_get(data["session_id"], profile)["new_password"]
del self._sessions[data["session_id"]]
def passwordChanged(__):
d = self.host.memory.setParam(
def password_changed(__):
d = self.host.memory.param_set(
C.PROFILE_PASS_PATH[1],
password,
C.PROFILE_PASS_PATH[0],
profile_key=profile,
)
d.addCallback(
lambda __: self.host.memory.setParam(
lambda __: self.host.memory.param_set(
"Password", password, "Connection", profile_key=profile
)
)
@ -536,11 +536,11 @@ class MiscAccount(object):
)
return defer.succeed({"xmlui": error_ui.toXml()})
d = self.host.plugins["XEP-0077"].changePassword(client, password)
d.addCallbacks(passwordChanged, errback)
d = self.host.plugins["XEP-0077"].change_password(client, password)
d.addCallbacks(password_changed, errback)
return d
def __deleteAccount(self, profile):
def __delete_account(self, profile):
"""Ask for a confirmation before deleting the XMPP account and SàT profile
@param profile
"""
@ -561,7 +561,7 @@ class MiscAccount(object):
D_(
"All your data stored on %(server)s, including your %(target)s will be erased."
)
% {"server": self.getNewAccountDomain(), "target": target}
% {"server": self.account_domain_new_get(), "target": target}
)
form_ui.addText(
D_(
@ -570,26 +570,26 @@ class MiscAccount(object):
)
return {"xmlui": form_ui.toXml()}
def __deleteAccountCb(self, data, profile):
def __delete_account_cb(self, data, profile):
"""Actually delete the XMPP account and SàT profile
@param data
@param profile
"""
client = self.host.getClient(profile)
client = self.host.get_client(profile)
def userDeleted(__):
def user_deleted(__):
# FIXME: client should be disconnected at this point, so 2 next loop should be removed (to be confirmed)
for jid_ in client.roster._jids: # empty roster
client.presence.unsubscribe(jid_)
for jid_ in self.host.memory.getWaitingSub(
for jid_ in self.host.memory.sub_waiting_get(
profile
): # delete waiting subscriptions
self.host.memory.delWaitingSub(jid_)
self.host.memory.del_waiting_sub(jid_)
delete_profile = lambda: self.host.memory.asyncDeleteProfile(
delete_profile = lambda: self.host.memory.profile_delete_async(
profile, force=True
)
if "GROUPBLOG" in self.host.plugins:
@ -611,10 +611,10 @@ class MiscAccount(object):
return defer.succeed({"xmlui": error_ui.toXml()})
d = self.host.plugins["XEP-0077"].unregister(client, jid.JID(client.jid.host))
d.addCallbacks(userDeleted, errback)
d.addCallbacks(user_deleted, errback)
return d
def __deleteBlogPosts(self, posts, comments, profile):
def __delete_blog_posts(self, posts, comments, profile):
"""Ask for a confirmation before deleting the blog posts
@param posts: delete all posts of the user (and their comments)
@param comments: delete all the comments of the user on other's posts
@ -678,7 +678,7 @@ class MiscAccount(object):
return {"xmlui": form_ui.toXml()}
def __deleteBlogPostsCb(self, posts, comments, data, profile):
def __delete_blog_posts_cb(self, posts, comments, data, profile):
"""Actually delete the XMPP account and SàT profile
@param posts: delete all posts of the user (and their comments)
@param comments: delete all the comments of the user on other's posts
@ -723,7 +723,7 @@ class MiscAccount(object):
d.addCallbacks(deleted, errback)
return d
def asyncConnectWithXMPPCredentials(self, jid_s, password):
def credentials_xmpp_connect(self, jid_s, password):
"""Create and connect a new SàT profile using the given XMPP credentials.
Re-use given JID and XMPP password for the profile name and profile password.
@ -733,34 +733,34 @@ class MiscAccount(object):
@raise exceptions.PasswordError, exceptions.ConflictError
"""
try: # be sure that the profile doesn't exist yet
self.host.memory.getProfileName(jid_s)
self.host.memory.get_profile_name(jid_s)
except exceptions.ProfileUnknownError:
pass
else:
raise exceptions.ConflictError
d = self.createProfile(password, jid_s, jid_s)
d = self.create_profile(password, jid_s, jid_s)
d.addCallback(
lambda __: self.host.memory.getProfileName(jid_s)
lambda __: self.host.memory.get_profile_name(jid_s)
) # checks if the profile has been successfuly created
d.addCallback(lambda profile: defer.ensureDeferred(
self.host.connect(profile, password, {}, 0)))
def connected(result):
self.sendEmails(None, profile=jid_s)
self.send_emails(None, profile=jid_s)
return result
def removeProfile(
def remove_profile(
failure
): # profile has been successfully created but the XMPP credentials are wrong!
log.debug(
"Removing previously auto-created profile: %s" % failure.getErrorMessage()
)
self.host.memory.asyncDeleteProfile(jid_s)
self.host.memory.profile_delete_async(jid_s)
raise failure
# FIXME: we don't catch the case where the JID host is not an XMPP server, and the user
# has to wait until the DBUS timeout ; as a consequence, emails are sent to the admins
# and the profile is not deleted. When the host exists, removeProfile is well called.
d.addCallbacks(connected, removeProfile)
# and the profile is not deleted. When the host exists, remove_profile is well called.
d.addCallbacks(connected, remove_profile)
return d

View file

@ -143,7 +143,7 @@ class Notification(AndroidNotification):
notification_intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
notification_intent.setAction(Intent.ACTION_MAIN)
notification_intent.addCategory(Intent.CATEGORY_LAUNCHER)
notification_intent.add_category(Intent.CATEGORY_LAUNCHER)
if sat_action is not None:
action_data = AndroidString(json.dumps(sat_action).encode())
log.debug(f"adding extra {INTENT_EXTRA_ACTION} ==> {action_data}")
@ -233,10 +233,10 @@ class AndroidPlugin(object):
category_label=D_(PARAM_VIBRATE_CATEGORY),
vibrate_param_name=PARAM_VIBRATE_NAME,
vibrate_param_label=PARAM_VIBRATE_LABEL,
vibrate_options=params.makeOptions(VIBRATION_OPTS, "always"),
vibrate_options=params.make_options(VIBRATION_OPTS, "always"),
ring_param_name=PARAM_RING_NAME,
ring_param_label=PARAM_RING_LABEL,
ring_options=params.makeOptions(RING_OPTS, "normal"),
ring_options=params.make_options(RING_OPTS, "normal"),
)
def __init__(self, host):
@ -245,7 +245,7 @@ class AndroidPlugin(object):
self.host = host
self._csi = host.plugins.get('XEP-0352')
self._csi_timer = None
host.memory.updateParams(self.params)
host.memory.update_params(self.params)
try:
os.mkdir(SOCKET_DIR, 0o700)
except OSError as e:
@ -268,15 +268,15 @@ class AndroidPlugin(object):
raise e
# we set a low priority because we want the notification to be sent after all
# plugins have done their job
host.trigger.add("messageReceived", self.messageReceivedTrigger, priority=-1000)
host.trigger.add("messageReceived", self.message_received_trigger, priority=-1000)
# profiles autoconnection
host.bridge.addMethod(
"profileAutoconnectGet",
host.bridge.add_method(
"profile_autoconnect_get",
".plugin",
in_sign="",
out_sign="s",
method=self._profileAutoconnectGet,
method=self._profile_autoconnect_get,
async_=True,
)
@ -284,7 +284,7 @@ class AndroidPlugin(object):
self.am = activity.getSystemService(Context.AUDIO_SERVICE)
# sound notification
media_dir = Path(host.memory.getConfig("", "media_dir"))
media_dir = Path(host.memory.config_get("", "media_dir"))
assert media_dir is not None
notif_path = media_dir / "sounds" / "notifications" / "music-box.mp3"
self.notif_player = MediaPlayer()
@ -297,20 +297,20 @@ class AndroidPlugin(object):
log.info("SSL Android patch applied")
# DNS fix
defer.ensureDeferred(self.updateResolver())
defer.ensureDeferred(self.update_resolver())
# Connectivity handling
self.cm = activity.getSystemService(Context.CONNECTIVITY_SERVICE)
self._net_type = None
d = defer.ensureDeferred(self._checkConnectivity())
d.addErrback(host.logErrback)
d = defer.ensureDeferred(self._check_connectivity())
d.addErrback(host.log_errback)
# XXX: we need to keep a reference to BroadcastReceiver to avoid
# "XXX has no attribute 'invoke'" error (looks like the same issue as
# https://github.com/kivy/pyjnius/issues/59)
self.br = BroadcastReceiver(
callback=lambda *args, **kwargs: reactor.callFromThread(
self.onConnectivityChange
self.on_connectivity_change
),
actions=["android.net.conn.CONNECTIVITY_CHANGE"]
)
@ -326,29 +326,29 @@ class AndroidPlugin(object):
previous_state = self._state
self._state = new_state
if new_state == STATE_RUNNING:
self._onRunning(previous_state)
self._on_running(previous_state)
elif new_state == STATE_PAUSED:
self._onPaused(previous_state)
self._on_paused(previous_state)
elif new_state == STATE_STOPPED:
self._onStopped(previous_state)
self._on_stopped(previous_state)
@property
def cagou_active(self):
return self._state == STATE_RUNNING
def _onRunning(self, previous_state):
def _on_running(self, previous_state):
if previous_state is not None:
self.host.bridge.bridgeReactivateSignals()
self.setActive()
self.host.bridge.bridge_reactivate_signals()
self.set_active()
def _onPaused(self, previous_state):
self.host.bridge.bridgeDeactivateSignals()
self.setInactive()
def _on_paused(self, previous_state):
self.host.bridge.bridge_deactivate_signals()
self.set_inactive()
def _onStopped(self, previous_state):
self.setInactive()
def _on_stopped(self, previous_state):
self.set_inactive()
def _notifyMessage(self, mess_data, client):
def _notify_message(self, mess_data, client):
"""Send notification when suitable
notification is sent if:
@ -378,7 +378,7 @@ class AndroidPlugin(object):
ringer_mode = self.am.getRingerMode()
vibrate_mode = ringer_mode == AudioManager.RINGER_MODE_VIBRATE
ring_setting = self.host.memory.getParamA(
ring_setting = self.host.memory.param_get_a(
PARAM_RING_NAME,
PARAM_RING_CATEGORY,
profile_key=client.profile
@ -387,7 +387,7 @@ class AndroidPlugin(object):
if ring_setting != 'never' and ringer_mode == AudioManager.RINGER_MODE_NORMAL:
self.notif_player.start()
vibration_setting = self.host.memory.getParamA(
vibration_setting = self.host.memory.param_get_a(
PARAM_VIBRATE_NAME,
PARAM_VIBRATE_CATEGORY,
profile_key=client.profile
@ -400,27 +400,27 @@ class AndroidPlugin(object):
log.warning("Can't use vibrator: {e}".format(e=e))
return mess_data
def messageReceivedTrigger(self, client, message_elt, post_treat):
def message_received_trigger(self, client, message_elt, post_treat):
if not self.cagou_active:
# we only send notification is the frontend is not displayed
post_treat.addCallback(self._notifyMessage, client)
post_treat.addCallback(self._notify_message, client)
return True
# Profile autoconnection
def _profileAutoconnectGet(self):
return defer.ensureDeferred(self.profileAutoconnectGet())
def _profile_autoconnect_get(self):
return defer.ensureDeferred(self.profile_autoconnect_get())
async def _getProfilesAutoconnect(self):
autoconnect_dict = await self.host.memory.storage.getIndParamValues(
async def _get_profiles_autoconnect(self):
autoconnect_dict = await self.host.memory.storage.get_ind_param_values(
category='Connection', name='autoconnect_backend',
)
return [p for p, v in autoconnect_dict.items() if C.bool(v)]
async def profileAutoconnectGet(self):
async def profile_autoconnect_get(self):
"""Return profile to connect automatically by frontend, if any"""
profiles_autoconnect = await self._getProfilesAutoconnect()
profiles_autoconnect = await self._get_profiles_autoconnect()
if not profiles_autoconnect:
return None
if len(profiles_autoconnect) > 1:
@ -431,56 +431,56 @@ class AndroidPlugin(object):
# CSI
def _setInactive(self):
def _set_inactive(self):
self._csi_timer = None
for client in self.host.getClients(C.PROF_KEY_ALL):
self._csi.setInactive(client)
for client in self.host.get_clients(C.PROF_KEY_ALL):
self._csi.set_inactive(client)
def setInactive(self):
def set_inactive(self):
if self._csi is None or self._csi_timer is not None:
return
self._csi_timer = reactor.callLater(CSI_DELAY, self._setInactive)
self._csi_timer = reactor.callLater(CSI_DELAY, self._set_inactive)
def setActive(self):
def set_active(self):
if self._csi is None:
return
if self._csi_timer is not None:
self._csi_timer.cancel()
self._csi_timer = None
for client in self.host.getClients(C.PROF_KEY_ALL):
self._csi.setActive(client)
for client in self.host.get_clients(C.PROF_KEY_ALL):
self._csi.set_active(client)
# Connectivity
async def _handleNetworkChange(self, net_type):
async def _handle_network_change(self, net_type):
"""Notify the clients about network changes.
This way the client can disconnect/reconnect transport, or change delays
"""
log.debug(f"handling network change ({net_type})")
if net_type == NET_TYPE_NONE:
for client in self.host.getClients(C.PROF_KEY_ALL):
client.networkDisabled()
for client in self.host.get_clients(C.PROF_KEY_ALL):
client.network_disabled()
else:
# DNS servers may have changed
await self.updateResolver()
await self.update_resolver()
# client may be there but disabled (e.g. with stream management)
for client in self.host.getClients(C.PROF_KEY_ALL):
for client in self.host.get_clients(C.PROF_KEY_ALL):
log.debug(f"enabling network for {client.profile}")
client.networkEnabled()
client.network_enabled()
# profiles may have been disconnected and then purged, we try
# to reconnect them in case
profiles_autoconnect = await self._getProfilesAutoconnect()
profiles_autoconnect = await self._get_profiles_autoconnect()
for profile in profiles_autoconnect:
if not self.host.isConnected(profile):
if not self.host.is_connected(profile):
log.info(f"{profile} is not connected, reconnecting it")
try:
await self.host.connect(profile)
except Exception as e:
log.error(f"Can't connect profile {profile}: {e}")
async def _checkConnectivity(self):
async def _check_connectivity(self):
active_network = self.cm.getActiveNetworkInfo()
if active_network is None:
net_type = NET_TYPE_NONE
@ -506,24 +506,24 @@ class AndroidPlugin(object):
log.info("network activated (type={net_type_android})"
.format(net_type_android=net_type_android))
else:
log.debug("_checkConnectivity called without network change ({net_type})"
log.debug("_check_connectivity called without network change ({net_type})"
.format(net_type = net_type))
# we always call _handleNetworkChange even if there is not connectivity change
# we always call _handle_network_change even if there is not connectivity change
# to be sure to reconnect when necessary
await self._handleNetworkChange(net_type)
await self._handle_network_change(net_type)
def onConnectivityChange(self):
log.debug("onConnectivityChange called")
d = defer.ensureDeferred(self._checkConnectivity())
d.addErrback(self.host.logErrback)
def on_connectivity_change(self):
log.debug("on_connectivity_change called")
d = defer.ensureDeferred(self._check_connectivity())
d.addErrback(self.host.log_errback)
async def updateResolver(self):
async def update_resolver(self):
# There is no "/etc/resolv.conf" on Android, which confuse Twisted and makes
# SRV record checking unusable. We fixe that by checking DNS server used, and
# updating Twisted's resolver accordingly
dns_servers = await self.getDNSServers()
dns_servers = await self.get_dns_servers()
log.info(
"Patching Twisted to use Android DNS resolver ({dns_servers})".format(
@ -531,7 +531,7 @@ class AndroidPlugin(object):
)
dns_client.theResolver = dns_client.createResolver(servers=dns_servers)
async def getDNSServers(self):
async def get_dns_servers(self):
servers = []
if api_version < 26:

View file

@ -84,31 +84,31 @@ class AppManager:
self._started = {}
# instance id to app data map
self._instances = {}
host.bridge.addMethod(
"applicationsList",
host.bridge.add_method(
"applications_list",
".plugin",
in_sign="as",
out_sign="as",
method=self.list_applications,
)
host.bridge.addMethod(
"applicationStart",
host.bridge.add_method(
"application_start",
".plugin",
in_sign="ss",
out_sign="s",
method=self._start,
async_=True,
)
host.bridge.addMethod(
"applicationStop",
host.bridge.add_method(
"application_stop",
".plugin",
in_sign="sss",
out_sign="",
method=self._stop,
async_=True,
)
host.bridge.addMethod(
"applicationExposedGet",
host.bridge.add_method(
"application_exposed_get",
".plugin",
in_sign="sss",
out_sign="s",
@ -117,12 +117,12 @@ class AppManager:
)
# application has been started succeesfully,
# args: name, instance_id, extra
host.bridge.addSignal(
host.bridge.add_signal(
"application_started", ".plugin", signature="sss"
)
# application went wrong with the application
# args: name, instance_id, extra
host.bridge.addSignal(
host.bridge.add_signal(
"application_error", ".plugin", signature="sss"
)
yaml.add_constructor(
@ -169,7 +169,7 @@ class AppManager:
"expected"
)
value = self.host.memory.getConfig(section, name, default)
value = self.host.memory.config_get(section, name, default)
# FIXME: "public_url" is used only here and doesn't take multi-sites into account
if name == "public_url" and (not value or value.startswith('http')):
if not value:
@ -408,7 +408,7 @@ class AppManager:
log.info(f"{app_name!r} is already started or being started")
return ret_data
else:
cache_path = self.host.memory.getCachePath(
cache_path = self.host.memory.get_cache_path(
PLUGIN_INFO[C.PI_IMPORT_NAME], app_name
)
cache_path.mkdir(0o700, parents=True, exist_ok=True)

View file

@ -58,10 +58,10 @@ class AttachPlugin:
log.info(_("plugin Attach initialization"))
self.host = host
self._u = host.plugins["UPLOAD"]
host.trigger.add("sendMessage", self._sendMessageTrigger)
host.trigger.add("sendMessageComponent", self._sendMessageTrigger)
host.trigger.add("sendMessage", self._send_message_trigger)
host.trigger.add("sendMessageComponent", self._send_message_trigger)
self._attachments_handlers = {'clear': [], 'encrypted': []}
self.register(self.defaultCanHandle, self.defaultAttach, False, -1000)
self.register(self.default_can_handle, self.default_attach, False, -1000)
def register(self, can_handle, attach, encrypted=False, priority=0):
"""Register an attachments handler
@ -94,7 +94,7 @@ class AttachPlugin:
handlers.sort(key=lambda h: h.priority, reverse=True)
log.debug(f"new attachments handler: {handler}")
async def attachFiles(self, client, data):
async def attach_files(self, client, data):
"""Main method to attach file
It will do generic pre-treatment, and call the suitable attachments handler
@ -135,13 +135,13 @@ class AttachPlugin:
_("Can't resize attachment of type {main_type!r}: {attachment}")
.format(main_type=main_type, attachment=attachment))
if client.encryption.isEncryptionRequested(data):
if client.encryption.is_encryption_requested(data):
handlers = self._attachments_handlers['encrypted']
else:
handlers = self._attachments_handlers['clear']
for handler in handlers:
can_handle = await utils.asDeferred(handler.can_handle, client, data)
can_handle = await utils.as_deferred(handler.can_handle, client, data)
if can_handle:
break
else:
@ -150,7 +150,7 @@ class AttachPlugin:
destinee = data['to']
))
await utils.asDeferred(handler.attach, client, data)
await utils.as_deferred(handler.attach, client, data)
for dir_path in tmp_dirs_to_clean:
log.debug(f"Cleaning temporary directory at {dir_path}")
@ -220,7 +220,7 @@ class AttachPlugin:
progress_id = attachment.pop("progress_id", None)
if progress_id:
extra["progress_id"] = progress_id
check_certificate = self.host.memory.getParamA(
check_certificate = self.host.memory.param_get_a(
"check_certificate", "Connection", profile_key=client.profile)
if not check_certificate:
extra['ignore_tls_errors'] = True
@ -251,19 +251,19 @@ class AttachPlugin:
return data
def _attachFiles(self, data, client):
return defer.ensureDeferred(self.attachFiles(client, data))
def _attach_files(self, data, client):
return defer.ensureDeferred(self.attach_files(client, data))
def _sendMessageTrigger(
def _send_message_trigger(
self, client, mess_data, pre_xml_treatments, post_xml_treatments):
if mess_data['extra'].get(C.KEY_ATTACHMENTS):
post_xml_treatments.addCallback(self._attachFiles, client=client)
post_xml_treatments.addCallback(self._attach_files, client=client)
return True
async def defaultCanHandle(self, client, data):
async def default_can_handle(self, client, data):
return True
async def defaultAttach(self, client, data):
async def default_attach(self, client, data):
await self.upload_files(client, data)
# TODO: handle xhtml-im
body_elt = data["xml"].body

View file

@ -40,15 +40,15 @@ class Debug(object):
def __init__(self, host):
log.info(_("Plugin Debug initialization"))
self.host = host
host.bridge.addMethod(
"debugFakeSignal",
host.bridge.add_method(
"debug_signal_fake",
".plugin",
in_sign="sss",
out_sign="",
method=self._fakeSignal,
method=self._fake_signal,
)
def _fakeSignal(self, signal, arguments, profile_key):
def _fake_signal(self, signal, arguments, profile_key):
"""send a signal from backend
@param signal(str): name of the signal
@ -58,6 +58,6 @@ class Debug(object):
args = json.loads(arguments)
method = getattr(self.host.bridge, signal)
if profile_key != C.PROF_KEY_NONE:
profile = self.host.memory.getProfileName(profile_key)
profile = self.host.memory.get_profile_name(profile_key)
args.append(profile)
method(*args)

View file

@ -54,20 +54,20 @@ class DownloadPlugin(object):
def __init__(self, host):
log.info(_("plugin Download initialization"))
self.host = host
host.bridge.addMethod(
"fileDownload",
host.bridge.add_method(
"file_download",
".plugin",
in_sign="ssss",
out_sign="s",
method=self._fileDownload,
method=self._file_download,
async_=True,
)
host.bridge.addMethod(
"fileDownloadComplete",
host.bridge.add_method(
"file_download_complete",
".plugin",
in_sign="ssss",
out_sign="s",
method=self._fileDownloadComplete,
method=self._file_download_complete,
async_=True,
)
self._download_callbacks = {}
@ -75,11 +75,11 @@ class DownloadPlugin(object):
self.register_scheme('http', self.download_http)
self.register_scheme('https', self.download_http)
def _fileDownload(
def _file_download(
self, attachment_s: str, dest_path: str, extra_s: str, profile: str
) -> defer.Deferred:
d = defer.ensureDeferred(self.file_download(
self.host.getClient(profile),
self.host.get_client(profile),
data_format.deserialise(attachment_s),
Path(dest_path),
data_format.deserialise(extra_s)
@ -118,11 +118,11 @@ class DownloadPlugin(object):
else:
return {"progress": progress_id}
def _fileDownloadComplete(
def _file_download_complete(
self, attachment_s: str, dest_path: str, extra_s: str, profile: str
) -> defer.Deferred:
d = defer.ensureDeferred(self.file_download_complete(
self.host.getClient(profile),
self.host.get_client(profile),
data_format.deserialise(attachment_s),
Path(dest_path),
data_format.deserialise(extra_s)
@ -168,7 +168,7 @@ class DownloadPlugin(object):
# we hash the URL to have an unique identifier, and avoid double download
url_hash = hashlib.sha256(uri_parsed.geturl().encode()).hexdigest()
cache_uid = f"{stem}_{url_hash}"
cache_data = client.cache.getMetadata(cache_uid)
cache_data = client.cache.get_metadata(cache_uid)
if cache_data is not None:
# file is already in cache, we return it
download_d = defer.succeed(cache_data['path'])
@ -176,14 +176,14 @@ class DownloadPlugin(object):
else:
# the file is not in cache
unique_name = '.'.join([cache_uid] + suffixes)
with client.cache.cacheData(
with client.cache.cache_data(
"DOWNLOAD", cache_uid, filename=unique_name) as f:
# we close the file and only use its name, the file will be opened
# by the registered callback
dest_path = Path(f.name)
# should we check certificates?
check_certificate = self.host.memory.getParamA(
check_certificate = self.host.memory.param_get_a(
"check_certificate", "Connection", profile_key=client.profile)
if not check_certificate:
extra['ignore_tls_errors'] = True
@ -203,7 +203,7 @@ class DownloadPlugin(object):
"Can't download URI {uri}: {reason}").format(
uri=uri, reason=e))
if cache_uid is not None:
client.cache.removeFromCache(cache_uid)
client.cache.remove_from_cache(cache_uid)
elif dest_path.exists():
dest_path.unlink()
raise e

View file

@ -77,30 +77,30 @@ class InvitationsPlugin(object):
log.info(_("plugin Invitations initialization"))
self.host = host
self.invitations = persistent.LazyPersistentBinaryDict('invitations')
host.bridge.addMethod("invitationCreate", ".plugin", in_sign='sasssssssssa{ss}s',
host.bridge.add_method("invitation_create", ".plugin", in_sign='sasssssssssa{ss}s',
out_sign='a{ss}',
method=self._create,
async_=True)
host.bridge.addMethod("invitationGet", ".plugin", in_sign='s', out_sign='a{ss}',
host.bridge.add_method("invitation_get", ".plugin", in_sign='s', out_sign='a{ss}',
method=self.get,
async_=True)
host.bridge.addMethod("invitationDelete", ".plugin", in_sign='s', out_sign='',
host.bridge.add_method("invitation_delete", ".plugin", in_sign='s', out_sign='',
method=self._delete,
async_=True)
host.bridge.addMethod("invitationModify", ".plugin", in_sign='sa{ss}b',
host.bridge.add_method("invitation_modify", ".plugin", in_sign='sa{ss}b',
out_sign='',
method=self._modify,
async_=True)
host.bridge.addMethod("invitationList", ".plugin", in_sign='s',
host.bridge.add_method("invitation_list", ".plugin", in_sign='s',
out_sign='a{sa{ss}}',
method=self._list,
async_=True)
host.bridge.addMethod("invitationSimpleCreate", ".plugin", in_sign='sssss',
host.bridge.add_method("invitation_simple_create", ".plugin", in_sign='sssss',
out_sign='a{ss}',
method=self._simpleCreate,
method=self._simple_create,
async_=True)
def checkExtra(self, extra):
def check_extra(self, extra):
if EXTRA_RESERVED.intersection(extra):
raise ValueError(
_("You can't use following key(s) in extra, they are reserved: {}")
@ -132,7 +132,7 @@ class InvitationsPlugin(object):
kwargs[key] = str(value)
return defer.ensureDeferred(self.create(**kwargs))
async def getExistingInvitation(self, email: Optional[str]) -> Optional[dict]:
async def get_existing_invitation(self, email: Optional[str]) -> Optional[dict]:
"""Retrieve existing invitation with given email
@param email: check if any invitation exist with this email
@ -151,7 +151,7 @@ class InvitationsPlugin(object):
invitation[KEY_ID] = id_
return invitation
async def _createAccountAndProfile(
async def _create_account_and_profile(
self,
id_: str,
kwargs: dict,
@ -161,7 +161,7 @@ class InvitationsPlugin(object):
## XMPP account creation
password = kwargs.pop('password', None)
if password is None:
password = utils.generatePassword()
password = utils.generate_password()
assert password
# XXX: password is here saved in clear in database
# it is needed for invitation as the same password is used for profile
@ -173,7 +173,7 @@ class InvitationsPlugin(object):
jid_ = kwargs.pop('jid_', None)
if not jid_:
domain = self.host.memory.getConfig(None, 'xmpp_domain')
domain = self.host.memory.config_get(None, 'xmpp_domain')
if not domain:
# TODO: fallback to profile's domain
raise ValueError(_("You need to specify xmpp_domain in sat.conf"))
@ -186,7 +186,7 @@ class InvitationsPlugin(object):
# we don't register account if there is no user as anonymous login is then
# used
try:
await self.host.plugins['XEP-0077'].registerNewAccount(jid_, password)
await self.host.plugins['XEP-0077'].register_new_account(jid_, password)
except error.StanzaError as e:
prefix = jid_.user
idx = 0
@ -197,7 +197,7 @@ class InvitationsPlugin(object):
log.info(_("requested jid already exists, trying with {}".format(
jid_.full())))
try:
await self.host.plugins['XEP-0077'].registerNewAccount(
await self.host.plugins['XEP-0077'].register_new_account(
jid_,
password
)
@ -216,11 +216,11 @@ class InvitationsPlugin(object):
uuid=id_
)
# profile creation should not fail as we generate unique name ourselves
await self.host.memory.createProfile(guest_profile, password)
await self.host.memory.startSession(password, guest_profile)
await self.host.memory.setParam("JabberID", jid_.full(), "Connection",
await self.host.memory.create_profile(guest_profile, password)
await self.host.memory.start_session(password, guest_profile)
await self.host.memory.param_set("JabberID", jid_.full(), "Connection",
profile_key=guest_profile)
await self.host.memory.setParam("Password", password, "Connection",
await self.host.memory.param_set("Password", password, "Connection",
profile_key=guest_profile)
async def create(self, **kwargs):
@ -290,11 +290,11 @@ class InvitationsPlugin(object):
_("You can't use following key(s) in both args and extra: {}").format(
', '.join(set(kwargs).intersection(extra))))
self.checkExtra(extra)
self.check_extra(extra)
email = kwargs.pop('email', None)
existing = await self.getExistingInvitation(email)
existing = await self.get_existing_invitation(email)
if existing is not None:
log.info(f"There is already an invitation for {email!r}")
extra.update(existing)
@ -316,7 +316,7 @@ class InvitationsPlugin(object):
id_ = existing[KEY_ID] if existing else str(shortuuid.uuid())
if existing is None:
await self._createAccountAndProfile(id_, kwargs, extra)
await self._create_account_and_profile(id_, kwargs, extra)
profile = kwargs.pop('profile', None)
guest_profile = extra[KEY_GUEST_PROFILE]
@ -333,8 +333,8 @@ class InvitationsPlugin(object):
pass
else:
await self.host.connect(guest_profile, password)
guest_client = self.host.getClient(guest_profile)
await id_plugin.setIdentity(guest_client, {'nicknames': [name]})
guest_client = self.host.get_client(guest_profile)
await id_plugin.set_identity(guest_client, {'nicknames': [name]})
await self.host.disconnect(guest_profile)
## email
@ -370,7 +370,7 @@ class InvitationsPlugin(object):
invite_url = url_template.format(**format_args)
format_args['url'] = invite_url
await sat_email.sendEmail(
await sat_email.send_email(
self.host.memory.config,
[email] + emails_extra,
(kwargs.pop('message_subject', None) or DEFAULT_SUBJECT).format(
@ -384,11 +384,11 @@ class InvitationsPlugin(object):
# FIXME: a parameter to disable auto roster adding would be nice
if profile is not None:
try:
client = self.host.getClient(profile)
client = self.host.get_client(profile)
except Exception as e:
log.error(f"Can't get host profile: {profile}: {e}")
else:
await self.host.updateContact(client, jid_, name, ['guests'])
await self.host.contact_update(client, jid_, name, ['guests'])
if kwargs:
log.warning(_("Not all arguments have been consumed: {}").format(kwargs))
@ -400,20 +400,20 @@ class InvitationsPlugin(object):
return extra
def _simpleCreate(self, invitee_email, invitee_name, url_template, extra_s, profile):
client = self.host.getClient(profile)
def _simple_create(self, invitee_email, invitee_name, url_template, extra_s, profile):
client = self.host.get_client(profile)
# FIXME: needed because python-dbus use a specific string class
invitee_email = str(invitee_email)
invitee_name = str(invitee_name)
url_template = str(url_template)
extra = data_format.deserialise(extra_s)
d = defer.ensureDeferred(
self.simpleCreate(client, invitee_email, invitee_name, url_template, extra)
self.simple_create(client, invitee_email, invitee_name, url_template, extra)
)
d.addCallback(lambda data: {k: str(v) for k,v in data.items()})
return d
async def simpleCreate(
async def simple_create(
self, client, invitee_email, invitee_name, url_template, extra):
"""Simplified method to invite somebody by email"""
return await self.create(
@ -443,7 +443,7 @@ class InvitationsPlugin(object):
password = data['password']
try:
await self.host.connect(guest_profile, password)
guest_client = self.host.getClient(guest_profile)
guest_client = self.host.get_client(guest_profile)
# XXX: be extra careful to use guest_client and not client below, as this will
# delete the associated XMPP account
log.debug("deleting XMPP account")
@ -453,7 +453,7 @@ class InvitationsPlugin(object):
f"Can't delete {guest_profile}'s XMPP account, maybe it as already been "
f"deleted: {e}")
try:
await self.host.memory.asyncDeleteProfile(guest_profile, True)
await self.host.memory.profile_delete_async(guest_profile, True)
except Exception as e:
log.warning(f"Can't delete guest profile {guest_profile}: {e}")
log.debug("removing guest data")
@ -474,8 +474,8 @@ class InvitationsPlugin(object):
else update them
@raise KeyError: there is not invitation with this id_
"""
self.checkExtra(new_extra)
def gotCurrentData(current_data):
self.check_extra(new_extra)
def got_current_data(current_data):
if replace:
new_data = new_extra
for k in EXTRA_RESERVED:
@ -500,7 +500,7 @@ class InvitationsPlugin(object):
self.invitations[id_] = new_data
d = self.invitations[id_]
d.addCallback(gotCurrentData)
d.addCallback(got_current_data)
return d
def _list(self, profile=C.PROF_KEY_NONE):

View file

@ -62,13 +62,13 @@ class ExtraPEP(object):
"category_label": D_(PARAM_KEY),
"param_name": PARAM_NAME,
"param_label": D_(PARAM_LABEL),
"jids": "\n".join({elt.toXml() for elt in params.createJidElts(PARAM_DEFAULT)}),
"jids": "\n".join({elt.toXml() for elt in params.create_jid_elts(PARAM_DEFAULT)}),
}
def __init__(self, host):
log.info(_("Plugin Extra PEP initialization"))
self.host = host
host.memory.updateParams(self.params)
host.memory.update_params(self.params)
def getFollowedEntities(self, profile_key):
return self.host.memory.getParamA(PARAM_NAME, PARAM_KEY, profile_key=profile_key)
def get_followed_entities(self, profile_key):
return self.host.memory.param_get_a(PARAM_NAME, PARAM_KEY, profile_key=profile_key)

View file

@ -69,24 +69,24 @@ class FilePlugin:
def __init__(self, host):
log.info(_("plugin File initialization"))
self.host = host
host.bridge.addMethod(
"fileSend",
host.bridge.add_method(
"file_send",
".plugin",
in_sign="ssssss",
out_sign="a{ss}",
method=self._fileSend,
method=self._file_send,
async_=True,
)
self._file_managers = []
host.importMenu(
host.import_menu(
(D_("Action"), D_("send file")),
self._fileSendMenu,
self._file_send_menu,
security_limit=10,
help_string=D_("Send a file"),
type_=C.MENU_SINGLE,
)
def _fileSend(
def _file_send(
self,
peer_jid_s: str,
filepath: str,
@ -95,13 +95,13 @@ class FilePlugin:
extra_s: str,
profile: str = C.PROF_KEY_NONE
) -> defer.Deferred:
client = self.host.getClient(profile)
return defer.ensureDeferred(self.fileSend(
client = self.host.get_client(profile)
return defer.ensureDeferred(self.file_send(
client, jid.JID(peer_jid_s), filepath, name or None, file_desc or None,
data_format.deserialise(extra_s)
))
async def fileSend(
async def file_send(
self, client, peer_jid, filepath, filename=None, file_desc=None, extra=None
):
"""Send a file using best available method
@ -119,7 +119,7 @@ class FilePlugin:
if not filename:
filename = os.path.basename(filepath) or "_"
for manager, priority in self._file_managers:
if await utils.asDeferred(manager.canHandleFileSend,
if await utils.as_deferred(manager.can_handle_file_send,
client, peer_jid, filepath):
try:
method_name = manager.name
@ -131,8 +131,8 @@ class FilePlugin:
)
)
try:
progress_id = await utils.asDeferred(
manager.fileSend, client, peer_jid, filepath, filename, file_desc,
progress_id = await utils.as_deferred(
manager.file_send, client, peer_jid, filepath, filename, file_desc,
extra
)
except Exception as e:
@ -155,15 +155,15 @@ class FilePlugin:
).toXml()
}
def _onFileChoosed(self, peer_jid, data, profile):
client = self.host.getClient(profile)
def _on_file_choosed(self, peer_jid, data, profile):
client = self.host.get_client(profile)
cancelled = C.bool(data.get("cancelled", C.BOOL_FALSE))
if cancelled:
return
path = data["path"]
return self.fileSend(client, peer_jid, path)
return self.file_send(client, peer_jid, path)
def _fileSendMenu(self, data, profile):
def _file_send_menu(self, data, profile):
""" XMLUI activated by menu: return file sending UI
@param profile: %(doc_profile)s
@ -173,8 +173,8 @@ class FilePlugin:
except RuntimeError:
raise exceptions.DataError(_("Invalid JID"))
file_choosed_id = self.host.registerCallback(
partial(self._onFileChoosed, jid_),
file_choosed_id = self.host.register_callback(
partial(self._on_file_choosed, jid_),
with_data=True,
one_shot=True,
)
@ -193,7 +193,7 @@ class FilePlugin:
def register(self, manager, priority: int = 0) -> None:
"""Register a fileSending manager
@param manager: object implementing canHandleFileSend, and fileSend methods
@param manager: object implementing can_handle_file_send, and file_send methods
@param priority: pririoty of this manager, the higher available will be used
"""
m_data = (manager, priority)
@ -201,9 +201,9 @@ class FilePlugin:
raise exceptions.ConflictError(
f"Manager {manager} is already registered"
)
if not hasattr(manager, "canHandleFileSend") or not hasattr(manager, "fileSend"):
if not hasattr(manager, "can_handle_file_send") or not hasattr(manager, "file_send"):
raise ValueError(
f'{manager} must have both "canHandleFileSend" and "fileSend" methods to '
f'{manager} must have both "can_handle_file_send" and "file_send" methods to '
'be registered')
self._file_managers.append(m_data)
self._file_managers.sort(key=lambda m: m[1], reverse=True)
@ -219,7 +219,7 @@ class FilePlugin:
# Dialogs with user
# the overwrite check is done here
def openFileWrite(self, client, file_path, transfer_data, file_data, stream_object):
def open_file_write(self, client, file_path, transfer_data, file_data, stream_object):
"""create SatFile or FileStremaObject for the requested file and fill suitable data
"""
if stream_object:
@ -245,15 +245,15 @@ class FilePlugin:
data_cb=file_data.get("data_cb"),
)
async def _gotConfirmation(
async def _got_confirmation(
self, client, data, peer_jid, transfer_data, file_data, stream_object
):
"""Called when the permission and dest path have been received
@param peer_jid(jid.JID): jid of the file sender
@param transfer_data(dict): same as for [self.getDestDir]
@param file_data(dict): same as for [self.getDestDir]
@param stream_object(bool): same as for [self.getDestDir]
@param transfer_data(dict): same as for [self.get_dest_dir]
@param file_data(dict): same as for [self.get_dest_dir]
@param stream_object(bool): same as for [self.get_dest_dir]
return (bool): True if copy is wanted and OK
False if user wants to cancel
if file exists ask confirmation and call again self._getDestDir if needed
@ -266,7 +266,7 @@ class FilePlugin:
# we manage case where file already exists
if os.path.exists(file_path):
overwrite = await xml_tools.deferConfirm(
overwrite = await xml_tools.defer_confirm(
self.host,
_(CONFIRM_OVERWRITE).format(file_path),
_(CONFIRM_OVERWRITE_TITLE),
@ -280,12 +280,12 @@ class FilePlugin:
)
if not overwrite:
return await self.getDestDir(client, peer_jid, transfer_data, file_data)
return await self.get_dest_dir(client, peer_jid, transfer_data, file_data)
self.openFileWrite(client, file_path, transfer_data, file_data, stream_object)
self.open_file_write(client, file_path, transfer_data, file_data, stream_object)
return True
async def getDestDir(
async def get_dest_dir(
self, client, peer_jid, transfer_data, file_data, stream_object=False
):
"""Request confirmation and destination dir to user
@ -296,7 +296,7 @@ class FilePlugin:
@param filename(unicode): name of the file
@param transfer_data(dict): data of the transfer session,
it will be only used to store the file_obj.
"file_obj" (or "stream_object") key *MUST NOT* exist before using getDestDir
"file_obj" (or "stream_object") key *MUST NOT* exist before using get_dest_dir
@param file_data(dict): information about the file to be transfered
It MUST contain the following keys:
- peer_jid (jid.JID): other peer jid
@ -314,7 +314,7 @@ class FilePlugin:
a stream.FileStreamObject will be used
return: True if transfer is accepted
"""
cont, ret_value = await self.host.trigger.asyncReturnPoint(
cont, ret_value = await self.host.trigger.async_return_point(
"FILE_getDestDir", client, peer_jid, transfer_data, file_data, stream_object
)
if not cont:
@ -323,8 +323,8 @@ class FilePlugin:
assert filename and not "/" in filename
assert PROGRESS_ID_KEY in file_data
# human readable size
file_data["size_human"] = common_utils.getHumanSize(file_data["size"])
resp_data = await xml_tools.deferDialog(
file_data["size_human"] = common_utils.get_human_size(file_data["size"])
resp_data = await xml_tools.defer_dialog(
self.host,
_(CONFIRM).format(peer=peer_jid.full(), **file_data),
_(CONFIRM_TITLE),
@ -339,7 +339,7 @@ class FilePlugin:
profile=client.profile,
)
accepted = await self._gotConfirmation(
accepted = await self._got_confirmation(
client,
resp_data,
peer_jid,

View file

@ -62,26 +62,26 @@ class forums(object):
self._p.OPT_SEND_ITEM_SUBSCRIBE: 1,
self._p.OPT_PUBLISH_MODEL: self._p.ACCESS_OPEN,
}
host.registerNamespace('forums', NS_FORUMS)
host.bridge.addMethod("forumsGet", ".plugin",
host.register_namespace('forums', NS_FORUMS)
host.bridge.add_method("forums_get", ".plugin",
in_sign='ssss', out_sign='s',
method=self._get,
async_=True)
host.bridge.addMethod("forumsSet", ".plugin",
host.bridge.add_method("forums_set", ".plugin",
in_sign='sssss', out_sign='',
method=self._set,
async_=True)
host.bridge.addMethod("forumTopicsGet", ".plugin",
host.bridge.add_method("forum_topics_get", ".plugin",
in_sign='ssa{ss}s', out_sign='(aa{ss}s)',
method=self._getTopics,
method=self._get_topics,
async_=True)
host.bridge.addMethod("forumTopicCreate", ".plugin",
host.bridge.add_method("forum_topic_create", ".plugin",
in_sign='ssa{ss}s', out_sign='',
method=self._createTopic,
method=self._create_topic,
async_=True)
@defer.inlineCallbacks
def _createForums(self, client, forums, service, node, forums_elt=None, names=None):
def _create_forums(self, client, forums, service, node, forums_elt=None, names=None):
"""Recursively create <forums> element(s)
@param forums(list): forums which may have subforums
@ -115,7 +115,7 @@ class forums(object):
log.info(_("creating missing forum node"))
forum_node = FORUM_TOPICS_NODE_TPL.format(node=node, uuid=shortuuid.uuid())
yield self._p.createNode(client, service, forum_node, self._node_options)
value = uri.buildXMPPUri('pubsub',
value = uri.build_xmpp_uri('pubsub',
path=service.full(),
node=forum_node)
if key in FORUM_ATTR:
@ -124,7 +124,7 @@ class forums(object):
forum_elt.addElement(key, content=value)
elif key == 'sub-forums':
sub_forums_elt = forum_elt.addElement('forums')
yield self._createForums(client, value, service, node, sub_forums_elt, names=names)
yield self._create_forums(client, value, service, node, sub_forums_elt, names=names)
else:
log.warning(_("Unknown forum attribute: {key}").format(key=key))
if not forum_elt.getAttribute('title'):
@ -137,7 +137,7 @@ class forums(object):
raise ValueError(_("forum need uri or sub-forums"))
defer.returnValue(forums_elt)
def _parseForums(self, parent_elt=None, forums=None):
def _parse_forums(self, parent_elt=None, forums=None):
"""Recursivly parse a <forums> elements and return corresponding forums data
@param item(domish.Element): item with <forums> element
@ -170,7 +170,7 @@ class forums(object):
data[elt.name] = str(elt)
elif elt.name == 'forums':
sub_forums = data['sub-forums'] = []
self._parseForums(elt, sub_forums)
self._parse_forums(elt, sub_forums)
if not 'title' in data or not {'uri', 'sub-forums'}.intersection(data):
log.warning(_("invalid forum, ignoring: {xml}").format(xml=forum_elt.toXml()))
else:
@ -181,7 +181,7 @@ class forums(object):
return forums
def _get(self, service=None, node=None, forums_key=None, profile_key=C.PROF_KEY_NONE):
client = self.host.getClient(profile_key)
client = self.host.get_client(profile_key)
if service.strip():
service = jid.JID(service)
else:
@ -199,14 +199,14 @@ class forums(object):
node = NS_FORUMS
if forums_key is None:
forums_key = 'default'
items_data = await self._p.getItems(client, service, node, item_ids=[forums_key])
items_data = await self._p.get_items(client, service, node, item_ids=[forums_key])
item = items_data[0][0]
# we have the item and need to convert it to json
forums = self._parseForums(item)
forums = self._parse_forums(item)
return forums
def _set(self, forums, service=None, node=None, forums_key=None, profile_key=C.PROF_KEY_NONE):
client = self.host.getClient(profile_key)
client = self.host.get_client(profile_key)
forums = json.loads(forums)
if service.strip():
service = jid.JID(service)
@ -241,16 +241,16 @@ class forums(object):
node = NS_FORUMS
if forums_key is None:
forums_key = 'default'
forums_elt = await self._createForums(client, forums, service, node)
return await self._p.sendItem(
forums_elt = await self._create_forums(client, forums, service, node)
return await self._p.send_item(
client, service, node, forums_elt, item_id=forums_key
)
def _getTopics(self, service, node, extra=None, profile_key=C.PROF_KEY_NONE):
client = self.host.getClient(profile_key)
extra = self._p.parseExtra(extra)
def _get_topics(self, service, node, extra=None, profile_key=C.PROF_KEY_NONE):
client = self.host.get_client(profile_key)
extra = self._p.parse_extra(extra)
d = defer.ensureDeferred(
self.getTopics(
self.get_topics(
client, jid.JID(service), node, rsm_request=extra.rsm_request,
extra=extra.extra
)
@ -260,12 +260,12 @@ class forums(object):
)
return d
async def getTopics(self, client, service, node, rsm_request=None, extra=None):
async def get_topics(self, client, service, node, rsm_request=None, extra=None):
"""Retrieve topics data
Topics are simple microblog URIs with some metadata duplicated from first post
"""
topics_data = await self._p.getItems(
topics_data = await self._p.get_items(
client, service, node, rsm_request=rsm_request, extra=extra
)
topics = []
@ -279,13 +279,13 @@ class forums(object):
topics.append(topic)
return (topics, metadata)
def _createTopic(self, service, node, mb_data, profile_key):
client = self.host.getClient(profile_key)
def _create_topic(self, service, node, mb_data, profile_key):
client = self.host.get_client(profile_key)
return defer.ensureDeferred(
self.createTopic(client, jid.JID(service), node, mb_data)
self.create_topic(client, jid.JID(service), node, mb_data)
)
async def createTopic(self, client, service, node, mb_data):
async def create_topic(self, client, service, node, mb_data):
try:
title = mb_data['title']
content = mb_data.pop('content')
@ -296,7 +296,7 @@ class forums(object):
topic_node = FORUM_TOPIC_NODE_TPL.format(node=node, uuid=shortuuid.uuid())
await self._p.createNode(client, service, topic_node, self._node_options)
await self._m.send(client, mb_data, service, topic_node)
topic_uri = uri.buildXMPPUri('pubsub',
topic_uri = uri.build_xmpp_uri('pubsub',
subtype='microblog',
path=service.full(),
node=topic_node)
@ -304,4 +304,4 @@ class forums(object):
topic_elt['uri'] = topic_uri
topic_elt['author'] = client.jid.userhost()
topic_elt.addElement('title', content = title)
await self._p.sendItem(client, service, node, topic_elt)
await self._p.send_item(client, service, node, topic_elt)

View file

@ -61,19 +61,19 @@ class GroupBlog(object):
log.info(_("Group blog plugin initialization"))
self.host = host
self._p = self.host.plugins["XEP-0060"]
host.trigger.add("XEP-0277_item2data", self._item2dataTrigger)
host.trigger.add("XEP-0277_data2entry", self._data2entryTrigger)
host.trigger.add("XEP-0277_comments", self._commentsTrigger)
host.trigger.add("XEP-0277_item2data", self._item_2_data_trigger)
host.trigger.add("XEP-0277_data2entry", self._data_2_entry_trigger)
host.trigger.add("XEP-0277_comments", self._comments_trigger)
## plugin management methods ##
def getHandler(self, client):
def get_handler(self, client):
return GroupBlog_handler()
@defer.inlineCallbacks
def profileConnected(self, client):
def profile_connected(self, client):
try:
yield self.host.checkFeatures(client, (NS_PUBSUB_GROUPBLOG,))
yield self.host.check_features(client, (NS_PUBSUB_GROUPBLOG,))
except exceptions.FeatureNotFound:
client.server_groupblog_available = False
log.warning(
@ -85,21 +85,21 @@ class GroupBlog(object):
client.server_groupblog_available = True
log.info(_("Server can manage group blogs"))
def getFeatures(self, profile):
def features_get(self, profile):
try:
client = self.host.getClient(profile)
client = self.host.get_client(profile)
except exceptions.ProfileNotSetError:
return {}
try:
return {"available": C.boolConst(client.server_groupblog_available)}
return {"available": C.bool_const(client.server_groupblog_available)}
except AttributeError:
if self.host.isConnected(profile):
if self.host.is_connected(profile):
log.debug("Profile is not connected, service is not checked yet")
else:
log.error("client.server_groupblog_available should be available !")
return {}
def _item2dataTrigger(self, item_elt, entry_elt, microblog_data):
def _item_2_data_trigger(self, item_elt, entry_elt, microblog_data):
"""Parse item to find group permission elements"""
config_form = data_form.findForm(item_elt, NS_PUBSUB_ITEM_CONFIG)
if config_form is None:
@ -109,7 +109,7 @@ class GroupBlog(object):
opt = self._p.OPT_ROSTER_GROUPS_ALLOWED
microblog_data['groups'] = config_form.fields[opt].values
def _data2entryTrigger(self, client, mb_data, entry_elt, item_elt):
def _data_2_entry_trigger(self, client, mb_data, entry_elt, item_elt):
"""Build fine access permission if needed
This trigger check if "group*" key are present,
@ -130,7 +130,7 @@ class GroupBlog(object):
form.addField(allowed)
item_elt.addChild(form.toElement())
def _commentsTrigger(self, client, mb_data, options):
def _comments_trigger(self, client, mb_data, options):
"""This method is called when a comments node is about to be created
It changes the access mode to roster if needed, and give the authorized groups

View file

@ -77,11 +77,11 @@ class Identity:
"avatar": {
"type": dict,
# convert avatar path to avatar metadata (and check validity)
"set_data_filter": self.avatarSetDataFilter,
"set_data_filter": self.avatar_set_data_filter,
# update profile avatar, so all frontends are aware
"set_post_treatment": self.avatarSetPostTreatment,
"update_is_new_data": self.avatarUpdateIsNewData,
"update_data_filter": self.avatarUpdateDataFilter,
"set_post_treatment": self.avatar_set_post_treatment,
"update_is_new_data": self.avatar_update_is_new_data,
"update_data_filter": self.avatar_update_data_filter,
# we store the metadata in database, to restore it on next connection
# (it is stored only for roster entities)
"store": True,
@ -92,70 +92,70 @@ class Identity:
# of returning only the data from the first successful callback
"get_all": True,
# append nicknames from roster, resource, etc.
"get_post_treatment": self.nicknamesGetPostTreatment,
"update_is_new_data": self.nicknamesUpdateIsNewData,
"get_post_treatment": self.nicknames_get_post_treatment,
"update_is_new_data": self.nicknames_update_is_new_data,
"store": True,
},
"description": {
"type": str,
"get_all": True,
"get_post_treatment": self.descriptionGetPostTreatment,
"get_post_treatment": self.description_get_post_treatment,
"store": True,
}
}
host.trigger.add("roster_update", self._rosterUpdateTrigger)
host.memory.setSignalOnUpdate("avatar")
host.memory.setSignalOnUpdate("nicknames")
host.bridge.addMethod(
"identityGet",
host.trigger.add("roster_update", self._roster_update_trigger)
host.memory.set_signal_on_update("avatar")
host.memory.set_signal_on_update("nicknames")
host.bridge.add_method(
"identity_get",
".plugin",
in_sign="sasbs",
out_sign="s",
method=self._getIdentity,
method=self._get_identity,
async_=True,
)
host.bridge.addMethod(
"identitiesGet",
host.bridge.add_method(
"identities_get",
".plugin",
in_sign="asass",
out_sign="s",
method=self._getIdentities,
method=self._get_identities,
async_=True,
)
host.bridge.addMethod(
"identitiesBaseGet",
host.bridge.add_method(
"identities_base_get",
".plugin",
in_sign="s",
out_sign="s",
method=self._getBaseIdentities,
method=self._get_base_identities,
async_=True,
)
host.bridge.addMethod(
"identitySet",
host.bridge.add_method(
"identity_set",
".plugin",
in_sign="ss",
out_sign="",
method=self._setIdentity,
method=self._set_identity,
async_=True,
)
host.bridge.addMethod(
"avatarGet",
host.bridge.add_method(
"avatar_get",
".plugin",
in_sign="sbs",
out_sign="s",
method=self._getAvatar,
async_=True,
)
host.bridge.addMethod(
"avatarSet",
host.bridge.add_method(
"avatar_set",
".plugin",
in_sign="sss",
out_sign="",
method=self._setAvatar,
method=self._set_avatar,
async_=True,
)
async def profileConnecting(self, client):
async def profile_connecting(self, client):
client._identity_update_lock = []
# we restore known identities from database
client._identity_storage = persistent.LazyPersistentBinaryDict(
@ -188,22 +188,22 @@ class Identity:
f"{value}")
to_delete.append(key)
continue
cache = self.host.common_cache.getMetadata(cache_uid)
cache = self.host.common_cache.get_metadata(cache_uid)
if cache is None:
log.debug(
f"purging avatar for {entity}: it is not in cache anymore")
to_delete.append(key)
continue
self.host.memory.updateEntityData(
self.host.memory.update_entity_data(
client, entity, name, value, silent=True
)
for key in to_delete:
await client._identity_storage.adel(key)
def _rosterUpdateTrigger(self, client, roster_item):
old_item = client.roster.getItem(roster_item.jid)
def _roster_update_trigger(self, client, roster_item):
old_item = client.roster.get_item(roster_item.jid)
if old_item is None or old_item.name != roster_item.name:
log.debug(
f"roster nickname has been updated to {roster_item.name!r} for "
@ -247,7 +247,7 @@ class Identity:
cb_list.append(callback)
cb_list.sort(key=lambda c: c.priority, reverse=True)
def getIdentityJid(self, client, peer_jid):
def get_identity_jid(self, client, peer_jid):
"""Return jid to use to set identity metadata
if it's a jid of a room occupant, full jid will be used
@ -260,9 +260,9 @@ class Identity:
if self._m is None:
return peer_jid.userhostJID()
else:
return self._m.getBareOrFull(client, peer_jid)
return self._m.get_bare_or_full(client, peer_jid)
def checkType(self, metadata_name, value):
def check_type(self, metadata_name, value):
"""Check that type used for a metadata is the one declared in self.metadata"""
value_type = self.metadata[metadata_name]["type"]
if not isinstance(value, value_type):
@ -270,7 +270,7 @@ class Identity:
f"{value} has wrong type: it is {type(value)} while {value_type} was "
f"expected")
def getFieldType(self, metadata_name: str) -> str:
def get_field_type(self, metadata_name: str) -> str:
"""Return the type the requested field
@param metadata_name: name of the field to check
@ -298,7 +298,7 @@ class Identity:
@param use_cache: if False, cache won't be checked
@param prefilled_values: map of origin => value to use when `get_all` is set
"""
entity = self.getIdentityJid(client, entity)
entity = self.get_identity_jid(client, entity)
try:
metadata = self.metadata[metadata_name]
except KeyError:
@ -306,7 +306,7 @@ class Identity:
get_all = metadata.get('get_all', False)
if use_cache:
try:
data = self.host.memory.getEntityDatum(
data = self.host.memory.get_entity_datum(
client, entity, metadata_name)
except (KeyError, exceptions.UnknownEntityError):
pass
@ -343,7 +343,7 @@ class Identity:
.format(callback=callback.get, metadata_name=metadata_name, e=e))
else:
if data:
self.checkType(metadata_name, data)
self.check_type(metadata_name, data)
if get_all:
if isinstance(data, list):
all_data.extend(data)
@ -359,9 +359,9 @@ class Identity:
post_treatment = metadata.get("get_post_treatment")
if post_treatment is not None:
data = await utils.asDeferred(post_treatment, client, entity, data)
data = await utils.as_deferred(post_treatment, client, entity, data)
self.host.memory.updateEntityData(
self.host.memory.update_entity_data(
client, entity, metadata_name, data)
if metadata.get('store', False):
@ -381,12 +381,12 @@ class Identity:
@param entity(jid.JID, None): entity for which avatar is requested
None to use profile's jid
"""
entity = self.getIdentityJid(client, entity)
entity = self.get_identity_jid(client, entity)
metadata = self.metadata[metadata_name]
data_filter = metadata.get("set_data_filter")
if data_filter is not None:
data = await utils.asDeferred(data_filter, client, entity, data)
self.checkType(metadata_name, data)
data = await utils.as_deferred(data_filter, client, entity, data)
self.check_type(metadata_name, data)
try:
callbacks = metadata['callbacks']
@ -411,7 +411,7 @@ class Identity:
post_treatment = metadata.get("set_post_treatment")
if post_treatment is not None:
await utils.asDeferred(post_treatment, client, entity, data)
await utils.as_deferred(post_treatment, client, entity, data)
async def update(
self,
@ -426,14 +426,14 @@ class Identity:
This method may be called by plugins when an identity metadata is available.
@param origin: namespace of the plugin which is source of the metadata
"""
entity = self.getIdentityJid(client, entity)
entity = self.get_identity_jid(client, entity)
if (entity, metadata_name) in client._identity_update_lock:
log.debug(f"update is locked for {entity}'s {metadata_name}")
return
metadata = self.metadata[metadata_name]
try:
cached_data = self.host.memory.getEntityDatum(
cached_data = self.host.memory.get_entity_datum(
client, entity, metadata_name)
except (KeyError, exceptions.UnknownEntityError):
# metadata is not cached, we do the update
@ -443,7 +443,7 @@ class Identity:
try:
update_is_new_data = metadata["update_is_new_data"]
except KeyError:
update_is_new_data = self.defaultUpdateIsNewData
update_is_new_data = self.default_update_is_new_data
if data is None:
if cached_data is None:
@ -467,7 +467,7 @@ class Identity:
# get_all is set, meaning that we have to check all plugins
# so we first delete current cache
try:
self.host.memory.delEntityDatum(client, entity, metadata_name)
self.host.memory.del_entity_datum(client, entity, metadata_name)
except (KeyError, exceptions.UnknownEntityError):
pass
# then fill it again by calling get, which will retrieve all values
@ -481,32 +481,32 @@ class Identity:
if data is not None:
data_filter = metadata['update_data_filter']
if data_filter is not None:
data = await utils.asDeferred(data_filter, client, entity, data)
self.checkType(metadata_name, data)
data = await utils.as_deferred(data_filter, client, entity, data)
self.check_type(metadata_name, data)
self.host.memory.updateEntityData(client, entity, metadata_name, data)
self.host.memory.update_entity_data(client, entity, metadata_name, data)
if metadata.get('store', False):
key = f"{entity}\n{metadata_name}"
await client._identity_storage.aset(key, data)
def defaultUpdateIsNewData(self, client, entity, cached_data, new_data):
def default_update_is_new_data(self, client, entity, cached_data, new_data):
return new_data != cached_data
def _getAvatar(self, entity, use_cache, profile):
client = self.host.getClient(profile)
client = self.host.get_client(profile)
entity = jid.JID(entity) if entity else None
d = defer.ensureDeferred(self.get(client, "avatar", entity, use_cache))
d.addCallback(lambda data: data_format.serialise(data))
return d
def _setAvatar(self, file_path, entity, profile_key=C.PROF_KEY_NONE):
client = self.host.getClient(profile_key)
def _set_avatar(self, file_path, entity, profile_key=C.PROF_KEY_NONE):
client = self.host.get_client(profile_key)
entity = jid.JID(entity) if entity else None
return defer.ensureDeferred(
self.set(client, "avatar", file_path, entity))
def _blockingCacheAvatar(
def _blocking_cache_avatar(
self,
source: str,
avatar_data: dict[str, Any]
@ -546,7 +546,7 @@ class Identity:
img_buf.seek(0)
image_hash = hashlib.sha1(img_buf.read()).hexdigest()
img_buf.seek(0)
with self.host.common_cache.cacheData(
with self.host.common_cache.cache_data(
source, image_hash, media_type
) as f:
f.write(img_buf.read())
@ -554,21 +554,21 @@ class Identity:
avatar_data['filename'] = avatar_data['path'].name
avatar_data['cache_uid'] = image_hash
async def cacheAvatar(self, source: str, avatar_data: Dict[str, Any]) -> None:
async def cache_avatar(self, source: str, avatar_data: Dict[str, Any]) -> None:
"""Resize if necessary and cache avatar
@param source: source importing the avatar (usually it is plugin's import name),
will be used in cache metadata
@param avatar_data: avatar metadata as build by [avatarSetDataFilter]
@param avatar_data: avatar metadata as build by [avatar_set_data_filter]
will be updated with following keys:
path: updated path using cached file
filename: updated filename using cached file
base64: resized and base64 encoded avatar
cache_uid: SHA1 hash used as cache unique ID
"""
await threads.deferToThread(self._blockingCacheAvatar, source, avatar_data)
await threads.deferToThread(self._blocking_cache_avatar, source, avatar_data)
async def avatarSetDataFilter(self, client, entity, file_path):
async def avatar_set_data_filter(self, client, entity, file_path):
"""Convert avatar file path to dict data"""
file_path = Path(file_path)
if not file_path.is_file():
@ -583,14 +583,14 @@ class Identity:
raise ValueError(f"Can't identify type of image at {file_path}")
if not media_type.startswith('image/'):
raise ValueError(f"File at {file_path} doesn't appear to be an image")
await self.cacheAvatar(IMPORT_NAME, avatar_data)
await self.cache_avatar(IMPORT_NAME, avatar_data)
return avatar_data
async def avatarSetPostTreatment(self, client, entity, avatar_data):
async def avatar_set_post_treatment(self, client, entity, avatar_data):
"""Update our own avatar"""
await self.update(client, IMPORT_NAME, "avatar", avatar_data, entity)
def avatarBuildMetadata(
def avatar_build_metadata(
self,
path: Path,
media_type: Optional[str] = None,
@ -622,10 +622,10 @@ class Identity:
"cache_uid": cache_uid,
}
def avatarUpdateIsNewData(self, client, entity, cached_data, new_data):
def avatar_update_is_new_data(self, client, entity, cached_data, new_data):
return new_data['path'] != cached_data['path']
async def avatarUpdateDataFilter(self, client, entity, data):
async def avatar_update_data_filter(self, client, entity, data):
if not isinstance(data, dict):
raise ValueError(f"Invalid data type ({type(data)}), a dict is expected")
mandatory_keys = {'path', 'filename', 'cache_uid'}
@ -633,7 +633,7 @@ class Identity:
raise ValueError(f"missing avatar data keys: {mandatory_keys - data.keys()}")
return data
async def nicknamesGetPostTreatment(self, client, entity, plugin_nicknames):
async def nicknames_get_post_treatment(self, client, entity, plugin_nicknames):
"""Prepend nicknames from core locations + set default nickname
nicknames are checked from many locations, there is always at least
@ -648,13 +648,13 @@ class Identity:
# for MUC we add resource
if entity.resource:
# getIdentityJid let the resource only if the entity is a MUC room
# get_identity_jid let the resource only if the entity is a MUC room
# occupant jid
nicknames.append(entity.resource)
# we first check roster (if we are not in a component)
if not client.is_component:
roster_item = client.roster.getItem(entity.userhostJID())
roster_item = client.roster.get_item(entity.userhostJID())
if roster_item is not None and roster_item.name:
# user set name has priority over entity set name
nicknames.append(roster_item.name)
@ -670,10 +670,10 @@ class Identity:
# we remove duplicates while preserving order with dict
return list(dict.fromkeys(nicknames))
def nicknamesUpdateIsNewData(self, client, entity, cached_data, new_nicknames):
def nicknames_update_is_new_data(self, client, entity, cached_data, new_nicknames):
return not set(new_nicknames).issubset(cached_data)
async def descriptionGetPostTreatment(
async def description_get_post_treatment(
self,
client: SatXMPPEntity,
entity: jid.JID,
@ -682,15 +682,15 @@ class Identity:
"""Join all descriptions in a unique string"""
return '\n'.join(plugin_description)
def _getIdentity(self, entity_s, metadata_filter, use_cache, profile):
def _get_identity(self, entity_s, metadata_filter, use_cache, profile):
entity = jid.JID(entity_s)
client = self.host.getClient(profile)
client = self.host.get_client(profile)
d = defer.ensureDeferred(
self.getIdentity(client, entity, metadata_filter, use_cache))
self.get_identity(client, entity, metadata_filter, use_cache))
d.addCallback(data_format.serialise)
return d
async def getIdentity(
async def get_identity(
self,
client: SatXMPPEntity,
entity: Optional[jid.JID] = None,
@ -719,14 +719,14 @@ class Identity:
return id_data
def _getIdentities(self, entities_s, metadata_filter, profile):
def _get_identities(self, entities_s, metadata_filter, profile):
entities = [jid.JID(e) for e in entities_s]
client = self.host.getClient(profile)
d = defer.ensureDeferred(self.getIdentities(client, entities, metadata_filter))
client = self.host.get_client(profile)
d = defer.ensureDeferred(self.get_identities(client, entities, metadata_filter))
d.addCallback(lambda d: data_format.serialise({str(j):i for j, i in d.items()}))
return d
async def getIdentities(
async def get_identities(
self,
client: SatXMPPEntity,
entities: List[jid.JID],
@ -735,7 +735,7 @@ class Identity:
"""Retrieve several identities at once
@param entities: entities from which identities must be retrieved
@param metadata_filter: same as for [getIdentity]
@param metadata_filter: same as for [get_identity]
@return: identities metadata where key is jid
if an error happens while retrieve a jid entity, it won't be present in the
result (and a warning will be logged)
@ -745,7 +745,7 @@ class Identity:
for entity_jid in entities:
get_identity_list.append(
defer.ensureDeferred(
self.getIdentity(
self.get_identity(
client,
entity=entity_jid,
metadata_filter=metadata_filter,
@ -761,13 +761,13 @@ class Identity:
identities[entity_jid] = identity
return identities
def _getBaseIdentities(self, profile_key):
client = self.host.getClient(profile_key)
d = defer.ensureDeferred(self.getBaseIdentities(client))
def _get_base_identities(self, profile_key):
client = self.host.get_client(profile_key)
d = defer.ensureDeferred(self.get_base_identities(client))
d.addCallback(lambda d: data_format.serialise({str(j):i for j, i in d.items()}))
return d
async def getBaseIdentities(
async def get_base_identities(
self,
client: SatXMPPEntity,
) -> dict:
@ -779,20 +779,20 @@ class Identity:
if client.is_component:
entities = [client.jid.userhostJID()]
else:
entities = client.roster.getJids() + [client.jid.userhostJID()]
entities = client.roster.get_jids() + [client.jid.userhostJID()]
return await self.getIdentities(
return await self.get_identities(
client,
entities,
['avatar', 'nicknames']
)
def _setIdentity(self, id_data_s, profile):
client = self.host.getClient(profile)
def _set_identity(self, id_data_s, profile):
client = self.host.get_client(profile)
id_data = data_format.deserialise(id_data_s)
return defer.ensureDeferred(self.setIdentity(client, id_data))
return defer.ensureDeferred(self.set_identity(client, id_data))
async def setIdentity(self, client, id_data):
async def set_identity(self, client, id_data):
"""Update profile's identity
@param id_data(dict): data to update, key can be one of self.metadata keys

View file

@ -99,7 +99,7 @@ class IPPlugin(object):
def __init__(self, host):
log.info(_("plugin IP discovery initialization"))
self.host = host
host.memory.updateParams(PARAMS)
host.memory.update_params(PARAMS)
# NAT-Port
try:
@ -109,50 +109,50 @@ class IPPlugin(object):
self._nat = None
# XXX: cache is kept until SàT is restarted
# if IP may have changed, use self.refreshIP
# if IP may have changed, use self.refresh_ip
self._external_ip_cache = None
self._local_ip_cache = None
def getHandler(self, client):
def get_handler(self, client):
return IPPlugin_handler()
def refreshIP(self):
def refresh_ip(self):
# FIXME: use a trigger instead ?
self._external_ip_cache = None
self._local_ip_cache = None
def _externalAllowed(self, client):
def _external_allowed(self, client):
"""Return value of parameter with autorisation of user to do external requests
if parameter is not set, a dialog is shown to use to get its confirmation, and parameted is set according to answer
@return (defer.Deferred[bool]): True if external request is autorised
"""
allow_get_ip = self.host.memory.params.getParamA(
allow_get_ip = self.host.memory.params.param_get_a(
GET_IP_NAME, GET_IP_CATEGORY, use_default=False
)
if allow_get_ip is None:
# we don't have autorisation from user yet to use get_ip, we ask him
def setParam(allowed):
# FIXME: we need to use boolConst as setParam only manage str/unicode
def param_set(allowed):
# FIXME: we need to use bool_const as param_set only manage str/unicode
# need to be fixed when params will be refactored
self.host.memory.setParam(
GET_IP_NAME, C.boolConst(allowed), GET_IP_CATEGORY
self.host.memory.param_set(
GET_IP_NAME, C.bool_const(allowed), GET_IP_CATEGORY
)
return allowed
d = xml_tools.deferConfirm(
d = xml_tools.defer_confirm(
self.host,
_(GET_IP_CONFIRM),
_(GET_IP_CONFIRM_TITLE),
profile=client.profile,
)
d.addCallback(setParam)
d.addCallback(param_set)
return d
return defer.succeed(allow_get_ip)
def _filterAddresse(self, ip_addr):
def _filter_addresse(self, ip_addr):
"""Filter acceptable addresses
For now, just remove IPv4 local addresses
@ -161,7 +161,7 @@ class IPPlugin(object):
"""
return not ip_addr.startswith("127.")
def _insertFirst(self, addresses, ip_addr):
def _insert_first(self, addresses, ip_addr):
"""Insert ip_addr as first item in addresses
@param addresses(list): list of IP addresses
@ -174,7 +174,7 @@ class IPPlugin(object):
else:
addresses.insert(0, ip_addr)
async def _getIPFromExternal(self, ext_url):
async def _get_ip_from_external(self, ext_url):
"""Get local IP by doing a connection on an external url
@param ext_utl(str): url to connect to
@ -201,7 +201,7 @@ class IPPlugin(object):
return local_ip
@defer.inlineCallbacks
def getLocalIPs(self, client):
def get_local_i_ps(self, client):
"""Try do discover local area network IPs
@return (deferred): list of lan IP addresses
@ -225,43 +225,43 @@ class IPPlugin(object):
continue
for data in inet_list:
addresse = data["addr"]
if self._filterAddresse(addresse):
if self._filter_addresse(addresse):
addresses.append(addresse)
# then we use our connection to server
ip = client.xmlstream.transport.getHost().host
if self._filterAddresse(ip):
self._insertFirst(addresses, ip)
if self._filter_addresse(ip):
self._insert_first(addresses, ip)
defer.returnValue(addresses)
# if server is local, we try with NAT-Port
if self._nat is not None:
nat_ip = yield self._nat.getIP(local=True)
nat_ip = yield self._nat.get_ip(local=True)
if nat_ip is not None:
self._insertFirst(addresses, nat_ip)
self._insert_first(addresses, nat_ip)
defer.returnValue(addresses)
if addresses:
defer.returnValue(addresses)
# still not luck, we need to contact external website
allow_get_ip = yield self._externalAllowed(client)
allow_get_ip = yield self._external_allowed(client)
if not allow_get_ip:
defer.returnValue(addresses or localhost)
try:
local_ip = yield defer.ensureDeferred(self._getIPFromExternal(GET_IP_PAGE))
local_ip = yield defer.ensureDeferred(self._get_ip_from_external(GET_IP_PAGE))
except (internet_error.DNSLookupError, internet_error.TimeoutError):
log.warning("Can't access Domain Name System")
else:
if local_ip is not None:
self._insertFirst(addresses, local_ip)
self._insert_first(addresses, local_ip)
defer.returnValue(addresses or localhost)
@defer.inlineCallbacks
def getExternalIP(self, client):
def get_external_ip(self, client):
"""Try to discover external IP
@return (deferred): external IP address or None if it can't be discovered
@ -295,13 +295,13 @@ class IPPlugin(object):
# then with NAT-Port
if self._nat is not None:
nat_ip = yield self._nat.getIP()
nat_ip = yield self._nat.get_ip()
if nat_ip is not None:
self._external_ip_cache = nat_ip
defer.returnValue(nat_ip)
# and finally by requesting external website
allow_get_ip = yield self._externalAllowed(client)
allow_get_ip = yield self._external_allowed(client)
try:
ip = ((yield webclient.getPage(GET_IP_PAGE.encode('utf-8')))
if allow_get_ip else None)

View file

@ -208,16 +208,16 @@ class PubsubLists:
log.info(_("Pubsub lists plugin initialization"))
self.host = host
self._s = self.host.plugins["XEP-0346"]
self.namespace = self._s.getSubmittedNS(APP_NS_TICKETS)
host.registerNamespace("tickets", APP_NS_TICKETS)
host.registerNamespace("tickets_type", NS_TICKETS_TYPE)
self.namespace = self._s.get_submitted_ns(APP_NS_TICKETS)
host.register_namespace("tickets", APP_NS_TICKETS)
host.register_namespace("tickets_type", NS_TICKETS_TYPE)
self.host.plugins["PUBSUB_INVITATION"].register(
APP_NS_TICKETS, self
)
self._p = self.host.plugins["XEP-0060"]
self._m = self.host.plugins["XEP-0277"]
host.bridge.addMethod(
"listGet",
host.bridge.add_method(
"list_get",
".plugin",
in_sign="ssiassss",
out_sign="s",
@ -232,68 +232,68 @@ class PubsubLists:
default_node=self.namespace,
form_ns=APP_NS_TICKETS,
filters={
"author": self._s.valueOrPublisherFilter,
"created": self._s.dateFilter,
"updated": self._s.dateFilter,
"time_limit": self._s.dateFilter,
"author": self._s.value_or_publisher_filter,
"created": self._s.date_filter,
"updated": self._s.date_filter,
"time_limit": self._s.date_filter,
},
profile_key=profile_key),
async_=True,
)
host.bridge.addMethod(
"listSet",
host.bridge.add_method(
"list_set",
".plugin",
in_sign="ssa{sas}ssss",
out_sign="s",
method=self._set,
async_=True,
)
host.bridge.addMethod(
"listDeleteItem",
host.bridge.add_method(
"list_delete_item",
".plugin",
in_sign="sssbs",
out_sign="",
method=self._delete,
async_=True,
)
host.bridge.addMethod(
"listSchemaGet",
host.bridge.add_method(
"list_schema_get",
".plugin",
in_sign="sss",
out_sign="s",
method=lambda service, nodeIdentifier, profile_key: self._s._getUISchema(
method=lambda service, nodeIdentifier, profile_key: self._s._get_ui_schema(
service, nodeIdentifier, default_node=self.namespace,
profile_key=profile_key),
async_=True,
)
host.bridge.addMethod(
"listsList",
host.bridge.add_method(
"lists_list",
".plugin",
in_sign="sss",
out_sign="s",
method=self._listsList,
method=self._lists_list,
async_=True,
)
host.bridge.addMethod(
"listTemplatesNamesGet",
host.bridge.add_method(
"list_templates_names_get",
".plugin",
in_sign="ss",
out_sign="s",
method=self._getTemplatesNames,
method=self._get_templates_names,
)
host.bridge.addMethod(
"listTemplateGet",
host.bridge.add_method(
"list_template_get",
".plugin",
in_sign="sss",
out_sign="s",
method=self._getTemplate,
method=self._get_template,
)
host.bridge.addMethod(
"listTemplateCreate",
host.bridge.add_method(
"list_template_create",
".plugin",
in_sign="ssss",
out_sign="(ss)",
method=self._createTemplate,
method=self._create_template,
async_=True,
)
@ -309,7 +309,7 @@ class PubsubLists:
item_elt: domish.Element
) -> None:
try:
schema = await self._s.getSchemaForm(client, service, node)
schema = await self._s.get_schema_form(client, service, node)
except Exception as e:
log.warning(f"Can't retrive node schema as {node!r} [{service}]: {e}")
else:
@ -323,7 +323,7 @@ class PubsubLists:
def _set(self, service, node, values, schema=None, item_id=None, extra_s='',
profile_key=C.PROF_KEY_NONE):
client, service, node, schema, item_id, extra = self._s.prepareBridgeSet(
client, service, node, schema, item_id, extra = self._s.prepare_bridge_set(
service, node, schema, item_id, extra_s, profile_key
)
d = defer.ensureDeferred(self.set(
@ -346,22 +346,22 @@ class PubsubLists:
'created' and 'updated' will be forced to current time:
- 'created' is set if item_id is None, i.e. if it's a new ticket
- 'updated' is set everytime
@param extra(dict, None): same as for [XEP-0060.sendItem] with additional keys:
@param extra(dict, None): same as for [XEP-0060.send_item] with additional keys:
- update(bool): if True, get previous item data to merge with current one
if True, item_id must be set
other arguments are same as for [self._s.sendDataFormItem]
other arguments are same as for [self._s.send_data_form_item]
@return (unicode): id of the created item
"""
if not node:
node = self.namespace
if not item_id:
comments_service = await self._m.getCommentsService(client, service)
comments_service = await self._m.get_comments_service(client, service)
# we need to use uuid for comments node, because we don't know item id in
# advance (we don't want to set it ourselves to let the server choose, so we
# can have a nicer id if serial ids is activated)
comments_node = self._m.getCommentsNode(
comments_node = self._m.get_comments_node(
node + "_" + str(shortuuid.uuid())
)
options = {
@ -372,7 +372,7 @@ class PubsubLists:
self._p.OPT_PUBLISH_MODEL: self._p.ACCESS_OPEN,
}
await self._p.createNode(client, comments_service, comments_node, options)
values["comments_uri"] = uri.buildXMPPUri(
values["comments_uri"] = uri.build_xmpp_uri(
"pubsub",
subtype="microblog",
path=comments_service.full(),
@ -386,7 +386,7 @@ class PubsubLists:
def _delete(
self, service_s, nodeIdentifier, itemIdentifier, notify, profile_key
):
client = self.host.getClient(profile_key)
client = self.host.get_client(profile_key)
return defer.ensureDeferred(self.delete(
client,
jid.JID(service_s) if service_s else None,
@ -405,26 +405,26 @@ class PubsubLists:
) -> None:
if not node:
node = self.namespace
return await self._p.retractItems(
return await self._p.retract_items(
service, node, (itemIdentifier,), notify, client.profile
)
def _listsList(self, service, node, profile):
def _lists_list(self, service, node, profile):
service = jid.JID(service) if service else None
node = node or None
client = self.host.getClient(profile)
d = defer.ensureDeferred(self.listsList(client, service, node))
client = self.host.get_client(profile)
d = defer.ensureDeferred(self.lists_list(client, service, node))
d.addCallback(data_format.serialise)
return d
async def listsList(
async def lists_list(
self, client, service: Optional[jid.JID], node: Optional[str]=None
) -> List[dict]:
"""Retrieve list of pubsub lists registered in personal interests
@return list: list of lists metadata
"""
items, metadata = await self.host.plugins['LIST_INTEREST'].listInterests(
items, metadata = await self.host.plugins['LIST_INTEREST'].list_interests(
client, service, node, namespace=APP_NS_TICKETS)
lists = []
for item in items:
@ -454,34 +454,34 @@ class PubsubLists:
return lists
def _getTemplatesNames(self, language, profile):
client = self.host.getClient(profile)
return data_format.serialise(self.getTemplatesNames(client, language))
def _get_templates_names(self, language, profile):
client = self.host.get_client(profile)
return data_format.serialise(self.get_templates_names(client, language))
def getTemplatesNames(self, client, language: str) -> list:
def get_templates_names(self, client, language: str) -> list:
"""Retrieve well known list templates"""
templates = [{"id": tpl_id, "name": d["name"], "icon": d["icon"]}
for tpl_id, d in TEMPLATES.items()]
return templates
def _getTemplate(self, name, language, profile):
client = self.host.getClient(profile)
return data_format.serialise(self.getTemplate(client, name, language))
def _get_template(self, name, language, profile):
client = self.host.get_client(profile)
return data_format.serialise(self.get_template(client, name, language))
def getTemplate(self, client, name: str, language: str) -> dict:
def get_template(self, client, name: str, language: str) -> dict:
"""Retrieve a well known template"""
return TEMPLATES[name]
def _createTemplate(self, template_id, name, access_model, profile):
client = self.host.getClient(profile)
d = defer.ensureDeferred(self.createTemplate(
def _create_template(self, template_id, name, access_model, profile):
client = self.host.get_client(profile)
d = defer.ensureDeferred(self.create_template(
client, template_id, name, access_model
))
d.addCallback(lambda node_data: (node_data[0].full(), node_data[1]))
return d
async def createTemplate(
async def create_template(
self, client, template_id: str, name: str, access_model: str
) -> Tuple[jid.JID, str]:
"""Create a list from a template"""
@ -493,12 +493,12 @@ class PubsubLists:
0,
{"type": "hidden", "name": NS_TICKETS_TYPE, "value": template_id}
)
schema = xml_tools.dataDict2dataForm(
schema = xml_tools.data_dict_2_data_form(
{"namespace": APP_NS_TICKETS, "fields": fields}
).toElement()
service = client.jid.userhostJID()
node = self._s.getSubmittedNS(f"{APP_NS_TICKETS}_{name}")
node = self._s.get_submitted_ns(f"{APP_NS_TICKETS}_{name}")
options = {
self._p.OPT_ACCESS_MODEL: access_model,
}
@ -507,11 +507,11 @@ class PubsubLists:
# XXX: should node options be in TEMPLATE?
options[self._p.OPT_OVERWRITE_POLICY] = self._p.OWPOL_ANY_PUB
await self._p.createNode(client, service, node, options)
await self._s.setSchema(client, service, node, schema)
await self._s.set_schema(client, service, node, schema)
list_elt = domish.Element((APP_NS_TICKETS, "list"))
list_elt["type"] = template_id
try:
await self.host.plugins['LIST_INTEREST'].registerPubsub(
await self.host.plugins['LIST_INTEREST'].register_pubsub(
client, APP_NS_TICKETS, service, node, creator=True,
name=name, element=list_elt)
except Exception as e:

View file

@ -69,35 +69,35 @@ class MergeRequests(object):
log.info(_("Merge requests plugin initialization"))
self.host = host
self._s = self.host.plugins["XEP-0346"]
self.namespace = self._s.getSubmittedNS(APP_NS_MERGE_REQUESTS)
host.registerNamespace('merge_requests', self.namespace)
self.namespace = self._s.get_submitted_ns(APP_NS_MERGE_REQUESTS)
host.register_namespace('merge_requests', self.namespace)
self._p = self.host.plugins["XEP-0060"]
self._t = self.host.plugins["LISTS"]
self._handlers = {}
self._handlers_list = [] # handlers sorted by priority
self._type_handlers = {} # data type => handler map
host.bridge.addMethod("mergeRequestsGet", ".plugin",
host.bridge.add_method("merge_requests_get", ".plugin",
in_sign='ssiassss', out_sign='s',
method=self._get,
async_=True
)
host.bridge.addMethod("mergeRequestSet", ".plugin",
host.bridge.add_method("merge_request_set", ".plugin",
in_sign='ssssa{sas}ssss', out_sign='s',
method=self._set,
async_=True)
host.bridge.addMethod("mergeRequestsSchemaGet", ".plugin",
host.bridge.add_method("merge_requests_schema_get", ".plugin",
in_sign='sss', out_sign='s',
method=lambda service, nodeIdentifier, profile_key:
self._s._getUISchema(service,
self._s._get_ui_schema(service,
nodeIdentifier,
default_node=self.namespace,
profile_key=profile_key),
async_=True)
host.bridge.addMethod("mergeRequestParseData", ".plugin",
host.bridge.add_method("merge_request_parse_data", ".plugin",
in_sign='ss', out_sign='aa{ss}',
method=self._parseData,
method=self._parse_data,
async_=True)
host.bridge.addMethod("mergeRequestsImport", ".plugin",
host.bridge.add_method("merge_requests_import", ".plugin",
in_sign='ssssa{ss}s', out_sign='',
method=self._import,
async_=True
@ -141,7 +141,7 @@ class MergeRequests(object):
def serialise(self, get_data):
tickets_xmlui, metadata, items_patches = get_data
tickets_xmlui_s, metadata = self._p.transItemsData((tickets_xmlui, metadata))
tickets_xmlui_s, metadata = self._p.trans_items_data((tickets_xmlui, metadata))
return data_format.serialise({
"items": tickets_xmlui_s,
"metadata": metadata,
@ -151,7 +151,7 @@ class MergeRequests(object):
def _get(self, service='', node='', max_items=10, item_ids=None, sub_id=None,
extra="", profile_key=C.PROF_KEY_NONE):
extra = data_format.deserialise(extra)
client, service, node, max_items, extra, sub_id = self._s.prepareBridgeGet(
client, service, node, max_items, extra, sub_id = self._s.prepare_bridge_get(
service, node, max_items, sub_id, extra, profile_key)
d = self.get(client, service, node or None, max_items, item_ids, sub_id or None,
extra.rsm_request, extra.extra)
@ -178,11 +178,11 @@ class MergeRequests(object):
# XXX: Q&D way to get list for labels when displaying them, but text when we
# have to modify them
if C.bool(extra.get('labels_as_list', C.BOOL_FALSE)):
filters = {'labels': self._s.textbox2ListFilter}
filters = {'labels': self._s.textbox_2_list_filter}
else:
filters = {}
tickets_xmlui, metadata = yield defer.ensureDeferred(
self._s.getDataFormItems(
self._s.get_data_form_items(
client,
service,
node,
@ -199,13 +199,13 @@ class MergeRequests(object):
for ticket in tickets_xmlui:
request_type = ticket.named_widgets[FIELD_DATA_TYPE].value
request_data = ticket.named_widgets[FIELD_DATA].value
parsed_data = yield self.parseData(request_type, request_data)
parsed_data = yield self.parse_data(request_type, request_data)
parsed_patches.append(parsed_data)
defer.returnValue((tickets_xmlui, metadata, parsed_patches))
def _set(self, service, node, repository, method, values, schema=None, item_id=None,
extra="", profile_key=C.PROF_KEY_NONE):
client, service, node, schema, item_id, extra = self._s.prepareBridgeSet(
client, service, node, schema, item_id, extra = self._s.prepare_bridge_set(
service, node, schema, item_id, extra, profile_key)
d = defer.ensureDeferred(
self.set(
@ -290,13 +290,13 @@ class MergeRequests(object):
deserialise, form_ns=APP_NS_MERGE_REQUESTS)
return item_id
def _parseData(self, data_type, data):
d = self.parseData(data_type, data)
def _parse_data(self, data_type, data):
d = self.parse_data(data_type, data)
d.addCallback(lambda parsed_patches:
{key: str(value) for key, value in parsed_patches.items()})
return d
def parseData(self, data_type, data):
def parse_data(self, data_type, data):
"""Parse a merge request data according to type
@param data_type(unicode): type of the data to parse
@ -314,7 +314,7 @@ class MergeRequests(object):
def _import(self, repository, item_id, service=None, node=None, extra=None,
profile_key=C.PROF_KEY_NONE):
client = self.host.getClient(profile_key)
client = self.host.get_client(profile_key)
service = jid.JID(service) if service else None
d = self.import_request(client, repository, item_id, service, node or None,
extra=extra or None)
@ -323,14 +323,14 @@ class MergeRequests(object):
@defer.inlineCallbacks
def import_request(self, client, repository, item, service=None, node=None,
extra=None):
"""Import a merge request in specified directory
"""import a merge request in specified directory
@param repository(unicode): path to the repository where the code stands
"""
if not node:
node = self.namespace
tickets_xmlui, metadata = yield defer.ensureDeferred(
self._s.getDataFormItems(
self._s.get_data_form_items(
client,
service,
node,

View file

@ -75,7 +75,7 @@ class NatPort(object):
def unload(self):
if self._to_unmap:
log.info("Cleaning mapped ports")
return threads.deferToThread(self._unmapPortsBlocking)
return threads.deferToThread(self._unmap_ports_blocking)
def _init_failed(self, failure_):
e = failure_.trap(exceptions.NotFound, exceptions.FeatureNotFound)
@ -98,23 +98,23 @@ class NatPort(object):
except Exception:
raise failure.Failure(exceptions.FeatureNotFound())
def getIP(self, local=False):
def get_ip(self, local=False):
"""Return IP address found with UPnP-IGD
@param local(bool): True to get external IP address, False to get local network one
@return (None, str): found IP address, or None of something got wrong
"""
def getIP(__):
def get_ip(__):
if self._upnp is None:
return None
# lanaddr can be the empty string if not found,
# we need to return None in this case
return (self._upnp.lanaddr or None) if local else self._external_ip
return self._initialised.addCallback(getIP)
return self._initialised.addCallback(get_ip)
def _unmapPortsBlocking(self):
def _unmap_ports_blocking(self):
"""Unmap ports mapped in this session"""
self._mutex.acquire()
try:
@ -137,7 +137,7 @@ class NatPort(object):
finally:
self._mutex.release()
def _mapPortBlocking(self, int_port, ext_port, protocol, desc):
def _map_port_blocking(self, int_port, ext_port, protocol, desc):
"""Internal blocking method to map port
@param int_port(int): internal port to use
@ -186,7 +186,7 @@ class NatPort(object):
return ext_port
def mapPort(self, int_port, ext_port=None, protocol="TCP", desc=DEFAULT_DESC):
def map_port(self, int_port, ext_port=None, protocol="TCP", desc=DEFAULT_DESC):
"""Add a port mapping
@param int_port(int): internal port to use
@ -199,7 +199,7 @@ class NatPort(object):
if self._upnp is None:
return defer.succeed(None)
def mappingCb(ext_port):
def mapping_cb(ext_port):
log.info(
"{protocol} mapping from {int_port} to {ext_port} successful".format(
protocol=protocol, int_port=int_port, ext_port=ext_port
@ -207,16 +207,16 @@ class NatPort(object):
)
return ext_port
def mappingEb(failure_):
def mapping_eb(failure_):
failure_.trap(MappingError)
log.warning("Can't map internal {int_port}".format(int_port=int_port))
def mappingUnknownEb(failure_):
def mapping_unknown_eb(failure_):
log.error(_("error while trying to map ports: {msg}").format(msg=failure_))
d = threads.deferToThread(
self._mapPortBlocking, int_port, ext_port, protocol, desc
self._map_port_blocking, int_port, ext_port, protocol, desc
)
d.addCallbacks(mappingCb, mappingEb)
d.addErrback(mappingUnknownEb)
d.addCallbacks(mapping_cb, mapping_eb)
d.addErrback(mapping_unknown_eb)
return d

View file

@ -44,7 +44,7 @@ PLUGIN_INFO = {
class Quiz(object):
def inheritFromRoomGame(self, host):
def inherit_from_room_game(self, host):
global RoomGame
RoomGame = host.plugins["ROOM-GAME"].__class__
self.__class__ = type(
@ -53,7 +53,7 @@ class Quiz(object):
def __init__(self, host):
log.info(_("Plugin Quiz initialization"))
self.inheritFromRoomGame(host)
self.inherit_from_room_game(host)
RoomGame._init_(
self,
host,
@ -62,39 +62,39 @@ class Quiz(object):
game_init={"stage": None},
player_init={"score": 0},
)
host.bridge.addMethod(
"quizGameLaunch",
host.bridge.add_method(
"quiz_game_launch",
".plugin",
in_sign="asss",
out_sign="",
method=self._prepareRoom,
method=self._prepare_room,
) # args: players, room_jid, profile
host.bridge.addMethod(
"quizGameCreate",
host.bridge.add_method(
"quiz_game_create",
".plugin",
in_sign="sass",
out_sign="",
method=self._createGame,
method=self._create_game,
) # args: room_jid, players, profile
host.bridge.addMethod(
"quizGameReady",
host.bridge.add_method(
"quiz_game_ready",
".plugin",
in_sign="sss",
out_sign="",
method=self._playerReady,
method=self._player_ready,
) # args: player, referee, profile
host.bridge.addMethod(
"quizGameAnswer",
host.bridge.add_method(
"quiz_game_answer",
".plugin",
in_sign="ssss",
out_sign="",
method=self.playerAnswer,
method=self.player_answer,
)
host.bridge.addSignal(
"quizGameStarted", ".plugin", signature="ssass"
host.bridge.add_signal(
"quiz_game_started", ".plugin", signature="ssass"
) # args: room_jid, referee, players, profile
host.bridge.addSignal(
"quizGameNew",
host.bridge.add_signal(
"quiz_game_new",
".plugin",
signature="sa{ss}s",
doc={
@ -104,8 +104,8 @@ class Quiz(object):
"param_2": "%(doc_profile)s",
},
)
host.bridge.addSignal(
"quizGameQuestion",
host.bridge.add_signal(
"quiz_game_question",
".plugin",
signature="sssis",
doc={
@ -117,8 +117,8 @@ class Quiz(object):
"param_4": "%(doc_profile)s",
},
)
host.bridge.addSignal(
"quizGamePlayerBuzzed",
host.bridge.add_signal(
"quiz_game_player_buzzed",
".plugin",
signature="ssbs",
doc={
@ -129,8 +129,8 @@ class Quiz(object):
"param_3": "%(doc_profile)s",
},
)
host.bridge.addSignal(
"quizGamePlayerSays",
host.bridge.add_signal(
"quiz_game_player_says",
".plugin",
signature="sssis",
doc={
@ -142,8 +142,8 @@ class Quiz(object):
"param_4": "%(doc_profile)s",
},
)
host.bridge.addSignal(
"quizGameAnswerResult",
host.bridge.add_signal(
"quiz_game_answer_result",
".plugin",
signature="ssba{si}s",
doc={
@ -155,8 +155,8 @@ class Quiz(object):
"param_4": "%(doc_profile)s",
},
)
host.bridge.addSignal(
"quizGameTimerExpired",
host.bridge.add_signal(
"quiz_game_timer_expired",
".plugin",
signature="ss",
doc={
@ -165,8 +165,8 @@ class Quiz(object):
"param_1": "%(doc_profile)s",
},
)
host.bridge.addSignal(
"quizGameTimerRestarted",
host.bridge.add_signal(
"quiz_game_timer_restarted",
".plugin",
signature="sis",
doc={
@ -238,7 +238,7 @@ class Quiz(object):
def __start_play(self, room_jid, game_data, profile):
"""Start the game (tell to the first player after dealer to play"""
client = self.host.getClient(profile)
client = self.host.get_client(profile)
game_data["stage"] = "play"
next_player_idx = game_data["current_player"] = (
game_data["init_player"] + 1
@ -251,9 +251,9 @@ class Quiz(object):
mess.firstChildElement().addElement("your_turn")
client.send(mess)
def playerAnswer(self, player, referee, answer, profile_key=C.PROF_KEY_NONE):
def player_answer(self, player, referee, answer, profile_key=C.PROF_KEY_NONE):
"""Called when a player give an answer"""
client = self.host.getClient(profile_key)
client = self.host.get_client(profile_key)
log.debug(
"new player answer (%(profile)s): %(answer)s"
% {"profile": client.profile, "answer": answer}
@ -264,17 +264,17 @@ class Quiz(object):
answer_elt.addContent(answer)
client.send(mess)
def timerExpired(self, room_jid, profile):
def timer_expired(self, room_jid, profile):
"""Called when nobody answered the question in time"""
client = self.host.getClient(profile)
client = self.host.get_client(profile)
game_data = self.games[room_jid]
game_data["stage"] = "expired"
mess = self.createGameElt(room_jid)
mess.firstChildElement().addElement("timer_expired")
client.send(mess)
reactor.callLater(4, self.askQuestion, room_jid, client.profile)
reactor.callLater(4, self.ask_question, room_jid, client.profile)
def pauseTimer(self, room_jid):
def pause_timer(self, room_jid):
"""Stop the timer and save the time left"""
game_data = self.games[room_jid]
left = max(0, game_data["timer"].getTime() - time())
@ -283,9 +283,9 @@ class Quiz(object):
game_data["previous_stage"] = game_data["stage"]
game_data["stage"] = "paused"
def restartTimer(self, room_jid, profile):
def restart_timer(self, room_jid, profile):
"""Restart a timer with the saved time"""
client = self.host.getClient(profile)
client = self.host.get_client(profile)
game_data = self.games[room_jid]
assert game_data["time_left"] is not None
mess = self.createGameElt(room_jid)
@ -293,15 +293,15 @@ class Quiz(object):
jabber_client.restarted_elt["time_left"] = str(game_data["time_left"])
client.send(mess)
game_data["timer"] = reactor.callLater(
game_data["time_left"], self.timerExpired, room_jid, profile
game_data["time_left"], self.timer_expired, room_jid, profile
)
game_data["time_left"] = None
game_data["stage"] = game_data["previous_stage"]
del game_data["previous_stage"]
def askQuestion(self, room_jid, profile):
def ask_question(self, room_jid, profile):
"""Ask a new question"""
client = self.host.getClient(profile)
client = self.host.get_client(profile)
game_data = self.games[room_jid]
game_data["stage"] = "question"
game_data["question_id"] = "1"
@ -314,13 +314,13 @@ class Quiz(object):
)
client.send(mess)
game_data["timer"] = reactor.callLater(
timer, self.timerExpired, room_jid, profile
timer, self.timer_expired, room_jid, profile
)
game_data["time_left"] = None
def checkAnswer(self, room_jid, player, answer, profile):
def check_answer(self, room_jid, player, answer, profile):
"""Check if the answer given is right"""
client = self.host.getClient(profile)
client = self.host.get_client(profile)
game_data = self.games[room_jid]
players_data = game_data["players_data"]
good_answer = game_data["question_id"] == "1" and answer == "42"
@ -334,11 +334,11 @@ class Quiz(object):
client.send(mess)
if good_answer:
reactor.callLater(4, self.askQuestion, room_jid, profile)
reactor.callLater(4, self.ask_question, room_jid, profile)
else:
reactor.callLater(4, self.restartTimer, room_jid, profile)
reactor.callLater(4, self.restart_timer, room_jid, profile)
def newGame(self, room_jid, profile):
def new_game(self, room_jid, profile):
"""Launch a new round"""
common_data = {"game_score": 0}
new_game_data = {
@ -349,11 +349,11 @@ Attention, tu es prêt ?"""
)
}
msg_elts = self.__game_data_to_xml(new_game_data)
RoomGame.newRound(self, room_jid, (common_data, msg_elts), profile)
reactor.callLater(10, self.askQuestion, room_jid, profile)
RoomGame.new_round(self, room_jid, (common_data, msg_elts), profile)
reactor.callLater(10, self.ask_question, room_jid, profile)
def room_game_cmd(self, mess_elt, profile):
client = self.host.getClient(profile)
client = self.host.get_client(profile)
from_jid = jid.JID(mess_elt["from"])
room_jid = jid.JID(from_jid.userhost())
game_elt = mess_elt.firstChildElement()
@ -367,7 +367,7 @@ Attention, tu es prêt ?"""
players = []
for player in elt.elements():
players.append(str(player))
self.host.bridge.quizGameStarted(
self.host.bridge.quiz_game_started(
room_jid.userhost(), from_jid.full(), players, profile
)
@ -383,15 +383,15 @@ Attention, tu es prêt ?"""
if (
list(status.values()).count("ready") == nb_players
): # everybody is ready, we can start the game
self.newGame(room_jid, profile)
self.new_game(room_jid, profile)
elif elt.name == "game_data":
self.host.bridge.quizGameNew(
self.host.bridge.quiz_game_new(
room_jid.userhost(), self.__xml_to_game_data(elt), profile
)
elif elt.name == "question": # A question is asked
self.host.bridge.quizGameQuestion(
self.host.bridge.quiz_game_question(
room_jid.userhost(),
elt["id"],
str(elt),
@ -411,7 +411,7 @@ Attention, tu es prêt ?"""
buzzer_elt["pause"] = str(pause)
client.send(mess)
if pause:
self.pauseTimer(room_jid)
self.pause_timer(room_jid)
# and we send the player answer
mess = self.createGameElt(room_jid)
_answer = str(elt)
@ -421,16 +421,16 @@ Attention, tu es prêt ?"""
say_elt["delay"] = "3"
reactor.callLater(2, client.send, mess)
reactor.callLater(
6, self.checkAnswer, room_jid, player, _answer, profile=profile
6, self.check_answer, room_jid, player, _answer, profile=profile
)
elif elt.name == "player_buzzed":
self.host.bridge.quizGamePlayerBuzzed(
self.host.bridge.quiz_game_player_buzzed(
room_jid.userhost(), elt["player"], elt["pause"] == str(True), profile
)
elif elt.name == "player_says":
self.host.bridge.quizGamePlayerSays(
self.host.bridge.quiz_game_player_says(
room_jid.userhost(),
elt["player"],
str(elt),
@ -440,15 +440,15 @@ Attention, tu es prêt ?"""
elif elt.name == "answer_result":
player, good_answer, score = self.__answer_result_to_signal_args(elt)
self.host.bridge.quizGameAnswerResult(
self.host.bridge.quiz_game_answer_result(
room_jid.userhost(), player, good_answer, score, profile
)
elif elt.name == "timer_expired":
self.host.bridge.quizGameTimerExpired(room_jid.userhost(), profile)
self.host.bridge.quiz_game_timer_expired(room_jid.userhost(), profile)
elif elt.name == "timer_restarted":
self.host.bridge.quizGameTimerRestarted(
self.host.bridge.quiz_game_timer_restarted(
room_jid.userhost(), int(elt["time_left"]), profile
)

View file

@ -65,7 +65,7 @@ QUEUE_LIMIT = 2
class Radiocol(object):
def inheritFromRoomGame(self, host):
def inherit_from_room_game(self, host):
global RoomGame
RoomGame = host.plugins["ROOM-GAME"].__class__
self.__class__ = type(
@ -74,7 +74,7 @@ class Radiocol(object):
def __init__(self, host):
log.info(_("Radio collective initialization"))
self.inheritFromRoomGame(host)
self.inherit_from_room_game(host)
RoomGame._init_(
self,
host,
@ -89,49 +89,49 @@ class Radiocol(object):
},
)
self.host = host
host.bridge.addMethod(
"radiocolLaunch",
host.bridge.add_method(
"radiocol_launch",
".plugin",
in_sign="asss",
out_sign="",
method=self._prepareRoom,
method=self._prepare_room,
async_=True,
)
host.bridge.addMethod(
"radiocolCreate",
host.bridge.add_method(
"radiocol_create",
".plugin",
in_sign="sass",
out_sign="",
method=self._createGame,
method=self._create_game,
)
host.bridge.addMethod(
"radiocolSongAdded",
host.bridge.add_method(
"radiocol_song_added",
".plugin",
in_sign="sss",
out_sign="",
method=self._radiocolSongAdded,
method=self._radiocol_song_added,
async_=True,
)
host.bridge.addSignal(
"radiocolPlayers", ".plugin", signature="ssass"
host.bridge.add_signal(
"radiocol_players", ".plugin", signature="ssass"
) # room_jid, referee, players, profile
host.bridge.addSignal(
"radiocolStarted", ".plugin", signature="ssasais"
host.bridge.add_signal(
"radiocol_started", ".plugin", signature="ssasais"
) # room_jid, referee, players, [QUEUE_TO_START, QUEUE_LIMIT], profile
host.bridge.addSignal(
"radiocolSongRejected", ".plugin", signature="sss"
host.bridge.add_signal(
"radiocol_song_rejected", ".plugin", signature="sss"
) # room_jid, reason, profile
host.bridge.addSignal(
"radiocolPreload", ".plugin", signature="ssssssss"
host.bridge.add_signal(
"radiocol_preload", ".plugin", signature="ssssssss"
) # room_jid, timestamp, filename, title, artist, album, profile
host.bridge.addSignal(
"radiocolPlay", ".plugin", signature="sss"
host.bridge.add_signal(
"radiocol_play", ".plugin", signature="sss"
) # room_jid, filename, profile
host.bridge.addSignal(
"radiocolNoUpload", ".plugin", signature="ss"
host.bridge.add_signal(
"radiocol_no_upload", ".plugin", signature="ss"
) # room_jid, profile
host.bridge.addSignal(
"radiocolUploadOk", ".plugin", signature="ss"
host.bridge.add_signal(
"radiocol_upload_ok", ".plugin", signature="ss"
) # room_jid, profile
def __create_preload_elt(self, sender, song_added_elt):
@ -143,10 +143,10 @@ class Radiocol(object):
# XXX: the frontend should know the temporary directory where file is put
return preload_elt
def _radiocolSongAdded(self, referee_s, song_path, profile):
return self.radiocolSongAdded(jid.JID(referee_s), song_path, profile)
def _radiocol_song_added(self, referee_s, song_path, profile):
return self.radiocol_song_added(jid.JID(referee_s), song_path, profile)
def radiocolSongAdded(self, referee, song_path, profile):
def radiocol_song_added(self, referee, song_path, profile):
"""This method is called by libervia when a song has been uploaded
@param referee (jid.JID): JID of the referee in the room (room userhost + '/' + nick)
@param song_path (unicode): absolute path of the song added
@ -174,7 +174,7 @@ class Radiocol(object):
song = OggVorbis(song_path)
except (OggVorbisHeaderError, HeaderNotFoundError):
# this file is not ogg vorbis nor mp3, we reject it
self.deleteFile(song_path) # FIXME: same host trick (see note above)
self.delete_file(song_path) # FIXME: same host trick (see note above)
return defer.fail(
exceptions.DataError(
D_(
@ -200,7 +200,7 @@ class Radiocol(object):
) # FIXME: works only because of the same host trick, see the note under the docstring
return self.send(referee, ("", "song_added"), attrs, profile=profile)
def playNext(self, room_jid, profile):
def play_next(self, room_jid, profile):
""""Play next song in queue if exists, and put a timer
which trigger after the song has been played to play next one"""
# TODO: songs need to be erased once played or found invalids
@ -210,7 +210,7 @@ class Radiocol(object):
log.debug(_("No more participants in the radiocol: cleaning data"))
radio_data["queue"] = []
for filename in radio_data["to_delete"]:
self.deleteFile(filename, radio_data)
self.delete_file(filename, radio_data)
radio_data["to_delete"] = {}
queue = radio_data["queue"]
if not queue:
@ -228,13 +228,13 @@ class Radiocol(object):
self.send(room_jid, ("", "upload_ok"), profile=profile)
radio_data["upload"] = True
reactor.callLater(length, self.playNext, room_jid, profile)
reactor.callLater(length, self.play_next, room_jid, profile)
# we wait more than the song length to delete the file, to manage poorly reactive networks/clients
reactor.callLater(
length + 90, self.deleteFile, filename, radio_data
length + 90, self.delete_file, filename, radio_data
) # FIXME: same host trick (see above)
def deleteFile(self, filename, radio_data=None):
def delete_file(self, filename, radio_data=None):
"""
Delete a previously uploaded file.
@param filename: filename to delete, or full filepath if radio_data is None
@ -263,16 +263,16 @@ class Radiocol(object):
def room_game_cmd(self, mess_elt, profile):
from_jid = jid.JID(mess_elt["from"])
room_jid = from_jid.userhostJID()
nick = self.host.plugins["XEP-0045"].getRoomNick(room_jid, profile)
nick = self.host.plugins["XEP-0045"].get_room_nick(room_jid, profile)
radio_elt = mess_elt.firstChildElement()
radio_data = self.games[room_jid]
if "queue" in radio_data:
queue = radio_data["queue"]
from_referee = self.isReferee(room_jid, from_jid.resource)
to_referee = self.isReferee(room_jid, jid.JID(mess_elt["to"]).user)
is_player = self.isPlayer(room_jid, nick)
from_referee = self.is_referee(room_jid, from_jid.resource)
to_referee = self.is_referee(room_jid, jid.JID(mess_elt["to"]).user)
is_player = self.is_player(room_jid, nick)
for elt in radio_elt.elements():
if not from_referee and not (to_referee and elt.name == "song_added"):
continue # sender must be referee, expect when a song is submitted
@ -287,9 +287,9 @@ class Radiocol(object):
for player in elt.elements():
players.append(str(player))
signal = (
self.host.bridge.radiocolStarted
self.host.bridge.radiocol_started
if elt.name == "started"
else self.host.bridge.radiocolPlayers
else self.host.bridge.radiocol_players
)
signal(
room_jid.userhost(),
@ -299,7 +299,7 @@ class Radiocol(object):
profile,
)
elif elt.name == "preload": # a song is in queue and must be preloaded
self.host.bridge.radiocolPreload(
self.host.bridge.radiocol_preload(
room_jid.userhost(),
elt["timestamp"],
elt["filename"],
@ -310,17 +310,17 @@ class Radiocol(object):
profile,
)
elif elt.name == "play":
self.host.bridge.radiocolPlay(
self.host.bridge.radiocol_play(
room_jid.userhost(), elt["filename"], profile
)
elif elt.name == "song_rejected": # a song has been refused
self.host.bridge.radiocolSongRejected(
self.host.bridge.radiocol_song_rejected(
room_jid.userhost(), elt["reason"], profile
)
elif elt.name == "no_upload":
self.host.bridge.radiocolNoUpload(room_jid.userhost(), profile)
self.host.bridge.radiocol_no_upload(room_jid.userhost(), profile)
elif elt.name == "upload_ok":
self.host.bridge.radiocolUploadOk(room_jid.userhost(), profile)
self.host.bridge.radiocol_upload_ok(room_jid.userhost(), profile)
elif elt.name == "song_added": # a song has been added
# FIXME: we are KISS for the proof of concept: every song is added, to a limit of 3 in queue.
# Need to manage some sort of rules to allow peoples to send songs
@ -348,11 +348,11 @@ class Radiocol(object):
if not radio_data["playing"] and len(queue) == QUEUE_TO_START:
# We have not started playing yet, and we have QUEUE_TO_START
# songs in queue. We can now start the party :)
self.playNext(room_jid, profile)
self.play_next(room_jid, profile)
else:
log.error(_("Unmanaged game element: %s") % elt.name)
def getSyncDataForPlayer(self, room_jid, nick):
def get_sync_data_for_player(self, room_jid, nick):
game_data = self.games[room_jid]
elements = []
if game_data["playing"]:

View file

@ -49,14 +49,14 @@ class RegisterAccount(object):
log.info(_("Plugin Register Account initialization"))
self.host = host
self._sessions = Sessions()
host.registerCallback(
self.registerNewAccountCB, with_data=True, force_id="registerNewAccount"
host.register_callback(
self.register_new_account_cb, with_data=True, force_id="register_new_account"
)
self.__register_account_id = host.registerCallback(
self._registerConfirmation, with_data=True
self.__register_account_id = host.register_callback(
self._register_confirmation, with_data=True
)
def registerNewAccountCB(self, data, profile):
def register_new_account_cb(self, data, profile):
"""Called when the user click on the "New account" button."""
session_data = {}
@ -81,7 +81,7 @@ class RegisterAccount(object):
session_data["user"], host, resource = jid.parse(session_data["JabberID"])
session_data["server"] = session_data[C.FORCE_SERVER_PARAM] or host
session_id, __ = self._sessions.newSession(session_data, profile=profile)
session_id, __ = self._sessions.new_session(session_data, profile=profile)
form_ui = xml_tools.XMLUI(
"form",
title=D_("Register new account"),
@ -95,30 +95,30 @@ class RegisterAccount(object):
)
return {"xmlui": form_ui.toXml()}
def _registerConfirmation(self, data, profile):
def _register_confirmation(self, data, profile):
"""Save the related parameters and proceed the registration."""
session_data = self._sessions.profileGet(data["session_id"], profile)
session_data = self._sessions.profile_get(data["session_id"], profile)
self.host.memory.setParam(
self.host.memory.param_set(
"JabberID", session_data["JabberID"], "Connection", profile_key=profile
)
self.host.memory.setParam(
self.host.memory.param_set(
"Password", session_data["Password"], "Connection", profile_key=profile
)
self.host.memory.setParam(
self.host.memory.param_set(
C.FORCE_SERVER_PARAM,
session_data[C.FORCE_SERVER_PARAM],
"Connection",
profile_key=profile,
)
self.host.memory.setParam(
self.host.memory.param_set(
C.FORCE_PORT_PARAM,
session_data[C.FORCE_PORT_PARAM],
"Connection",
profile_key=profile,
)
d = self._registerNewAccount(
d = self._register_new_account(
jid.JID(session_data["JabberID"]),
session_data["Password"],
None,
@ -127,14 +127,14 @@ class RegisterAccount(object):
del self._sessions[data["session_id"]]
return d
def _registerNewAccount(self, client, jid_, password, email, server):
def _register_new_account(self, client, jid_, password, email, server):
#  FIXME: port is not set here
def registeredCb(__):
def registered_cb(__):
xmlui = xml_tools.XMLUI("popup", title=D_("Confirmation"))
xmlui.addText(D_("Registration successful."))
return {"xmlui": xmlui.toXml()}
def registeredEb(failure):
def registered_eb(failure):
xmlui = xml_tools.XMLUI("popup", title=D_("Failure"))
xmlui.addText(D_("Registration failed: %s") % failure.getErrorMessage())
try:
@ -146,8 +146,8 @@ class RegisterAccount(object):
pass
return {"xmlui": xmlui.toXml()}
registered_d = self.host.plugins["XEP-0077"].registerNewAccount(
registered_d = self.host.plugins["XEP-0077"].register_new_account(
client, jid_, password, email=email, host=server, port=C.XMPP_C2S_PORT
)
registered_d.addCallbacks(registeredCb, registeredEb)
registered_d.addCallbacks(registered_cb, registered_eb)
return registered_d

View file

@ -56,9 +56,9 @@ PLUGIN_INFO = {
class RoomGame(object):
"""This class is used to help launching a MUC game.
Bridge methods callbacks: _prepareRoom, _playerReady, _createGame
Triggered methods: userJoinedTrigger, userLeftTrigger
Also called from subclasses: newRound
bridge methods callbacks: _prepare_room, _player_ready, _create_game
Triggered methods: user_joined_trigger, user_left_trigger
Also called from subclasses: new_round
For examples of messages sequences, please look in sub-classes.
"""
@ -81,13 +81,13 @@ class RoomGame(object):
class MyGame(object):
def inheritFromRoomGame(self, host):
def inherit_from_room_game(self, host):
global RoomGame
RoomGame = host.plugins["ROOM-GAME"].__class__
self.__class__ = type(self.__class__.__name__, (self.__class__, RoomGame, object), {})
def __init__(self, host):
self.inheritFromRoomGame(host)
self.inherit_from_room_game(host)
RoomGame._init_(self, host, ...)
"""
@ -125,41 +125,41 @@ class RoomGame(object):
# by an arbitrary value. If needed, this attribute would be set to True from the testcase.
self.testing = False
host.trigger.add("MUC user joined", self.userJoinedTrigger)
host.trigger.add("MUC user left", self.userLeftTrigger)
host.trigger.add("MUC user joined", self.user_joined_trigger)
host.trigger.add("MUC user left", self.user_left_trigger)
def _createOrInvite(self, room_jid, other_players, profile):
def _create_or_invite(self, room_jid, other_players, profile):
"""
This is called only when someone explicitly wants to play.
The game will not be created if one already exists in the room,
also its creation could be postponed until all the expected players
join the room (in that case it will be created from userJoinedTrigger).
join the room (in that case it will be created from user_joined_trigger).
@param room (wokkel.muc.Room): the room
@param other_players (list[jid.JID]): list of the other players JID (bare)
"""
# FIXME: broken !
raise NotImplementedError("To be fixed")
client = self.host.getClient(profile)
user_jid = self.host.getJidNStream(profile)[0]
nick = self.host.plugins["XEP-0045"].getRoomNick(client, room_jid)
client = self.host.get_client(profile)
user_jid = self.host.get_jid_n_stream(profile)[0]
nick = self.host.plugins["XEP-0045"].get_room_nick(client, room_jid)
nicks = [nick]
if self._gameExists(room_jid):
if not self._checkJoinAuth(room_jid, user_jid, nick):
if self._game_exists(room_jid):
if not self._check_join_auth(room_jid, user_jid, nick):
return
nicks.extend(self._invitePlayers(room_jid, other_players, nick, profile))
self._updatePlayers(room_jid, nicks, True, profile)
nicks.extend(self._invite_players(room_jid, other_players, nick, profile))
self._update_players(room_jid, nicks, True, profile)
else:
self._initGame(room_jid, nick)
(auth, waiting, missing) = self._checkWaitAuth(room_jid, other_players)
self._init_game(room_jid, nick)
(auth, waiting, missing) = self._check_wait_auth(room_jid, other_players)
nicks.extend(waiting)
nicks.extend(self._invitePlayers(room_jid, missing, nick, profile))
nicks.extend(self._invite_players(room_jid, missing, nick, profile))
if auth:
self.createGame(room_jid, nicks, profile)
self.create_game(room_jid, nicks, profile)
else:
self._updatePlayers(room_jid, nicks, False, profile)
self._update_players(room_jid, nicks, False, profile)
def _initGame(self, room_jid, referee_nick):
def _init_game(self, room_jid, referee_nick):
"""
@param room_jid (jid.JID): JID of the room
@ -167,7 +167,7 @@ class RoomGame(object):
"""
# Important: do not add the referee to 'players' yet. For a
# <players /> message to be emitted whenever a new player is joining,
# it is necessary to not modify 'players' outside of _updatePlayers.
# it is necessary to not modify 'players' outside of _update_players.
referee_jid = jid.JID(room_jid.userhost() + "/" + referee_nick)
self.games[room_jid] = {
"referee": referee_jid,
@ -178,19 +178,19 @@ class RoomGame(object):
self.games[room_jid].update(copy.deepcopy(self.game_init))
self.invitations.setdefault(room_jid, [])
def _gameExists(self, room_jid, started=False):
def _game_exists(self, room_jid, started=False):
"""Return True if a game has been initialized/started.
@param started: if False, the game must be initialized to return True,
otherwise it must be initialized and started with createGame.
otherwise it must be initialized and started with create_game.
@return: True if a game is initialized/started in that room"""
return room_jid in self.games and (not started or self.games[room_jid]["started"])
def _checkJoinAuth(self, room_jid, user_jid=None, nick="", verbose=False):
def _check_join_auth(self, room_jid, user_jid=None, nick="", verbose=False):
"""Checks if this profile is allowed to join the game.
The parameter nick is used to check if the user is already
a player in that game. When this method is called from
userJoinedTrigger, nick is also used to check the user
user_joined_trigger, nick is also used to check the user
identity instead of user_jid_s (see TODO comment below).
@param room_jid (jid.JID): the JID of the room hosting the game
@param user_jid (jid.JID): JID of the user
@ -198,9 +198,9 @@ class RoomGame(object):
@return: True if this profile can join the game
"""
auth = False
if not self._gameExists(room_jid):
if not self._game_exists(room_jid):
auth = False
elif self.join_mode == self.ALL or self.isPlayer(room_jid, nick):
elif self.join_mode == self.ALL or self.is_player(room_jid, nick):
auth = True
elif self.join_mode == self.INVITED:
# considering all the batches of invitations
@ -227,7 +227,7 @@ class RoomGame(object):
)
return auth
def _updatePlayers(self, room_jid, nicks, sync, profile):
def _update_players(self, room_jid, nicks, sync, profile):
"""Update the list of players and signal to the room that some players joined the game.
If sync is True, the news players are synchronized with the game data they have missed.
Remark: self.games[room_jid]['players'] should not be modified outside this method.
@ -251,16 +251,16 @@ class RoomGame(object):
sync = (
sync
and self._gameExists(room_jid, True)
and self._game_exists(room_jid, True)
and len(self.games[room_jid]["players"]) > 0
)
setStatus("desync" if sync else "init")
self.games[room_jid]["players"].extend(new_nicks)
self._synchronizeRoom(room_jid, [room_jid], profile)
self._synchronize_room(room_jid, [room_jid], profile)
if sync:
setStatus("init")
def _synchronizeRoom(self, room_jid, recipients, profile):
def _synchronize_room(self, room_jid, recipients, profile):
"""Communicate the list of players to the whole room or only to some users,
also send the synchronization data to the players who recently joined the game.
@param room_jid (jid.JID): JID of the room
@ -269,16 +269,16 @@ class RoomGame(object):
- room JID + "/" + user nick
@param profile (unicode): %(doc_profile)s
"""
if self._gameExists(room_jid, started=True):
element = self._createStartElement(self.games[room_jid]["players"])
if self._game_exists(room_jid, started=True):
element = self._create_start_element(self.games[room_jid]["players"])
else:
element = self._createStartElement(
element = self._create_start_element(
self.games[room_jid]["players"], name="players"
)
elements = [(element, None, None)]
sync_args = []
sync_data = self._getSyncData(room_jid)
sync_data = self._get_sync_data(room_jid)
for nick in sync_data:
user_jid = jid.JID(room_jid.userhost() + "/" + nick)
if user_jid in recipients:
@ -291,19 +291,19 @@ class RoomGame(object):
sync_args.append(([user_jid, user_elements], {"profile": profile}))
for recipient in recipients:
self._sendElements(recipient, elements, profile=profile)
self._send_elements(recipient, elements, profile=profile)
for args, kwargs in sync_args:
self._sendElements(*args, **kwargs)
self._send_elements(*args, **kwargs)
def _getSyncData(self, room_jid, force_nicks=None):
def _get_sync_data(self, room_jid, force_nicks=None):
"""The synchronization data are returned for each player who
has the state 'desync' or if he's been contained by force_nicks.
@param room_jid (jid.JID): JID of the room
@param force_nicks: force the synchronization for this list of the nicks
@return: a mapping between player nicks and a list of elements to
be sent by self._synchronizeRoom for the game to be synchronized.
be sent by self._synchronize_room for the game to be synchronized.
"""
if not self._gameExists(room_jid):
if not self._game_exists(room_jid):
return {}
data = {}
status = self.games[room_jid]["status"]
@ -314,12 +314,12 @@ class RoomGame(object):
if nick not in nicks:
nicks.append(nick)
for nick in nicks:
elements = self.getSyncDataForPlayer(room_jid, nick)
elements = self.get_sync_data_for_player(room_jid, nick)
if elements:
data[nick] = elements
return data
def getSyncDataForPlayer(self, room_jid, nick):
def get_sync_data_for_player(self, room_jid, nick):
"""This method may (and should probably) be overwritten by a child class.
@param room_jid (jid.JID): JID of the room
@param nick: the nick of the player to be synchronized
@ -327,7 +327,7 @@ class RoomGame(object):
"""
return []
def _invitePlayers(self, room_jid, other_players, nick, profile):
def _invite_players(self, room_jid, other_players, nick, profile):
"""Invite players to a room, associated game may exist or not.
@param other_players (list[jid.JID]): list of the players to invite
@ -336,7 +336,7 @@ class RoomGame(object):
"""
raise NotImplementedError("Need to be fixed !")
# FIXME: this is broken and unsecure !
if not self._checkInviteAuth(room_jid, nick):
if not self._check_invite_auth(room_jid, nick):
return []
# TODO: remove invitation waiting for too long, using the time data
self.invitations[room_jid].append(
@ -356,7 +356,7 @@ class RoomGame(object):
nicks.append(other_nick)
return nicks
def _checkInviteAuth(self, room_jid, nick, verbose=False):
def _check_invite_auth(self, room_jid, nick, verbose=False):
"""Checks if this user is allowed to invite players
@param room_jid (jid.JID): JID of the room
@ -365,16 +365,16 @@ class RoomGame(object):
@return: True if the user is allowed to invite other players
"""
auth = False
if self.invite_mode == self.FROM_ALL or not self._gameExists(room_jid):
if self.invite_mode == self.FROM_ALL or not self._game_exists(room_jid):
auth = True
elif self.invite_mode == self.FROM_NONE:
auth = not self._gameExists(room_jid, started=True) and self.isReferee(
auth = not self._game_exists(room_jid, started=True) and self.is_referee(
room_jid, nick
)
elif self.invite_mode == self.FROM_REFEREE:
auth = self.isReferee(room_jid, nick)
auth = self.is_referee(room_jid, nick)
elif self.invite_mode == self.FROM_PLAYERS:
auth = self.isPlayer(room_jid, nick)
auth = self.is_player(room_jid, nick)
if not auth and (verbose or _DEBUG):
log.debug(
_("%(user)s not allowed to invite for the game %(game)s in %(room)s")
@ -382,31 +382,31 @@ class RoomGame(object):
)
return auth
def isReferee(self, room_jid, nick):
def is_referee(self, room_jid, nick):
"""Checks if the player with this nick is the referee for the game in this room"
@param room_jid (jid.JID): room JID
@param nick: user nick in the room
@return: True if the user is the referee of the game in this room
"""
if not self._gameExists(room_jid):
if not self._game_exists(room_jid):
return False
return (
jid.JID(room_jid.userhost() + "/" + nick) == self.games[room_jid]["referee"]
)
def isPlayer(self, room_jid, nick):
def is_player(self, room_jid, nick):
"""Checks if the user with this nick is a player for the game in this room.
@param room_jid (jid.JID): JID of the room
@param nick: user nick in the room
@return: True if the user is a player of the game in this room
"""
if not self._gameExists(room_jid):
if not self._game_exists(room_jid):
return False
# Important: the referee is not in the 'players' list right after
# the game initialization, that's why we do also check with isReferee
return nick in self.games[room_jid]["players"] or self.isReferee(room_jid, nick)
# the game initialization, that's why we do also check with is_referee
return nick in self.games[room_jid]["players"] or self.is_referee(room_jid, nick)
def _checkWaitAuth(self, room, other_players, verbose=False):
def _check_wait_auth(self, room, other_players, verbose=False):
"""Check if we must wait for other players before starting the game.
@param room (wokkel.muc.Room): the room
@ -441,26 +441,26 @@ class RoomGame(object):
)
return result
def getUniqueName(self, muc_service=None, profile_key=C.PROF_KEY_NONE):
def get_unique_name(self, muc_service=None, profile_key=C.PROF_KEY_NONE):
"""Generate unique room name
@param muc_service (jid.JID): you can leave empty to autofind the muc service
@param profile_key (unicode): %(doc_profile_key)s
@return: jid.JID (unique name for a new room to be created)
"""
client = self.host.getClient(profile_key)
client = self.host.get_client(profile_key)
# FIXME: jid.JID must be used instead of strings
room = self.host.plugins["XEP-0045"].getUniqueName(client, muc_service)
room = self.host.plugins["XEP-0045"].get_unique_name(client, muc_service)
return jid.JID("sat_%s_%s" % (self.name.lower(), room.userhost()))
def _prepareRoom(
def _prepare_room(
self, other_players=None, room_jid_s="", profile_key=C.PROF_KEY_NONE
):
room_jid = jid.JID(room_jid_s) if room_jid_s else None
other_players = [jid.JID(player).userhostJID() for player in other_players]
return self.prepareRoom(other_players, room_jid, profile_key)
return self.prepare_room(other_players, room_jid, profile_key)
def prepareRoom(self, other_players=None, room_jid=None, profile_key=C.PROF_KEY_NONE):
def prepare_room(self, other_players=None, room_jid=None, profile_key=C.PROF_KEY_NONE):
"""Prepare the room for a game: create it if it doesn't exist and invite players.
@param other_players (list[JID]): list of other players JID (bare)
@ -468,9 +468,9 @@ class RoomGame(object):
@param profile_key (unicode): %(doc_profile_key)s
"""
# FIXME: need to be refactored
client = self.host.getClient(profile_key)
client = self.host.get_client(profile_key)
log.debug(_("Preparing room for %s game") % self.name)
profile = self.host.memory.getProfileName(profile_key)
profile = self.host.memory.get_profile_name(profile_key)
if not profile:
log.error(_("Unknown profile"))
return defer.succeed(None)
@ -479,19 +479,19 @@ class RoomGame(object):
# Create/join the given room, or a unique generated one if no room is specified.
if room_jid is None:
room_jid = self.getUniqueName(profile_key=profile_key)
room_jid = self.get_unique_name(profile_key=profile_key)
else:
self.host.plugins["XEP-0045"].checkRoomJoined(client, room_jid)
self._createOrInvite(client, room_jid, other_players)
self.host.plugins["XEP-0045"].check_room_joined(client, room_jid)
self._create_or_invite(client, room_jid, other_players)
return defer.succeed(None)
user_jid = self.host.getJidNStream(profile)[0]
user_jid = self.host.get_jid_n_stream(profile)[0]
d = self.host.plugins["XEP-0045"].join(room_jid, user_jid.user, {}, profile)
return d.addCallback(
lambda __: self._createOrInvite(client, room_jid, other_players)
lambda __: self._create_or_invite(client, room_jid, other_players)
)
def userJoinedTrigger(self, room, user, profile):
def user_joined_trigger(self, room, user, profile):
"""This trigger is used to check if the new user can take part of a game, create the game if we were waiting for him or just update the players list.
@room: wokkel.muc.Room object. room.roster is a dict{wokkel.muc.User.nick: wokkel.muc.User}
@ -500,13 +500,13 @@ class RoomGame(object):
"""
room_jid = room.occupantJID.userhostJID()
profile_nick = room.occupantJID.resource
if not self.isReferee(room_jid, profile_nick):
if not self.is_referee(room_jid, profile_nick):
return True # profile is not the referee
if not self._checkJoinAuth(
if not self._check_join_auth(
room_jid, user.entity if user.entity else None, user.nick
):
# user not allowed but let him know that we are playing :p
self._synchronizeRoom(
self._synchronize_room(
room_jid, [jid.JID(room_jid.userhost() + "/" + user.nick)], profile
)
return True
@ -520,17 +520,17 @@ class RoomGame(object):
)
return True
other_players = self.invitations[room_jid][batch][1]
(auth, nicks, __) = self._checkWaitAuth(room, other_players)
(auth, nicks, __) = self._check_wait_auth(room, other_players)
if auth:
del self.invitations[room_jid][batch]
nicks.insert(0, profile_nick) # add the referee
self.createGame(room_jid, nicks, profile_key=profile)
self.create_game(room_jid, nicks, profile_key=profile)
return True
# let the room know that a new player joined
self._updatePlayers(room_jid, [user.nick], True, profile)
self._update_players(room_jid, [user.nick], True, profile)
return True
def userLeftTrigger(self, room, user, profile):
def user_left_trigger(self, room, user, profile):
"""This trigger is used to update or stop the game when a user leaves.
@room: wokkel.muc.Room object. room.roster is a dict{wokkel.muc.User.nick: wokkel.muc.User}
@ -539,9 +539,9 @@ class RoomGame(object):
"""
room_jid = room.occupantJID.userhostJID()
profile_nick = room.occupantJID.resource
if not self.isReferee(room_jid, profile_nick):
if not self.is_referee(room_jid, profile_nick):
return True # profile is not the referee
if self.isPlayer(room_jid, user.nick):
if self.is_player(room_jid, user.nick):
try:
self.games[room_jid]["players"].remove(user.nick)
except ValueError:
@ -559,7 +559,7 @@ class RoomGame(object):
self.invitations[room_jid][batch][1].append(user_jid)
return True
def _checkCreateGameAndInit(self, room_jid, profile):
def _check_create_game_and_init(self, room_jid, profile):
"""Check if that profile can create the game. If the game can be created
but is not initialized yet, this method will also do the initialization.
@ -569,16 +569,16 @@ class RoomGame(object):
- create: set to True to allow the game creation
- sync: set to True to advice a game synchronization
"""
user_nick = self.host.plugins["XEP-0045"].getRoomNick(room_jid, profile)
user_nick = self.host.plugins["XEP-0045"].get_room_nick(room_jid, profile)
if not user_nick:
log.error(
"Internal error: profile %s has not joined the room %s"
% (profile, room_jid.userhost())
)
return False, False
if self._gameExists(room_jid):
is_referee = self.isReferee(room_jid, user_nick)
if self._gameExists(room_jid, started=True):
if self._game_exists(room_jid):
is_referee = self.is_referee(room_jid, user_nick)
if self._game_exists(room_jid, started=True):
log.info(
_("%(game)s game already created in room %(room)s")
% {"game": self.name, "room": room_jid.userhost()}
@ -591,13 +591,13 @@ class RoomGame(object):
)
return False, False
else:
self._initGame(room_jid, user_nick)
self._init_game(room_jid, user_nick)
return True, False
def _createGame(self, room_jid_s, nicks=None, profile_key=C.PROF_KEY_NONE):
self.createGame(jid.JID(room_jid_s), nicks, profile_key)
def _create_game(self, room_jid_s, nicks=None, profile_key=C.PROF_KEY_NONE):
self.create_game(jid.JID(room_jid_s), nicks, profile_key)
def createGame(self, room_jid, nicks=None, profile_key=C.PROF_KEY_NONE):
def create_game(self, room_jid, nicks=None, profile_key=C.PROF_KEY_NONE):
"""Create a new game.
This can be called directly from a frontend and skips all the checks and invitation system,
@ -610,19 +610,19 @@ class RoomGame(object):
_("Creating %(game)s game in room %(room)s")
% {"game": self.name, "room": room_jid}
)
profile = self.host.memory.getProfileName(profile_key)
profile = self.host.memory.get_profile_name(profile_key)
if not profile:
log.error(_("profile %s is unknown") % profile_key)
return
(create, sync) = self._checkCreateGameAndInit(room_jid, profile)
(create, sync) = self._check_create_game_and_init(room_jid, profile)
if nicks is None:
nicks = []
if not create:
if sync:
self._updatePlayers(room_jid, nicks, True, profile)
self._update_players(room_jid, nicks, True, profile)
return
self.games[room_jid]["started"] = True
self._updatePlayers(room_jid, nicks, False, profile)
self._update_players(room_jid, nicks, False, profile)
if self.player_init:
# specific data to each player (score, private data)
self.games[room_jid].setdefault("players_data", {})
@ -632,16 +632,16 @@ class RoomGame(object):
self.player_init
)
def _playerReady(self, player_nick, referee_jid_s, profile_key=C.PROF_KEY_NONE):
self.playerReady(player_nick, jid.JID(referee_jid_s), profile_key)
def _player_ready(self, player_nick, referee_jid_s, profile_key=C.PROF_KEY_NONE):
self.player_ready(player_nick, jid.JID(referee_jid_s), profile_key)
def playerReady(self, player_nick, referee_jid, profile_key=C.PROF_KEY_NONE):
def player_ready(self, player_nick, referee_jid, profile_key=C.PROF_KEY_NONE):
"""Must be called when player is ready to start a new game
@param player: the player nick in the room
@param referee_jid (jid.JID): JID of the referee
"""
profile = self.host.memory.getProfileName(profile_key)
profile = self.host.memory.get_profile_name(profile_key)
if not profile:
log.error(_("profile %s is unknown") % profile_key)
return
@ -649,7 +649,7 @@ class RoomGame(object):
# TODO: we probably need to add the game and room names in the sent message
self.send(referee_jid, "player_ready", {"player": player_nick}, profile=profile)
def newRound(self, room_jid, data, profile):
def new_round(self, room_jid, data, profile):
"""Launch a new round (reinit the user data)
@param room_jid: room userhost
@ -681,7 +681,7 @@ class RoomGame(object):
for player in players:
players_data[player].update(copy.deepcopy(common_data))
def _createGameElt(self, to_jid):
def _create_game_elt(self, to_jid):
"""Create a generic domish Element for the game messages
@param to_jid: JID of the recipient
@ -694,7 +694,7 @@ class RoomGame(object):
elt.addElement(self.ns_tag)
return elt
def _createStartElement(self, players=None, name="started"):
def _create_start_element(self, players=None, name="started"):
"""Create a domish Element listing the game users
@param players: list of the players
@ -715,7 +715,7 @@ class RoomGame(object):
started_elt.addChild(player_elt)
return started_elt
def _sendElements(self, to_jid, data, profile=None):
def _send_elements(self, to_jid, data, profile=None):
""" TODO
@param to_jid: recipient JID
@ -729,8 +729,8 @@ class RoomGame(object):
@param profile: the profile from which the message is sent
@return: a Deferred instance
"""
client = self.host.getClient(profile)
msg = self._createGameElt(to_jid)
client = self.host.get_client(profile)
msg = self._create_game_elt(to_jid)
for elem, attrs, content in data:
if elem is not None:
if isinstance(elem, domish.Element):
@ -757,9 +757,9 @@ class RoomGame(object):
@param profile: the profile from which the message is sent
@return: a Deferred instance
"""
return self._sendElements(to_jid, [(elem, attrs, content)], profile)
return self._send_elements(to_jid, [(elem, attrs, content)], profile)
def getHandler(self, client):
def get_handler(self, client):
return RoomGameHandler(self)

View file

@ -76,13 +76,13 @@ class StaticBlog(object):
def __init__(self, host):
try: # TODO: remove this attribute when all blogs can be retrieved
self.domain = host.plugins["MISC-ACCOUNT"].getNewAccountDomain()
self.domain = host.plugins["MISC-ACCOUNT"].account_domain_new_get()
except KeyError:
self.domain = None
host.memory.updateParams(self.params)
# host.importMenu((D_("User"), D_("Public blog")), self._displayPublicBlog, security_limit=1, help_string=D_("Display public blog page"), type_=C.MENU_JID_CONTEXT)
host.memory.update_params(self.params)
# host.import_menu((D_("User"), D_("Public blog")), self._display_public_blog, security_limit=1, help_string=D_("Display public blog page"), type_=C.MENU_JID_CONTEXT)
def _displayPublicBlog(self, menu_data, profile):
def _display_public_blog(self, menu_data, profile):
"""Check if the blog can be displayed and answer the frontend.
@param menu_data: %(menu_data)s

View file

@ -49,7 +49,7 @@ PLUGIN_INFO = {
class Tarot(object):
def inheritFromRoomGame(self, host):
def inherit_from_room_game(self, host):
global RoomGame
RoomGame = host.plugins["ROOM-GAME"].__class__
self.__class__ = type(
@ -59,7 +59,7 @@ class Tarot(object):
def __init__(self, host):
log.info(_("Plugin Tarot initialization"))
self._sessions = memory.Sessions()
self.inheritFromRoomGame(host)
self.inherit_from_room_game(host)
RoomGame._init_(
self,
host,
@ -81,61 +81,61 @@ class Tarot(object):
_("Garde Sans"),
_("Garde Contre"),
]
host.bridge.addMethod(
"tarotGameLaunch",
host.bridge.add_method(
"tarot_game_launch",
".plugin",
in_sign="asss",
out_sign="",
method=self._prepareRoom,
method=self._prepare_room,
async_=True,
) # args: players, room_jid, profile
host.bridge.addMethod(
"tarotGameCreate",
host.bridge.add_method(
"tarot_game_create",
".plugin",
in_sign="sass",
out_sign="",
method=self._createGame,
method=self._create_game,
) # args: room_jid, players, profile
host.bridge.addMethod(
"tarotGameReady",
host.bridge.add_method(
"tarot_game_ready",
".plugin",
in_sign="sss",
out_sign="",
method=self._playerReady,
method=self._player_ready,
) # args: player, referee, profile
host.bridge.addMethod(
"tarotGamePlayCards",
host.bridge.add_method(
"tarot_game_play_cards",
".plugin",
in_sign="ssa(ss)s",
out_sign="",
method=self.play_cards,
) # args: player, referee, cards, profile
host.bridge.addSignal(
"tarotGamePlayers", ".plugin", signature="ssass"
host.bridge.add_signal(
"tarot_game_players", ".plugin", signature="ssass"
) # args: room_jid, referee, players, profile
host.bridge.addSignal(
"tarotGameStarted", ".plugin", signature="ssass"
host.bridge.add_signal(
"tarot_game_started", ".plugin", signature="ssass"
) # args: room_jid, referee, players, profile
host.bridge.addSignal(
"tarotGameNew", ".plugin", signature="sa(ss)s"
host.bridge.add_signal(
"tarot_game_new", ".plugin", signature="sa(ss)s"
) # args: room_jid, hand, profile
host.bridge.addSignal(
"tarotGameChooseContrat", ".plugin", signature="sss"
host.bridge.add_signal(
"tarot_game_choose_contrat", ".plugin", signature="sss"
) # args: room_jid, xml_data, profile
host.bridge.addSignal(
"tarotGameShowCards", ".plugin", signature="ssa(ss)a{ss}s"
host.bridge.add_signal(
"tarot_game_show_cards", ".plugin", signature="ssa(ss)a{ss}s"
) # args: room_jid, type ["chien", "poignée",...], cards, data[dict], profile
host.bridge.addSignal(
"tarotGameCardsPlayed", ".plugin", signature="ssa(ss)s"
host.bridge.add_signal(
"tarot_game_cards_played", ".plugin", signature="ssa(ss)s"
) # args: room_jid, player, type ["chien", "poignée",...], cards, data[dict], profile
host.bridge.addSignal(
"tarotGameYourTurn", ".plugin", signature="ss"
host.bridge.add_signal(
"tarot_game_your_turn", ".plugin", signature="ss"
) # args: room_jid, profile
host.bridge.addSignal(
"tarotGameScore", ".plugin", signature="ssasass"
host.bridge.add_signal(
"tarot_game_score", ".plugin", signature="ssasass"
) # args: room_jid, xml_data, winners (list of nicks), loosers (list of nicks), profile
host.bridge.addSignal(
"tarotGameInvalidCards", ".plugin", signature="ssa(ss)a(ss)s"
host.bridge.add_signal(
"tarot_game_invalid_cards", ".plugin", signature="ssa(ss)a(ss)s"
) # args: room_jid, game phase, played_cards, invalid_cards, profile
self.deck_ordered = []
for value in ["excuse"] + list(map(str, list(range(1, 22)))):
@ -143,10 +143,10 @@ class Tarot(object):
for suit in ["pique", "coeur", "carreau", "trefle"]:
for value in list(map(str, list(range(1, 11)))) + ["valet", "cavalier", "dame", "roi"]:
self.deck_ordered.append(TarotCard((suit, value)))
self.__choose_contrat_id = host.registerCallback(
self._contratChoosed, with_data=True
self.__choose_contrat_id = host.register_callback(
self._contrat_choosed, with_data=True
)
self.__score_id = host.registerCallback(self._scoreShowed, with_data=True)
self.__score_id = host.register_callback(self._score_showed, with_data=True)
def __card_list_to_xml(self, cards_list, elt_name):
"""Convert a card list to domish element"""
@ -519,13 +519,13 @@ class Tarot(object):
to_jid = jid.JID(room_jid.userhost() + "/" + next_player) # FIXME: gof:
self.send(to_jid, "your_turn", profile=profile)
def _contratChoosed(self, raw_data, profile):
def _contrat_choosed(self, raw_data, profile):
"""Will be called when the contrat is selected
@param raw_data: contains the choosed session id and the chosen contrat
@param profile_key: profile
"""
try:
session_data = self._sessions.profileGet(raw_data["session_id"], profile)
session_data = self._sessions.profile_get(raw_data["session_id"], profile)
except KeyError:
log.warning(_("session id doesn't exist, session has probably expired"))
# TODO: send error dialog
@ -533,8 +533,8 @@ class Tarot(object):
room_jid = session_data["room_jid"]
referee_jid = self.games[room_jid]["referee"]
player = self.host.plugins["XEP-0045"].getRoomNick(room_jid, profile)
data = xml_tools.XMLUIResult2DataFormResult(raw_data)
player = self.host.plugins["XEP-0045"].get_room_nick(room_jid, profile)
data = xml_tools.xmlui_result_2_data_form_result(raw_data)
contrat = data["contrat"]
log.debug(
_("contrat [%(contrat)s] choosed by %(profile)s")
@ -551,13 +551,13 @@ class Tarot(object):
del self._sessions[raw_data["session_id"]]
return d
def _scoreShowed(self, raw_data, profile):
def _score_showed(self, raw_data, profile):
"""Will be called when the player closes the score dialog
@param raw_data: nothing to retrieve from here but the session id
@param profile_key: profile
"""
try:
session_data = self._sessions.profileGet(raw_data["session_id"], profile)
session_data = self._sessions.profile_get(raw_data["session_id"], profile)
except KeyError:
log.warning(_("session id doesn't exist, session has probably expired"))
# TODO: send error dialog
@ -565,7 +565,7 @@ class Tarot(object):
room_jid_s = session_data["room_jid"].userhost()
# XXX: empty hand means to the frontend "reset the display"...
self.host.bridge.tarotGameNew(room_jid_s, [], profile)
self.host.bridge.tarot_game_new(room_jid_s, [], profile)
del self._sessions[raw_data["session_id"]]
return defer.succeed({})
@ -576,7 +576,7 @@ class Tarot(object):
@cards: cards played (list of tuples)
@profile_key: profile
"""
profile = self.host.memory.getProfileName(profile_key)
profile = self.host.memory.get_profile_name(profile_key)
if not profile:
log.error(_("profile %s is unknown") % profile_key)
return
@ -587,7 +587,7 @@ class Tarot(object):
elem = self.__card_list_to_xml(TarotCard.from_tuples(cards), "cards_played")
self.send(jid.JID(referee), elem, {"player": player}, profile=profile)
def newRound(self, room_jid, profile):
def new_round(self, room_jid, profile):
game_data = self.games[room_jid]
players = game_data["players"]
game_data["first_player"] = None # first player for the current trick
@ -613,7 +613,7 @@ class Tarot(object):
for player in players:
msg_elts[player] = self.__card_list_to_xml(hand[player], "hand")
RoomGame.newRound(self, room_jid, (common_data, msg_elts), profile)
RoomGame.new_round(self, room_jid, (common_data, msg_elts), profile)
pl_idx = game_data["current_player"] = (game_data["init_player"] + 1) % len(
players
@ -626,14 +626,14 @@ class Tarot(object):
"""
@param mess_elt: instance of twisted.words.xish.domish.Element
"""
client = self.host.getClient(profile)
client = self.host.get_client(profile)
from_jid = jid.JID(mess_elt["from"])
room_jid = jid.JID(from_jid.userhost())
nick = self.host.plugins["XEP-0045"].getRoomNick(client, room_jid)
nick = self.host.plugins["XEP-0045"].get_room_nick(client, room_jid)
game_elt = mess_elt.firstChildElement()
game_data = self.games[room_jid]
is_player = self.isPlayer(room_jid, nick)
is_player = self.is_player(room_jid, nick)
if "players_data" in game_data:
players_data = game_data["players_data"]
@ -649,9 +649,9 @@ class Tarot(object):
for player in elt.elements():
players.append(str(player))
signal = (
self.host.bridge.tarotGameStarted
self.host.bridge.tarot_game_started
if elt.name == "started"
else self.host.bridge.tarotGamePlayers
else self.host.bridge.tarot_game_players
)
signal(room_jid.userhost(), from_jid.full(), players, profile)
@ -667,21 +667,21 @@ class Tarot(object):
if (
list(status.values()).count("ready") == nb_players
): # everybody is ready, we can start the game
self.newRound(room_jid, profile)
self.new_round(room_jid, profile)
elif elt.name == "hand": # a new hand has been received
self.host.bridge.tarotGameNew(
self.host.bridge.tarot_game_new(
room_jid.userhost(), self.__xml_to_list(elt), profile
)
elif elt.name == "contrat": # it's time to choose contrat
form = data_form.Form.fromElement(elt.firstChildElement())
session_id, session_data = self._sessions.newSession(profile=profile)
session_id, session_data = self._sessions.new_session(profile=profile)
session_data["room_jid"] = room_jid
xml_data = xml_tools.dataForm2XMLUI(
xml_data = xml_tools.data_form_2_xmlui(
form, self.__choose_contrat_id, session_id
).toXml()
self.host.bridge.tarotGameChooseContrat(
self.host.bridge.tarot_game_choose_contrat(
room_jid.userhost(), xml_data, profile
)
@ -752,7 +752,7 @@ class Tarot(object):
data = {"attaquant": elt["attaquant"]}
game_data["stage"] = "ecart"
game_data["attaquant"] = elt["attaquant"]
self.host.bridge.tarotGameShowCards(
self.host.bridge.tarot_game_show_cards(
room_jid.userhost(), "chien", self.__xml_to_list(elt), data, profile
)
@ -790,7 +790,7 @@ class Tarot(object):
cards = TarotCard.from_tuples(self.__xml_to_list(elt))
if mess_elt["type"] == "groupchat":
self.host.bridge.tarotGameCardsPlayed(
self.host.bridge.tarot_game_cards_played(
room_jid.userhost(),
elt["player"],
self.__xml_to_list(elt),
@ -858,7 +858,7 @@ class Tarot(object):
self.send(to_jid, "your_turn", profile=profile)
elif elt.name == "your_turn":
self.host.bridge.tarotGameYourTurn(room_jid.userhost(), profile)
self.host.bridge.tarot_game_your_turn(room_jid.userhost(), profile)
elif elt.name == "score":
form_elt = next(elt.elements(name="x", uri="jabber:x:data"))
@ -869,12 +869,12 @@ class Tarot(object):
for looser in elt.elements(name="looser", uri=NS_CG):
loosers.append(str(looser))
form = data_form.Form.fromElement(form_elt)
session_id, session_data = self._sessions.newSession(profile=profile)
session_id, session_data = self._sessions.new_session(profile=profile)
session_data["room_jid"] = room_jid
xml_data = xml_tools.dataForm2XMLUI(
xml_data = xml_tools.data_form_2_xmlui(
form, self.__score_id, session_id
).toXml()
self.host.bridge.tarotGameScore(
self.host.bridge.tarot_game_score(
room_jid.userhost(), xml_data, winners, loosers, profile
)
elif elt.name == "error":
@ -885,7 +885,7 @@ class Tarot(object):
invalid_cards = self.__xml_to_list(
next(elt.elements(name="invalid", uri=NS_CG))
)
self.host.bridge.tarotGameInvalidCards(
self.host.bridge.tarot_game_invalid_cards(
room_jid.userhost(),
elt["phase"],
played_cards,
@ -897,5 +897,5 @@ class Tarot(object):
else:
log.error(_("Unmanaged card game element: %s") % elt.name)
def getSyncDataForPlayer(self, room_jid, nick):
def get_sync_data_for_player(self, room_jid, nick):
return []

View file

@ -66,12 +66,12 @@ class TextCommands(object):
log.info(_("Text commands initialization"))
self.host = host
# this is internal command, so we set high priority
host.trigger.add("sendMessage", self.sendMessageTrigger, priority=1000000)
host.trigger.add("sendMessage", self.send_message_trigger, priority=1000000)
self._commands = {}
self._whois = []
self.registerTextCommands(self)
self.register_text_commands(self)
def _parseDocString(self, cmd, cmd_name):
def _parse_doc_string(self, cmd, cmd_name):
"""Parse a docstring to get text command data
@param cmd: function or method callback for the command,
@ -150,7 +150,7 @@ class TextCommands(object):
return data
def registerTextCommands(self, instance):
def register_text_commands(self, instance):
""" Add a text command
@param instance: instance of a class containing text commands
@ -176,10 +176,10 @@ class TextCommands(object):
)
cmd_name = new_name
self._commands[cmd_name] = cmd_data = {"callback": cmd}
cmd_data.update(self._parseDocString(cmd, cmd_name))
cmd_data.update(self._parse_doc_string(cmd, cmd_name))
log.info(_("Registered text command [%s]") % cmd_name)
def addWhoIsCb(self, callback, priority=0):
def add_who_is_cb(self, callback, priority=0):
"""Add a callback which give information to the /whois command
@param callback: a callback which will be called with the following arguments
@ -193,14 +193,14 @@ class TextCommands(object):
self._whois.append((priority, callback))
self._whois.sort(key=lambda item: item[0], reverse=True)
def sendMessageTrigger(
def send_message_trigger(
self, client, mess_data, pre_xml_treatments, post_xml_treatments
):
"""Install SendMessage command hook """
pre_xml_treatments.addCallback(self._sendMessageCmdHook, client)
pre_xml_treatments.addCallback(self._send_message_cmd_hook, client)
return True
def _sendMessageCmdHook(self, mess_data, client):
def _send_message_cmd_hook(self, mess_data, client):
""" Check text commands in message, and react consequently
msg starting with / are potential command. If a command is found, it is executed,
@ -239,7 +239,7 @@ class TextCommands(object):
d = None
command = msg[1:].partition(" ")[0].lower().strip()
if not command.isidentifier():
self.feedBack(
self.feed_back(
client,
_("Invalid command /%s. ") % command + self.HELP_SUGGESTION,
mess_data,
@ -247,7 +247,7 @@ class TextCommands(object):
raise failure.Failure(exceptions.CancelError())
# looks like an actual command, we try to call the corresponding method
def retHandling(ret):
def ret_handling(ret):
""" Handle command return value:
if ret is True, normally send message (possibly modified by command)
else, abord message sending
@ -258,12 +258,12 @@ class TextCommands(object):
log.debug("text command detected ({})".format(command))
raise failure.Failure(exceptions.CancelError())
def genericErrback(failure):
def generic_errback(failure):
try:
msg = "with condition {}".format(failure.value.condition)
except AttributeError:
msg = "with error {}".format(failure.value)
self.feedBack(client, "Command failed {}".format(msg), mess_data)
self.feed_back(client, "Command failed {}".format(msg), mess_data)
return False
mess_data["unparsed"] = msg[
@ -272,7 +272,7 @@ class TextCommands(object):
try:
cmd_data = self._commands[command]
except KeyError:
self.feedBack(
self.feed_back(
client,
_("Unknown command /%s. ") % command + self.HELP_SUGGESTION,
mess_data,
@ -280,7 +280,7 @@ class TextCommands(object):
log.debug("text command help message")
raise failure.Failure(exceptions.CancelError())
else:
if not self._contextValid(mess_data, cmd_data):
if not self._context_valid(mess_data, cmd_data):
# The command is not launched in the right context, we throw a message with help instructions
context_txt = (
_("group discussions")
@ -290,23 +290,23 @@ class TextCommands(object):
feedback = _("/{command} command only applies in {context}.").format(
command=command, context=context_txt
)
self.feedBack(
self.feed_back(
client, "{} {}".format(feedback, self.HELP_SUGGESTION), mess_data
)
log.debug("text command invalid message")
raise failure.Failure(exceptions.CancelError())
else:
d = utils.asDeferred(cmd_data["callback"], client, mess_data)
d.addErrback(genericErrback)
d.addCallback(retHandling)
d = utils.as_deferred(cmd_data["callback"], client, mess_data)
d.addErrback(generic_errback)
d.addCallback(ret_handling)
return d
def _contextValid(self, mess_data, cmd_data):
def _context_valid(self, mess_data, cmd_data):
"""Tell if a command can be used in the given context
@param mess_data(dict): message data as given in sendMessage trigger
@param cmd_data(dict): command data as returned by self._parseDocString
@param cmd_data(dict): command data as returned by self._parse_doc_string
@return (bool): True if command can be used in this context
"""
if (cmd_data["type"] == "group" and mess_data["type"] != "groupchat") or (
@ -315,7 +315,7 @@ class TextCommands(object):
return False
return True
def getRoomJID(self, arg, service_jid):
def get_room_jid(self, arg, service_jid):
"""Return a room jid with a shortcut
@param arg: argument: can be a full room jid (e.g.: sat@chat.jabberfr.org)
@ -329,7 +329,7 @@ class TextCommands(object):
return jid.JID(arg + service_jid)
return jid.JID(f"{arg}@{service_jid}")
def feedBack(self, client, message, mess_data, info_type=FEEDBACK_INFO_TYPE):
def feed_back(self, client, message, mess_data, info_type=FEEDBACK_INFO_TYPE):
"""Give a message back to the user"""
if mess_data["type"] == "groupchat":
to_ = mess_data["to"].userhostJID()
@ -342,7 +342,7 @@ class TextCommands(object):
mess_data["type"] = C.MESS_TYPE_INFO
mess_data["message"] = {"": message}
mess_data["extra"]["info_type"] = info_type
client.messageSendToBridge(mess_data)
client.message_send_to_bridge(mess_data)
def cmd_whois(self, client, mess_data):
"""show informations on entity
@ -358,7 +358,7 @@ class TextCommands(object):
if mess_data["type"] == "groupchat":
room = mess_data["to"].userhostJID()
try:
if self.host.plugins["XEP-0045"].isNickInRoom(client, room, entity):
if self.host.plugins["XEP-0045"].is_nick_in_room(client, room, entity):
entity = "%s/%s" % (room, entity)
except KeyError:
log.warning("plugin XEP-0045 is not present")
@ -371,11 +371,11 @@ class TextCommands(object):
if not target_jid.user or not target_jid.host:
raise jid.InvalidFormat
except (RuntimeError, jid.InvalidFormat, AttributeError):
self.feedBack(client, _("Invalid jid, can't whois"), mess_data)
self.feed_back(client, _("Invalid jid, can't whois"), mess_data)
return False
if not target_jid.resource:
target_jid.resource = self.host.memory.getMainResource(client, target_jid)
target_jid.resource = self.host.memory.main_resource_get(client, target_jid)
whois_msg = [_("whois for %(jid)s") % {"jid": target_jid}]
@ -385,14 +385,14 @@ class TextCommands(object):
lambda __: callback(client, whois_msg, mess_data, target_jid)
)
def feedBack(__):
self.feedBack(client, "\n".join(whois_msg), mess_data)
def feed_back(__):
self.feed_back(client, "\n".join(whois_msg), mess_data)
return False
d.addCallback(feedBack)
d.addCallback(feed_back)
return d
def _getArgsHelp(self, cmd_data):
def _get_args_help(self, cmd_data):
"""Return help string for args of cmd_name, according to docstring data
@param cmd_data: command data
@ -420,7 +420,7 @@ class TextCommands(object):
def cmd_whoami(self, client, mess_data):
"""give your own jid"""
self.feedBack(client, client.jid.full(), mess_data)
self.feed_back(client, client.jid.full(), mess_data)
def cmd_help(self, client, mess_data):
"""show help on available commands
@ -432,7 +432,7 @@ class TextCommands(object):
if cmd_name and cmd_name[0] == "/":
cmd_name = cmd_name[1:]
if cmd_name and cmd_name not in self._commands:
self.feedBack(
self.feed_back(
client, _("Invalid command name [{}]\n".format(cmd_name)), mess_data
)
cmd_name = ""
@ -443,7 +443,7 @@ class TextCommands(object):
for command in sorted(self._commands):
cmd_data = self._commands[command]
if not self._contextValid(mess_data, cmd_data):
if not self._context_valid(mess_data, cmd_data):
continue
spaces = (longuest - len(command)) * " "
help_cmds.append(
@ -464,8 +464,8 @@ class TextCommands(object):
short_help=cmd_data["doc_short_help"],
syntax=_(" " * 4 + "syntax: {}\n").format(syntax) if syntax else "",
args_help="\n".join(
[" " * 8 + "{}".format(line) for line in self._getArgsHelp(cmd_data)]
[" " * 8 + "{}".format(line) for line in self._get_args_help(cmd_data)]
),
)
self.feedBack(client, help_mess, mess_data)
self.feed_back(client, help_mess, mess_data)

View file

@ -196,7 +196,7 @@ class TextSyntaxes(object):
"syntaxes": self.syntaxes,
}
self.addSyntax(
self.add_syntax(
self.SYNTAX_XHTML,
lambda xhtml: defer.succeed(xhtml),
lambda xhtml: defer.succeed(xhtml),
@ -204,10 +204,10 @@ class TextSyntaxes(object):
)
# TODO: text => XHTML should add <a/> to url like in frontends
# it's probably best to move sat_frontends.tools.strings to sat.tools.common or similar
self.addSyntax(
self.add_syntax(
self.SYNTAX_TEXT,
lambda text: escape(text),
lambda xhtml: self._removeMarkups(xhtml),
lambda xhtml: self._remove_markups(xhtml),
[TextSyntaxes.OPT_HIDDEN],
)
try:
@ -217,7 +217,7 @@ class TextSyntaxes(object):
# XXX: we disable raw HTML parsing by default, to avoid parsing error
# when the user is not aware of markdown and HTML
class EscapeHTML(Extension):
def extendMarkdown(self, md):
def extend_markdown(self, md):
md.preprocessors.deregister('html_block')
md.inlinePatterns.deregister('html')
@ -226,7 +226,7 @@ class TextSyntaxes(object):
h.body_width = 0 # do not truncate the lines, it breaks the long URLs
return h.handle(html)
self.addSyntax(
self.add_syntax(
self.SYNTAX_MARKDOWN,
partial(markdown.markdown,
extensions=[
@ -251,22 +251,22 @@ class TextSyntaxes(object):
"You can download/install them from https://pythonhosted.org/Markdown/ "
"and https://github.com/Alir3z4/html2text/"
)
host.bridge.addMethod(
"syntaxConvert",
host.bridge.add_method(
"syntax_convert",
".plugin",
in_sign="sssbs",
out_sign="s",
async_=True,
method=self.convert,
)
host.bridge.addMethod(
"syntaxGet", ".plugin", in_sign="s", out_sign="s", method=self.getSyntax
host.bridge.add_method(
"syntax_get", ".plugin", in_sign="s", out_sign="s", method=self.get_syntax
)
if xml_tools.cleanXHTML is None:
if xml_tools.clean_xhtml is None:
log.debug("Installing cleaning method")
xml_tools.cleanXHTML = self.cleanXHTML
xml_tools.clean_xhtml = self.clean_xhtml
def _updateParamOptions(self):
def _update_param_options(self):
data_synt = self.syntaxes
default_synt = TextSyntaxes.default_syntax
syntaxes = []
@ -284,23 +284,23 @@ class TextSyntaxes(object):
options.append('<option value="%s" %s/>' % (syntax, selected))
self.params_data["options"] = "\n".join(options)
self.host.memory.updateParams(self.params % self.params_data)
self.host.memory.update_params(self.params % self.params_data)
def getCurrentSyntax(self, profile):
def get_current_syntax(self, profile):
""" Return the selected syntax for the given profile
@param profile: %(doc_profile)s
@return: profile selected syntax
"""
return self.host.memory.getParamA(NAME, CATEGORY, profile_key=profile)
return self.host.memory.param_get_a(NAME, CATEGORY, profile_key=profile)
def _logError(self, failure, action="converting syntax"):
def _log_error(self, failure, action="converting syntax"):
log.error(
"Error while {action}: {failure}".format(action=action, failure=failure)
)
return failure
def cleanStyle(self, styles_raw: str) -> str:
def clean_style(self, styles_raw: str) -> str:
""""Clean unsafe CSS styles
Remove styles not in the whitelist, or where the value doesn't match the regex
@ -327,7 +327,7 @@ class TextSyntaxes(object):
["%s: %s" % (key_, value_) for key_, value_ in cleaned_styles]
)
def cleanClasses(self, classes_raw: str) -> str:
def clean_classes(self, classes_raw: str) -> str:
"""Remove any non whitelisted class
@param classes_raw: classes set on an element
@ -335,7 +335,7 @@ class TextSyntaxes(object):
"""
return " ".join(SAFE_CLASSES.intersection(classes_raw.split()))
def cleanXHTML(self, xhtml):
def clean_xhtml(self, xhtml):
"""Clean XHTML text by removing potentially dangerous/malicious parts
@param xhtml(unicode, lxml.etree._Element): raw HTML/XHTML text to clean
@ -360,9 +360,9 @@ class TextSyntaxes(object):
)
xhtml_elt = cleaner.clean_html(xhtml_elt)
for elt in xhtml_elt.xpath("//*[@style]"):
elt.set("style", self.cleanStyle(elt.get("style")))
elt.set("style", self.clean_style(elt.get("style")))
for elt in xhtml_elt.xpath("//*[@class]"):
elt.set("class", self.cleanClasses(elt.get("class")))
elt.set("class", self.clean_classes(elt.get("class")))
# we remove self-closing elements for non-void elements
for element in xhtml_elt.iter(tag=etree.Element):
if not element.text:
@ -389,11 +389,11 @@ class TextSyntaxes(object):
# TODO: a way for parser to return parsing errors/warnings
if syntax_from == _SYNTAX_CURRENT:
syntax_from = self.getCurrentSyntax(profile)
syntax_from = self.get_current_syntax(profile)
else:
syntax_from = syntax_from.lower().strip()
if syntax_to == _SYNTAX_CURRENT:
syntax_to = self.getCurrentSyntax(profile)
syntax_to = self.get_current_syntax(profile)
else:
syntax_to = syntax_to.lower().strip()
syntaxes = self.syntaxes
@ -411,7 +411,7 @@ class TextSyntaxes(object):
# TODO: keep only body element and change it to a div here ?
if safe:
d.addCallback(self.cleanXHTML)
d.addCallback(self.clean_xhtml)
if TextSyntaxes.OPT_NO_THREAD in syntaxes[syntax_to]["flags"]:
d.addCallback(syntaxes[syntax_to]["from"])
@ -422,7 +422,7 @@ class TextSyntaxes(object):
d.addCallback(lambda text: text.rstrip())
return d
def addSyntax(self, name, to_xhtml_cb, from_xhtml_cb, flags=None):
def add_syntax(self, name, to_xhtml_cb, from_xhtml_cb, flags=None):
"""Add a new syntax to the manager
@param name: unique name of the syntax
@ -456,9 +456,9 @@ class TextSyntaxes(object):
if TextSyntaxes.OPT_DEFAULT in flags:
TextSyntaxes.default_syntax = key
self._updateParamOptions()
self._update_param_options()
def getSyntax(self, name):
def get_syntax(self, name):
"""get syntax key corresponding to a name
@raise exceptions.NotFound: syntax doesn't exist
@ -468,7 +468,7 @@ class TextSyntaxes(object):
return key
raise exceptions.NotFound
def _removeMarkups(self, xhtml):
def _remove_markups(self, xhtml):
"""Remove XHTML markups from the given string.
@param xhtml: the XHTML string to be cleaned

View file

@ -57,28 +57,28 @@ class UploadPlugin(object):
def __init__(self, host):
log.info(_("plugin Upload initialization"))
self.host = host
host.bridge.addMethod(
"fileUpload",
host.bridge.add_method(
"file_upload",
".plugin",
in_sign="sssss",
out_sign="a{ss}",
method=self._fileUpload,
method=self._file_upload,
async_=True,
)
self._upload_callbacks = []
def _fileUpload(
def _file_upload(
self, filepath, filename, upload_jid_s="", options='', profile=C.PROF_KEY_NONE
):
client = self.host.getClient(profile)
client = self.host.get_client(profile)
upload_jid = jid.JID(upload_jid_s) if upload_jid_s else None
options = data_format.deserialise(options)
return defer.ensureDeferred(self.fileUpload(
return defer.ensureDeferred(self.file_upload(
client, filepath, filename or None, upload_jid, options
))
async def fileUpload(self, client, filepath, filename, upload_jid, options):
async def file_upload(self, client, filepath, filename, upload_jid, options):
"""Send a file using best available method
parameters are the same as for [upload]
@ -159,7 +159,7 @@ class UploadPlugin(object):
components)
exceptions.NotFound must be raised if no entity has been found
@param upload_cb(callable): method to upload a file
must have the same signature as [fileUpload]
must have the same signature as [file_upload]
must return a tuple with progress_id and a Deferred which fire download URL
when upload is finished
@param priority(int): pririoty of this method, the higher available will be used

View file

@ -51,7 +51,7 @@ class URIFinder(object):
def __init__(self, host):
log.info(_("URI finder plugin initialization"))
self.host = host
host.bridge.addMethod("URIFind", ".plugin",
host.bridge.add_method("uri_find", ".plugin",
in_sign='sas', out_sign='a{sa{ss}}',
method=self.find,
async_=True)

View file

@ -61,25 +61,25 @@ class Watched(object):
def __init__(self, host):
log.info(_("Watched initialisation"))
self.host = host
host.memory.updateParams(self.params)
host.trigger.add("presence_received", self._presenceReceivedTrigger)
host.memory.update_params(self.params)
host.trigger.add("presence_received", self._presence_received_trigger)
def _presenceReceivedTrigger(self, client, entity, show, priority, statuses):
def _presence_received_trigger(self, client, entity, show, priority, statuses):
if show == C.PRESENCE_UNAVAILABLE:
return True
# we check that the previous presence was unavailable (no notification else)
try:
old_show = self.host.memory.getEntityDatum(
old_show = self.host.memory.get_entity_datum(
client, entity, "presence").show
except (KeyError, exceptions.UnknownEntityError):
old_show = C.PRESENCE_UNAVAILABLE
if old_show == C.PRESENCE_UNAVAILABLE:
watched = self.host.memory.getParamA(
watched = self.host.memory.param_get_a(
NAME, CATEGORY, profile_key=client.profile)
if entity in watched or entity.userhostJID() in watched:
self.host.actionNew(
self.host.action_new(
{
"xmlui": xml_tools.note(
_(NOTIF).format(entity=entity.full())

View file

@ -74,12 +74,12 @@ class Welcome(object):
def __init__(self, host):
log.info(_("plugin Welcome initialization"))
self.host = host
host.memory.updateParams(PARAMS)
host.memory.update_params(PARAMS)
def profileConnected(self, client):
def profile_connected(self, client):
# XXX: if you wan to try first_start again, you'll have to remove manually
# the welcome value from your profile params in sat.db
welcome = self.host.memory.params.getParamA(
welcome = self.host.memory.params.param_get_a(
WELCOME_PARAM_NAME,
WELCOME_PARAM_CATEGORY,
use_default=False,
@ -93,8 +93,8 @@ class Welcome(object):
if welcome:
xmlui = xml_tools.note(WELCOME_MSG, WELCOME_MSG_TITLE)
self.host.actionNew({"xmlui": xmlui.toXml()}, profile=client.profile)
self.host.memory.setParam(
self.host.action_new({"xmlui": xmlui.toXml()}, profile=client.profile)
self.host.memory.param_set(
WELCOME_PARAM_NAME,
C.BOOL_FALSE,
WELCOME_PARAM_CATEGORY,

View file

@ -54,29 +54,29 @@ class XmlLog(object):
def __init__(self, host):
log.info(_("Plugin XML Log initialization"))
self.host = host
host.memory.updateParams(self.params)
host.bridge.addSignal(
"xmlLog", ".plugin", signature="sss"
host.memory.update_params(self.params)
host.bridge.add_signal(
"xml_log", ".plugin", signature="sss"
) # args: direction("IN" or "OUT"), xml_data, profile
host.trigger.add("stream_hooks", self.addHooks)
host.trigger.add("stream_hooks", self.add_hooks)
def addHooks(self, client, receive_hooks, send_hooks):
self.do_log = self.host.memory.getParamA("Xml log", "Debug")
def add_hooks(self, client, receive_hooks, send_hooks):
self.do_log = self.host.memory.param_get_a("Xml log", "Debug")
if self.do_log:
receive_hooks.append(partial(self.onReceive, client=client))
send_hooks.append(partial(self.onSend, client=client))
receive_hooks.append(partial(self.on_receive, client=client))
send_hooks.append(partial(self.on_send, client=client))
log.info(_("XML log activated"))
return True
def onReceive(self, element, client):
self.host.bridge.xmlLog("IN", element.toXml(), client.profile)
def on_receive(self, element, client):
self.host.bridge.xml_log("IN", element.toXml(), client.profile)
def onSend(self, obj, client):
def on_send(self, obj, client):
if isinstance(obj, str):
xml_log = obj
elif isinstance(obj, domish.Element):
xml_log = obj.toXml()
else:
log.error(_("INTERNAL ERROR: Unmanaged XML type"))
self.host.bridge.xmlLog("OUT", xml_log, client.profile)
self.host.bridge.xml_log("OUT", xml_log, client.profile)

View file

@ -65,7 +65,7 @@ class PubsubCache:
def __init__(self, host):
log.info(_("PubSub Cache initialization"))
strategy = host.memory.getConfig(None, "pubsub_cache_strategy")
strategy = host.memory.config_get(None, "pubsub_cache_strategy")
if strategy == "no_cache":
log.info(
_(
@ -81,47 +81,47 @@ class PubsubCache:
self.analysers = {}
# map for caching in progress (node, service) => Deferred
self.in_progress = {}
self.host.trigger.add("XEP-0060_getItems", self._getItemsTrigger)
self._p.addManagedNode(
self.host.trigger.add("XEP-0060_getItems", self._get_items_trigger)
self._p.add_managed_node(
"",
items_cb=self.onItemsEvent,
delete_cb=self.onDeleteEvent,
purge_db=self.onPurgeEvent,
items_cb=self.on_items_event,
delete_cb=self.on_delete_event,
purge_db=self.on_purge_event,
)
host.bridge.addMethod(
"psCacheGet",
host.bridge.add_method(
"ps_cache_get",
".plugin",
in_sign="ssiassss",
out_sign="s",
method=self._getItemsFromCache,
method=self._get_items_from_cache,
async_=True,
)
host.bridge.addMethod(
"psCacheSync",
host.bridge.add_method(
"ps_cache_sync",
".plugin",
"sss",
out_sign="",
method=self._synchronise,
async_=True,
)
host.bridge.addMethod(
"psCachePurge",
host.bridge.add_method(
"ps_cache_purge",
".plugin",
"s",
out_sign="",
method=self._purge,
async_=True,
)
host.bridge.addMethod(
"psCacheReset",
host.bridge.add_method(
"ps_cache_reset",
".plugin",
"",
out_sign="",
method=self._reset,
async_=True,
)
host.bridge.addMethod(
"psCacheSearch",
host.bridge.add_method(
"ps_cache_search",
".plugin",
"s",
out_sign="s",
@ -129,7 +129,7 @@ class PubsubCache:
async_=True,
)
def registerAnalyser(self, analyser: dict) -> None:
def register_analyser(self, analyser: dict) -> None:
"""Register a new pubsub node analyser
@param analyser: An analyser is a dictionary which may have the following keys
@ -203,7 +203,7 @@ class PubsubCache:
)
self.analysers[name] = analyser
async def cacheItems(
async def cache_items(
self,
client: SatXMPPEntity,
pubsub_node: PubsubNode,
@ -216,7 +216,7 @@ class PubsubCache:
if parser is not None:
parsed_items = [
await utils.asDeferred(
await utils.as_deferred(
parser,
client,
item,
@ -228,16 +228,16 @@ class PubsubCache:
else:
parsed_items = None
await self.host.memory.storage.cachePubsubItems(
await self.host.memory.storage.cache_pubsub_items(
client, pubsub_node, items, parsed_items
)
async def _cacheNode(
async def _cache_node(
self,
client: SatXMPPEntity,
pubsub_node: PubsubNode
) -> None:
await self.host.memory.storage.updatePubsubNodeSyncState(
await self.host.memory.storage.update_pubsub_node_sync_state(
pubsub_node, SyncState.IN_PROGRESS
)
service, node = pubsub_node.service, pubsub_node.name
@ -274,7 +274,7 @@ class PubsubCache:
)
try:
await self.host.checkFeatures(
await self.host.check_features(
client, [rsm.NS_RSM, self._p.DISCO_RSM], pubsub_node.service
)
except error.StanzaError as e:
@ -286,7 +286,7 @@ class PubsubCache:
items, __ = await client.pubsub_client.items(
pubsub_node.service, pubsub_node.name, maxItems=20
)
await self.cacheItems(
await self.cache_items(
client, pubsub_node, items
)
else:
@ -299,7 +299,7 @@ class PubsubCache:
items, __ = await client.pubsub_client.items(
pubsub_node.service, pubsub_node.name, maxItems=20
)
await self.cacheItems(
await self.cache_items(
client, pubsub_node, items
)
else:
@ -310,7 +310,7 @@ class PubsubCache:
items, rsm_response = await client.pubsub_client.items(
service, node, rsm_request=rsm_request
)
await self.cacheItems(
await self.cache_items(
client, pubsub_node, items
)
for item in items:
@ -334,11 +334,11 @@ class PubsubCache:
)
rsm_request = None
break
rsm_request = rsm_p.getNextRequest(rsm_request, rsm_response)
rsm_request = rsm_p.get_next_request(rsm_request, rsm_response)
if rsm_request is None:
break
await self.host.memory.storage.updatePubsubNodeSyncState(
await self.host.memory.storage.update_pubsub_node_sync_state(
pubsub_node, SyncState.COMPLETED
)
except Exception as e:
@ -347,27 +347,27 @@ class PubsubCache:
log.error(
f"Can't cache node {node!r} at {service} for {client.profile}: {e}\n{tb}"
)
await self.host.memory.storage.updatePubsubNodeSyncState(
await self.host.memory.storage.update_pubsub_node_sync_state(
pubsub_node, SyncState.ERROR
)
await self.host.memory.storage.deletePubsubItems(pubsub_node)
await self.host.memory.storage.delete_pubsub_items(pubsub_node)
raise e
def _cacheNodeClean(self, __, pubsub_node):
def _cache_node_clean(self, __, pubsub_node):
del self.in_progress[(pubsub_node.service, pubsub_node.name)]
def cacheNode(
def cache_node(
self,
client: SatXMPPEntity,
pubsub_node: PubsubNode
) -> None:
"""Launch node caching as a background task"""
d = defer.ensureDeferred(self._cacheNode(client, pubsub_node))
d.addBoth(self._cacheNodeClean, pubsub_node=pubsub_node)
d = defer.ensureDeferred(self._cache_node(client, pubsub_node))
d.addBoth(self._cache_node_clean, pubsub_node=pubsub_node)
self.in_progress[(pubsub_node.service, pubsub_node.name)] = d
return d
async def analyseNode(
async def analyse_node(
self,
client: SatXMPPEntity,
service: jid.JID,
@ -451,26 +451,26 @@ class PubsubCache:
except KeyError:
pass
else:
await utils.asDeferred(match_cb, client, analyse)
await utils.as_deferred(match_cb, client, analyse)
return analyse
def _getItemsFromCache(
def _get_items_from_cache(
self, service="", node="", max_items=10, item_ids=None, sub_id=None,
extra="", profile_key=C.PROF_KEY_NONE
):
d = defer.ensureDeferred(self._aGetItemsFromCache(
d = defer.ensureDeferred(self._a_get_items_from_cache(
service, node, max_items, item_ids, sub_id, extra, profile_key
))
d.addCallback(self._p.transItemsData)
d.addCallback(self._p.serialiseItems)
d.addCallback(self._p.trans_items_data)
d.addCallback(self._p.serialise_items)
return d
async def _aGetItemsFromCache(
async def _a_get_items_from_cache(
self, service, node, max_items, item_ids, sub_id, extra, profile_key
):
client = self.host.getClient(profile_key)
client = self.host.get_client(profile_key)
service = jid.JID(service) if service else client.jid.userhostJID()
pubsub_node = await self.host.memory.storage.getPubsubNode(
pubsub_node = await self.host.memory.storage.get_pubsub_node(
client, service, node
)
if pubsub_node is None:
@ -478,8 +478,8 @@ class PubsubCache:
f"{node!r} at {service} doesn't exist in cache for {client.profile!r}"
)
max_items = None if max_items == C.NO_LIMIT else max_items
extra = self._p.parseExtra(data_format.deserialise(extra))
items, metadata = await self.getItemsFromCache(
extra = self._p.parse_extra(data_format.deserialise(extra))
items, metadata = await self.get_items_from_cache(
client,
pubsub_node,
max_items,
@ -490,7 +490,7 @@ class PubsubCache:
)
return [i.data for i in items], metadata
async def getItemsFromCache(
async def get_items_from_cache(
self,
client: SatXMPPEntity,
node: PubsubNode,
@ -507,7 +507,7 @@ class PubsubCache:
raise NotImplementedError("MAM queries are not supported yet")
if max_items is None and rsm_request is None:
max_items = 20
pubsub_items, metadata = await self.host.memory.storage.getItems(
pubsub_items, metadata = await self.host.memory.storage.get_items(
node, max_items=max_items, item_ids=item_ids or None,
order_by=extra.get(C.KEY_ORDER_BY)
)
@ -520,7 +520,7 @@ class PubsubCache:
raise exceptions.InternalError(
"Pubsub max items and item IDs must not be used at the same time"
)
pubsub_items, metadata = await self.host.memory.storage.getItems(
pubsub_items, metadata = await self.host.memory.storage.get_items(
node, max_items=max_items, order_by=extra.get(C.KEY_ORDER_BY)
)
else:
@ -530,7 +530,7 @@ class PubsubCache:
desc = True
else:
before = rsm_request.before
pubsub_items, metadata = await self.host.memory.storage.getItems(
pubsub_items, metadata = await self.host.memory.storage.get_items(
node, max_items=rsm_request.max, before=before, after=rsm_request.after,
from_index=rsm_request.index, order_by=extra.get(C.KEY_ORDER_BY),
desc=desc, force_rsm=True,
@ -538,8 +538,8 @@ class PubsubCache:
return pubsub_items, metadata
async def onItemsEvent(self, client, event):
node = await self.host.memory.storage.getPubsubNode(
async def on_items_event(self, client, event):
node = await self.host.memory.storage.get_pubsub_node(
client, event.sender, event.nodeIdentifier
)
if node is None:
@ -555,45 +555,45 @@ class PubsubCache:
if not item_id:
log.warning(
"Ignoring invalid retract item element: "
f"{xml_tools.pFmtElt(elt)}"
f"{xml_tools.p_fmt_elt(elt)}"
)
continue
retract_ids.append(elt["id"])
else:
log.warning(
f"Unexpected Pubsub event element: {xml_tools.pFmtElt(elt)}"
f"Unexpected Pubsub event element: {xml_tools.p_fmt_elt(elt)}"
)
if items:
log.debug(f"[{client.profile}] caching new items received from {node}")
await self.cacheItems(
await self.cache_items(
client, node, items
)
if retract_ids:
log.debug(f"deleting retracted items from {node}")
await self.host.memory.storage.deletePubsubItems(
await self.host.memory.storage.delete_pubsub_items(
node, items_names=retract_ids
)
async def onDeleteEvent(self, client, event):
async def on_delete_event(self, client, event):
log.debug(
f"deleting node {event.nodeIdentifier} from {event.sender} for "
f"{client.profile}"
)
await self.host.memory.storage.deletePubsubNode(
await self.host.memory.storage.delete_pubsub_node(
[client.profile], [event.sender], [event.nodeIdentifier]
)
async def onPurgeEvent(self, client, event):
node = await self.host.memory.storage.getPubsubNode(
async def on_purge_event(self, client, event):
node = await self.host.memory.storage.get_pubsub_node(
client, event.sender, event.nodeIdentifier
)
if node is None:
return
log.debug(f"purging node {node} for {client.profile}")
await self.host.memory.storage.deletePubsubItems(node)
await self.host.memory.storage.delete_pubsub_items(node)
async def _getItemsTrigger(
async def _get_items_trigger(
self,
client: SatXMPPEntity,
service: Optional[jid.JID],
@ -613,17 +613,17 @@ class PubsubCache:
if service is None:
service = client.jid.userhostJID()
for __ in range(5):
pubsub_node = await self.host.memory.storage.getPubsubNode(
pubsub_node = await self.host.memory.storage.get_pubsub_node(
client, service, node
)
if pubsub_node is not None and pubsub_node.sync_state == SyncState.COMPLETED:
analyse = {"to_sync": True}
else:
analyse = await self.analyseNode(client, service, node)
analyse = await self.analyse_node(client, service, node)
if pubsub_node is None:
try:
pubsub_node = await self.host.memory.storage.setPubsubNode(
pubsub_node = await self.host.memory.storage.set_pubsub_node(
client,
service,
node,
@ -650,7 +650,7 @@ class PubsubCache:
if "mam" in extra:
log.debug("MAM caching is not supported yet, skipping cache")
return True, None
pubsub_items, metadata = await self.getItemsFromCache(
pubsub_items, metadata = await self.get_items_from_cache(
client, pubsub_node, max_items, item_ids, sub_id, rsm_request, extra
)
return False, ([i.data for i in pubsub_items], metadata)
@ -663,7 +663,7 @@ class PubsubCache:
"restarted. Resetting the status, caching will be done again."
)
pubsub_node.sync_state = None
await self.host.memory.storage.deletePubsubItems(pubsub_node)
await self.host.memory.storage.delete_pubsub_items(pubsub_node)
elif time.time() - pubsub_node.sync_state_updated > PROGRESS_DEADLINE:
log.warning(
f"{pubsub_node} is in progress for too long "
@ -672,7 +672,7 @@ class PubsubCache:
)
self.in_progress.pop[(service, node)].cancel()
pubsub_node.sync_state = None
await self.host.memory.storage.deletePubsubItems(pubsub_node)
await self.host.memory.storage.delete_pubsub_items(pubsub_node)
else:
log.debug(
f"{pubsub_node} synchronisation is already in progress, skipping"
@ -684,7 +684,7 @@ class PubsubCache:
f"There is already a caching in progress for {pubsub_node}, this "
"should not happen"
)
self.cacheNode(client, pubsub_node)
self.cache_node(client, pubsub_node)
elif pubsub_node.sync_state == SyncState.ERROR:
log.debug(
f"{pubsub_node} synchronisation has previously failed, skipping"
@ -692,7 +692,7 @@ class PubsubCache:
return True, None
async def _subscribeTrigger(
async def _subscribe_trigger(
self,
client: SatXMPPEntity,
service: jid.JID,
@ -703,7 +703,7 @@ class PubsubCache:
) -> None:
pass
async def _unsubscribeTrigger(
async def _unsubscribe_trigger(
self,
client: SatXMPPEntity,
service: jid.JID,
@ -715,7 +715,7 @@ class PubsubCache:
pass
def _synchronise(self, service, node, profile_key):
client = self.host.getClient(profile_key)
client = self.host.get_client(profile_key)
service = client.jid.userhostJID() if not service else jid.JID(service)
return defer.ensureDeferred(self.synchronise(client, service, node))
@ -735,7 +735,7 @@ class PubsubCache:
resynchronised (all items will be deleted and re-downloaded).
"""
pubsub_node = await self.host.memory.storage.getPubsubNode(
pubsub_node = await self.host.memory.storage.get_pubsub_node(
client, service, node
)
if pubsub_node is None:
@ -744,8 +744,8 @@ class PubsubCache:
"Synchronising the new node {node} at {service}"
).format(node=node, service=service.full)
)
analyse = await self.analyseNode(client, service, node)
pubsub_node = await self.host.memory.storage.setPubsubNode(
analyse = await self.analyse_node(client, service, node)
pubsub_node = await self.host.memory.storage.set_pubsub_node(
client,
service,
node,
@ -772,8 +772,8 @@ class PubsubCache:
)
# we first delete and recreate the node (will also delete its items)
await self.host.memory.storage.delete(pubsub_node)
analyse = await self.analyseNode(client, service, node)
pubsub_node = await self.host.memory.storage.setPubsubNode(
analyse = await self.analyse_node(client, service, node)
pubsub_node = await self.host.memory.storage.set_pubsub_node(
client,
service,
node,
@ -781,7 +781,7 @@ class PubsubCache:
type_=analyse.get("type"),
)
# then we can put node in cache
await self.cacheNode(client, pubsub_node)
await self.cache_node(client, pubsub_node)
async def purge(self, purge_filters: dict) -> None:
"""Remove items according to filters
@ -804,7 +804,7 @@ class PubsubCache:
datetime before which items must have been updated last to be deleted
"""
purge_filters["names"] = purge_filters.pop("nodes", None)
await self.host.memory.storage.purgePubsubItems(**purge_filters)
await self.host.memory.storage.purge_pubsub_items(**purge_filters)
def _purge(self, purge_filters: str) -> None:
purge_filters = data_format.deserialise(purge_filters)
@ -820,16 +820,16 @@ class PubsubCache:
After calling this method, cache will be refilled progressively as if it where new
"""
await self.host.memory.storage.deletePubsubNode(None, None, None)
await self.host.memory.storage.delete_pubsub_node(None, None, None)
def _reset(self) -> defer.Deferred:
return defer.ensureDeferred(self.reset())
async def search(self, query: dict) -> List[PubsubItem]:
"""Search pubsub items in cache"""
return await self.host.memory.storage.searchPubsubItems(query)
return await self.host.memory.storage.search_pubsub_items(query)
async def serialisableSearch(self, query: dict) -> List[dict]:
async def serialisable_search(self, query: dict) -> List[dict]:
"""Search pubsub items in cache and returns parsed data
The returned data can be serialised.
@ -844,7 +844,7 @@ class PubsubCache:
parsed["pubsub_node"] = item.node.name
if query.get("with_payload"):
parsed["item_payload"] = item.data.toXml()
parsed["node_profile"] = self.host.memory.storage.getProfileById(
parsed["node_profile"] = self.host.memory.storage.get_profile_by_id(
item.node.profile_id
)
@ -856,6 +856,6 @@ class PubsubCache:
services = query.get("services")
if services:
query["services"] = [jid.JID(s) for s in services]
d = defer.ensureDeferred(self.serialisableSearch(query))
d = defer.ensureDeferred(self.serialisable_search(query))
d.addCallback(data_format.serialise)
return d

View file

@ -67,10 +67,10 @@ class AESGCM(object):
"aesgcm", self.download
)
self._attach.register(
self.canHandleAttachment, self.attach, encrypted=True)
self.can_handle_attachment, self.attach, encrypted=True)
host.trigger.add("XEP-0363_upload_pre_slot", self._upload_pre_slot)
host.trigger.add("XEP-0363_upload", self._upload_trigger)
host.trigger.add("messageReceived", self._messageReceivedTrigger)
host.trigger.add("messageReceived", self._message_received_trigger)
async def download(self, client, uri_parsed, dest_path, options):
fragment = bytes.fromhex(uri_parsed.fragment)
@ -123,7 +123,7 @@ class AESGCM(object):
resp = await treq_client.get(download_url, unbuffered=True)
if resp.code == 200:
d = treq.collect(resp, partial(
self.onDataDownload,
self.on_data_download,
client=client,
file_obj=file_obj,
decryptor=decryptor))
@ -132,9 +132,9 @@ class AESGCM(object):
self.host.plugins["DOWNLOAD"].errback_download(file_obj, d, resp)
return progress_id, d
async def canHandleAttachment(self, client, data):
async def can_handle_attachment(self, client, data):
try:
await self._http_upload.getHTTPUploadEntity(client)
await self._http_upload.get_http_upload_entity(client)
except exceptions.NotFound:
return False
else:
@ -190,7 +190,7 @@ class AESGCM(object):
# nothing left to send, we can cancel the message
raise exceptions.CancelError("Cancelled by AESGCM attachment handling")
def onDataDownload(self, data, client, file_obj, decryptor):
def on_data_download(self, data, client, file_obj, decryptor):
if file_obj.tell() + len(data) > file_obj.size:
# we're reaching end of file with this bunch of data
# we may still have a last bunch if the tag is incomplete
@ -277,20 +277,20 @@ class AESGCM(object):
return True
def _popAESGCMLinks(self, match, links):
def _pop_aesgcm_links(self, match, links):
link = match.group()
if link not in links:
links.append(link)
return ""
def _checkAESGCMAttachments(self, client, data):
def _check_aesgcm_attachments(self, client, data):
if not data.get('message'):
return data
links = []
for lang, message in list(data['message'].items()):
message = AESGCM_RE.sub(
partial(self._popAESGCMLinks, links=links),
partial(self._pop_aesgcm_links, links=links),
message)
if links:
message = message.strip()
@ -319,9 +319,9 @@ class AESGCM(object):
return data
def _messageReceivedTrigger(self, client, message_elt, post_treat):
def _message_received_trigger(self, client, message_elt, post_treat):
# we use a post_treat callback instead of "message_parse" trigger because we need
# to check if the "encrypted" flag is set to decide if we add the same flag to the
# attachment
post_treat.addCallback(partial(self._checkAESGCMAttachments, client))
post_treat.addCallback(partial(self._check_aesgcm_attachments, client))
return True

View file

@ -92,7 +92,7 @@ class Context(potr.context.Context):
def _p_carbons(self):
return self.context_manager.parent._p_carbons
def getPolicy(self, key):
def get_policy(self, key):
if key in DEFAULT_POLICY_FLAGS:
return DEFAULT_POLICY_FLAGS[key]
else:
@ -123,10 +123,10 @@ class Context(potr.context.Context):
"extra": {},
"timestamp": time.time(),
}
client.generateMessageXML(mess_data)
client.generate_message_xml(mess_data)
xml = mess_data['xml']
self._p_carbons.setPrivate(xml)
self._p_hints.addHintElements(xml, [
self._p_carbons.set_private(xml)
self._p_hints.add_hint_elements(xml, [
self._p_hints.HINT_NO_COPY,
self._p_hints.HINT_NO_PERMANENT_STORE])
client.send(mess_data["xml"])
@ -135,19 +135,19 @@ class Context(potr.context.Context):
assert message_elt.name == "message"
message_elt.addElement("body", content=msg)
def stopCb(self, __, feedback):
def stop_cb(self, __, feedback):
client = self.user.client
self.host.bridge.otrState(
self.host.bridge.otr_state(
OTR_STATE_UNENCRYPTED, self.peer.full(), client.profile
)
client.feedback(self.peer, feedback)
def stopEb(self, failure_):
def stop_eb(self, failure_):
# encryption may be already stopped in case of manual stop
if not failure_.check(exceptions.NotFound):
log.error("Error while stopping OTR encryption: {msg}".format(msg=failure_))
def isTrusted(self):
def is_trusted(self):
# we have to check value because potr code says that a 2-tuples should be
# returned while in practice it's either None or u"trusted"
trusted = self.getCurrentTrust()
@ -160,24 +160,24 @@ class Context(potr.context.Context):
value=trusted))
return False
def setState(self, state):
def set_state(self, state):
client = self.user.client
old_state = self.state
super(Context, self).setState(state)
log.debug("setState: %s (old_state=%s)" % (state, old_state))
super(Context, self).set_state(state)
log.debug("set_state: %s (old_state=%s)" % (state, old_state))
if state == potr.context.STATE_PLAINTEXT:
feedback = _("/!\\ conversation with %(other_jid)s is now UNENCRYPTED") % {
"other_jid": self.peer.full()
}
d = defer.ensureDeferred(client.encryption.stop(self.peer, NS_OTR))
d.addCallback(self.stopCb, feedback=feedback)
d.addErrback(self.stopEb)
d.addCallback(self.stop_cb, feedback=feedback)
d.addErrback(self.stop_eb)
return
elif state == potr.context.STATE_ENCRYPTED:
defer.ensureDeferred(client.encryption.start(self.peer, NS_OTR))
try:
trusted = self.isTrusted()
trusted = self.is_trusted()
except TypeError:
trusted = False
trusted_str = _("trusted") if trusted else _("untrusted")
@ -195,7 +195,7 @@ class Context(potr.context.Context):
other_jid=self.peer.full(),
extra_info=NO_ADV_FEATURES,
)
self.host.bridge.otrState(
self.host.bridge.otr_state(
OTR_STATE_ENCRYPTED, self.peer.full(), client.profile
)
elif state == potr.context.STATE_FINISHED:
@ -203,8 +203,8 @@ class Context(potr.context.Context):
other_jid=self.peer.full()
)
d = defer.ensureDeferred(client.encryption.stop(self.peer, NS_OTR))
d.addCallback(self.stopCb, feedback=feedback)
d.addErrback(self.stopEb)
d.addCallback(self.stop_cb, feedback=feedback)
d.addErrback(self.stop_eb)
return
else:
log.error(D_("Unknown OTR state"))
@ -240,19 +240,19 @@ class Account(potr.context.Account):
self.host = host
self.client = client
def loadPrivkey(self):
log.debug("loadPrivkey")
def load_privkey(self):
log.debug("load_privkey")
return self.privkey
def savePrivkey(self):
log.debug("savePrivkey")
def save_privkey(self):
log.debug("save_privkey")
if self.privkey is None:
raise exceptions.InternalError(_("Save is called but privkey is None !"))
priv_key = hexlify(self.privkey.serializePrivateKey())
encrypted_priv_key = self.host.memory.encryptValue(priv_key, self.client.profile)
encrypted_priv_key = self.host.memory.encrypt_value(priv_key, self.client.profile)
self.client._otr_data[PRIVATE_KEY] = encrypted_priv_key
def loadTrusts(self):
def load_trusts(self):
trust_data = self.client._otr_data.get("trust", {})
for jid_, jid_data in trust_data.items():
for fingerprint, trust_level in jid_data.items():
@ -263,12 +263,12 @@ class Account(potr.context.Account):
)
self.trusts.setdefault(jid.JID(jid_), {})[fingerprint] = trust_level
def saveTrusts(self):
def save_trusts(self):
log.debug("saving trusts for {profile}".format(profile=self.client.profile))
log.debug("trusts = {}".format(self.client._otr_data["trust"]))
self.client._otr_data.force("trust")
def setTrust(self, other_jid, fingerprint, trustLevel):
def set_trust(self, other_jid, fingerprint, trustLevel):
try:
trust_data = self.client._otr_data["trust"]
except KeyError:
@ -276,7 +276,7 @@ class Account(potr.context.Account):
self.client._otr_data["trust"] = trust_data
jid_data = trust_data.setdefault(other_jid.full(), {})
jid_data[fingerprint] = trustLevel
super(Account, self).setTrust(other_jid, fingerprint, trustLevel)
super(Account, self).set_trust(other_jid, fingerprint, trustLevel)
class ContextManager(object):
@ -289,18 +289,18 @@ class ContextManager(object):
def host(self):
return self.parent.host
def startContext(self, other_jid):
def start_context(self, other_jid):
assert isinstance(other_jid, jid.JID)
context = self.contexts.setdefault(
other_jid, Context(self, other_jid)
)
return context
def getContextForUser(self, other):
log.debug("getContextForUser [%s]" % other)
def get_context_for_user(self, other):
log.debug("get_context_for_user [%s]" % other)
if not other.resource:
log.warning("getContextForUser called with a bare jid: %s" % other.full())
return self.startContext(other)
log.warning("get_context_for_user called with a bare jid: %s" % other.full())
return self.start_context(other)
class OTR(object):
@ -314,48 +314,48 @@ class OTR(object):
) #  FIXME: OTR should not be skipped per profile, this need to be refactored
self._p_hints = host.plugins["XEP-0334"]
self._p_carbons = host.plugins["XEP-0280"]
host.trigger.add("messageReceived", self.messageReceivedTrigger, priority=100000)
host.trigger.add("sendMessage", self.sendMessageTrigger, priority=100000)
host.trigger.add("sendMessageData", self._sendMessageDataTrigger)
host.bridge.addMethod(
"skipOTR", ".plugin", in_sign="s", out_sign="", method=self._skipOTR
host.trigger.add("messageReceived", self.message_received_trigger, priority=100000)
host.trigger.add("sendMessage", self.send_message_trigger, priority=100000)
host.trigger.add("send_message_data", self._send_message_data_trigger)
host.bridge.add_method(
"skip_otr", ".plugin", in_sign="s", out_sign="", method=self._skip_otr
) # FIXME: must be removed, must be done on per-message basis
host.bridge.addSignal(
"otrState", ".plugin", signature="sss"
host.bridge.add_signal(
"otr_state", ".plugin", signature="sss"
) # args: state, destinee_jid, profile
# XXX: menus are disabled in favor to the new more generic encryption menu
# there are let here commented for a little while as a reference
# host.importMenu(
# host.import_menu(
# (OTR_MENU, D_(u"Start/Refresh")),
# self._otrStartRefresh,
# self._otr_start_refresh,
# security_limit=0,
# help_string=D_(u"Start or refresh an OTR session"),
# type_=C.MENU_SINGLE,
# )
# host.importMenu(
# host.import_menu(
# (OTR_MENU, D_(u"End session")),
# self._otrSessionEnd,
# self._otr_session_end,
# security_limit=0,
# help_string=D_(u"Finish an OTR session"),
# type_=C.MENU_SINGLE,
# )
# host.importMenu(
# host.import_menu(
# (OTR_MENU, D_(u"Authenticate")),
# self._otrAuthenticate,
# self._otr_authenticate,
# security_limit=0,
# help_string=D_(u"Authenticate user/see your fingerprint"),
# type_=C.MENU_SINGLE,
# )
# host.importMenu(
# host.import_menu(
# (OTR_MENU, D_(u"Drop private key")),
# self._dropPrivKey,
# self._drop_priv_key,
# security_limit=0,
# type_=C.MENU_SINGLE,
# )
host.trigger.add("presence_received", self._presenceReceivedTrigger)
self.host.registerEncryptionPlugin(self, "OTR", NS_OTR, directed=True)
host.trigger.add("presence_received", self._presence_received_trigger)
self.host.register_encryption_plugin(self, "OTR", NS_OTR, directed=True)
def _skipOTR(self, profile):
def _skip_otr(self, profile):
"""Tell the backend to not handle OTR for this profile.
@param profile (str): %(doc_profile)s
@ -366,7 +366,7 @@ class OTR(object):
self.skipped_profiles.add(profile)
@defer.inlineCallbacks
def profileConnecting(self, client):
def profile_connecting(self, client):
if client.profile in self.skipped_profiles:
return
ctxMng = client._otr_context_manager = ContextManager(self, client)
@ -374,7 +374,7 @@ class OTR(object):
yield client._otr_data.load()
encrypted_priv_key = client._otr_data.get(PRIVATE_KEY, None)
if encrypted_priv_key is not None:
priv_key = self.host.memory.decryptValue(
priv_key = self.host.memory.decrypt_value(
encrypted_priv_key, client.profile
)
ctxMng.account.privkey = potr.crypt.PK.parsePrivateKey(
@ -382,9 +382,9 @@ class OTR(object):
)[0]
else:
ctxMng.account.privkey = None
ctxMng.account.loadTrusts()
ctxMng.account.load_trusts()
def profileDisconnected(self, client):
def profile_disconnected(self, client):
if client.profile in self.skipped_profiles:
self.skipped_profiles.remove(client.profile)
return
@ -394,20 +394,20 @@ class OTR(object):
# encryption plugin methods
def startEncryption(self, client, entity_jid):
self.startRefresh(client, entity_jid)
def start_encryption(self, client, entity_jid):
self.start_refresh(client, entity_jid)
def stopEncryption(self, client, entity_jid):
self.endSession(client, entity_jid)
def stop_encryption(self, client, entity_jid):
self.end_session(client, entity_jid)
def getTrustUI(self, client, entity_jid):
def get_trust_ui(self, client, entity_jid):
if not entity_jid.resource:
entity_jid.resource = self.host.memory.getMainResource(
entity_jid.resource = self.host.memory.main_resource_get(
client, entity_jid
) # FIXME: temporary and unsecure, must be changed when frontends
# are refactored
ctxMng = client._otr_context_manager
otrctx = ctxMng.getContextForUser(entity_jid)
otrctx = ctxMng.get_context_for_user(entity_jid)
priv_key = ctxMng.account.privkey
if priv_key is None:
@ -444,21 +444,21 @@ class OTR(object):
)
return dialog
def setTrust(raw_data, profile):
if xml_tools.isXMLUICancelled(raw_data):
def set_trust(raw_data, profile):
if xml_tools.is_xmlui_cancelled(raw_data):
return {}
# This method is called when authentication form is submited
data = xml_tools.XMLUIResult2DataFormResult(raw_data)
data = xml_tools.xmlui_result_2_data_form_result(raw_data)
if data["match"] == "yes":
otrctx.setCurrentTrust(OTR_STATE_TRUSTED)
note_msg = _("Your correspondent {correspondent} is now TRUSTED")
self.host.bridge.otrState(
self.host.bridge.otr_state(
OTR_STATE_TRUSTED, entity_jid.full(), client.profile
)
else:
otrctx.setCurrentTrust("")
note_msg = _("Your correspondent {correspondent} is now UNTRUSTED")
self.host.bridge.otrState(
self.host.bridge.otr_state(
OTR_STATE_UNTRUSTED, entity_jid.full(), client.profile
)
note = xml_tools.XMLUI(
@ -470,8 +470,8 @@ class OTR(object):
)
return {"xmlui": note.toXml()}
submit_id = self.host.registerCallback(setTrust, with_data=True, one_shot=True)
trusted = otrctx.isTrusted()
submit_id = self.host.register_callback(set_trust, with_data=True, one_shot=True)
trusted = otrctx.is_trusted()
xmlui = xml_tools.XMLUI(
C.XMLUI_FORM,
@ -489,29 +489,29 @@ class OTR(object):
)
)
xmlui.addDivider("blank")
xmlui.changeContainer("pairs")
xmlui.change_container("pairs")
xmlui.addLabel(D_("Is your correspondent fingerprint the same as here ?"))
xmlui.addList(
"match", [("yes", _("yes")), ("no", _("no"))], ["yes" if trusted else "no"]
)
return xmlui
def _otrStartRefresh(self, menu_data, profile):
def _otr_start_refresh(self, menu_data, profile):
"""Start or refresh an OTR session
@param menu_data: %(menu_data)s
@param profile: %(doc_profile)s
"""
client = self.host.getClient(profile)
client = self.host.get_client(profile)
try:
to_jid = jid.JID(menu_data["jid"])
except KeyError:
log.error(_("jid key is not present !"))
return defer.fail(exceptions.DataError)
self.startRefresh(client, to_jid)
self.start_refresh(client, to_jid)
return {}
def startRefresh(self, client, to_jid):
def start_refresh(self, client, to_jid):
"""Start or refresh an OTR session
@param to_jid(jid.JID): jid to start encrypted session with
@ -522,47 +522,47 @@ class OTR(object):
"Can't start an OTR session, there is already an encrypted session "
"with {name}").format(name=encrypted_session['plugin'].name))
if not to_jid.resource:
to_jid.resource = self.host.memory.getMainResource(
to_jid.resource = self.host.memory.main_resource_get(
client, to_jid
) # FIXME: temporary and unsecure, must be changed when frontends
# are refactored
otrctx = client._otr_context_manager.getContextForUser(to_jid)
otrctx = client._otr_context_manager.get_context_for_user(to_jid)
query = otrctx.sendMessage(0, b"?OTRv?")
otrctx.inject(query)
def _otrSessionEnd(self, menu_data, profile):
def _otr_session_end(self, menu_data, profile):
"""End an OTR session
@param menu_data: %(menu_data)s
@param profile: %(doc_profile)s
"""
client = self.host.getClient(profile)
client = self.host.get_client(profile)
try:
to_jid = jid.JID(menu_data["jid"])
except KeyError:
log.error(_("jid key is not present !"))
return defer.fail(exceptions.DataError)
self.endSession(client, to_jid)
self.end_session(client, to_jid)
return {}
def endSession(self, client, to_jid):
def end_session(self, client, to_jid):
"""End an OTR session"""
if not to_jid.resource:
to_jid.resource = self.host.memory.getMainResource(
to_jid.resource = self.host.memory.main_resource_get(
client, to_jid
) # FIXME: temporary and unsecure, must be changed when frontends
# are refactored
otrctx = client._otr_context_manager.getContextForUser(to_jid)
otrctx = client._otr_context_manager.get_context_for_user(to_jid)
otrctx.disconnect()
return {}
def _otrAuthenticate(self, menu_data, profile):
def _otr_authenticate(self, menu_data, profile):
"""End an OTR session
@param menu_data: %(menu_data)s
@param profile: %(doc_profile)s
"""
client = self.host.getClient(profile)
client = self.host.get_client(profile)
try:
to_jid = jid.JID(menu_data["jid"])
except KeyError:
@ -572,20 +572,20 @@ class OTR(object):
def authenticate(self, client, to_jid):
"""Authenticate other user and see our own fingerprint"""
xmlui = self.getTrustUI(client, to_jid)
xmlui = self.get_trust_ui(client, to_jid)
return {"xmlui": xmlui.toXml()}
def _dropPrivKey(self, menu_data, profile):
def _drop_priv_key(self, menu_data, profile):
"""Drop our private Key
@param menu_data: %(menu_data)s
@param profile: %(doc_profile)s
"""
client = self.host.getClient(profile)
client = self.host.get_client(profile)
try:
to_jid = jid.JID(menu_data["jid"])
if not to_jid.resource:
to_jid.resource = self.host.memory.getMainResource(
to_jid.resource = self.host.memory.main_resource_get(
client, to_jid
) # FIXME: temporary and unsecure, must be changed when frontends
# are refactored
@ -599,7 +599,7 @@ class OTR(object):
"xmlui": xml_tools.note(_("You don't have a private key yet !")).toXml()
}
def dropKey(data, profile):
def drop_key(data, profile):
if C.bool(data["answer"]):
# we end all sessions
for context in list(ctxMng.contexts.values()):
@ -614,7 +614,7 @@ class OTR(object):
}
return {}
submit_id = self.host.registerCallback(dropKey, with_data=True, one_shot=True)
submit_id = self.host.register_callback(drop_key, with_data=True, one_shot=True)
confirm = xml_tools.XMLUI(
C.XMLUI_DIALOG,
@ -624,10 +624,10 @@ class OTR(object):
)
return {"xmlui": confirm.toXml()}
def _receivedTreatment(self, data, client):
def _received_treatment(self, data, client):
from_jid = data["from"]
log.debug("_receivedTreatment [from_jid = %s]" % from_jid)
otrctx = client._otr_context_manager.getContextForUser(from_jid)
log.debug("_received_treatment [from_jid = %s]" % from_jid)
otrctx = client._otr_context_manager.get_context_for_user(from_jid)
try:
message = (
@ -699,17 +699,17 @@ class OTR(object):
exceptions.CancelError("Cancelled by OTR")
) # no message at all (no history, no signal)
client.encryption.markAsEncrypted(data, namespace=NS_OTR)
trusted = otrctx.isTrusted()
client.encryption.mark_as_encrypted(data, namespace=NS_OTR)
trusted = otrctx.is_trusted()
if trusted:
client.encryption.markAsTrusted(data)
client.encryption.mark_as_trusted(data)
else:
client.encryption.markAsUntrusted(data)
client.encryption.mark_as_untrusted(data)
return data
def _receivedTreatmentForSkippedProfiles(self, data):
def _received_treatment_for_skipped_profiles(self, data):
"""This profile must be skipped because the frontend manages OTR itself,
but we still need to check if the message must be stored in history or not
@ -731,7 +731,7 @@ class OTR(object):
data["history"] = C.HISTORY_SKIP
return data
def messageReceivedTrigger(self, client, message_elt, post_treat):
def message_received_trigger(self, client, message_elt, post_treat):
if client.is_component:
return True
if message_elt.getAttribute("type") == C.MESS_TYPE_GROUPCHAT:
@ -742,12 +742,12 @@ class OTR(object):
# OTR is only usable when resources are present
return True
if client.profile in self.skipped_profiles:
post_treat.addCallback(self._receivedTreatmentForSkippedProfiles)
post_treat.addCallback(self._received_treatment_for_skipped_profiles)
else:
post_treat.addCallback(self._receivedTreatment, client)
post_treat.addCallback(self._received_treatment, client)
return True
def _sendMessageDataTrigger(self, client, mess_data):
def _send_message_data_trigger(self, client, mess_data):
if client.is_component:
return True
encryption = mess_data.get(C.MESS_KEY_ENCRYPTION)
@ -755,10 +755,10 @@ class OTR(object):
return
to_jid = mess_data['to']
if not to_jid.resource:
to_jid.resource = self.host.memory.getMainResource(
to_jid.resource = self.host.memory.main_resource_get(
client, to_jid
) # FIXME: temporary and unsecure, must be changed when frontends
otrctx = client._otr_context_manager.getContextForUser(to_jid)
otrctx = client._otr_context_manager.get_context_for_user(to_jid)
message_elt = mess_data["xml"]
if otrctx.state == potr.context.STATE_ENCRYPTED:
log.debug("encrypting message")
@ -776,8 +776,8 @@ class OTR(object):
if body is None:
log.warning("No message found")
else:
self._p_carbons.setPrivate(message_elt)
self._p_hints.addHintElements(message_elt, [
self._p_carbons.set_private(message_elt)
self._p_hints.add_hint_elements(message_elt, [
self._p_hints.HINT_NO_COPY,
self._p_hints.HINT_NO_PERMANENT_STORE])
otrctx.sendMessage(0, str(body).encode("utf-8"), appdata=mess_data)
@ -791,7 +791,7 @@ class OTR(object):
client.feedback(to_jid, feedback)
raise failure.Failure(exceptions.CancelError("Cancelled by OTR plugin"))
def sendMessageTrigger(self, client, mess_data, pre_xml_treatments,
def send_message_trigger(self, client, mess_data, pre_xml_treatments,
post_xml_treatments):
if client.is_component:
return True
@ -808,32 +808,32 @@ class OTR(object):
return True
if not to_jid.resource:
to_jid.resource = self.host.memory.getMainResource(
to_jid.resource = self.host.memory.main_resource_get(
client, to_jid
) # FIXME: full jid may not be known
otrctx = client._otr_context_manager.getContextForUser(to_jid)
otrctx = client._otr_context_manager.get_context_for_user(to_jid)
if otrctx.state != potr.context.STATE_PLAINTEXT:
defer.ensureDeferred(client.encryption.start(to_jid, NS_OTR))
client.encryption.setEncryptionFlag(mess_data)
client.encryption.set_encryption_flag(mess_data)
if not mess_data["to"].resource:
# if not resource was given, we force it here
mess_data["to"] = to_jid
return True
def _presenceReceivedTrigger(self, client, entity, show, priority, statuses):
def _presence_received_trigger(self, client, entity, show, priority, statuses):
if show != C.PRESENCE_UNAVAILABLE:
return True
if not entity.resource:
try:
entity.resource = self.host.memory.getMainResource(
entity.resource = self.host.memory.main_resource_get(
client, entity
) # FIXME: temporary and unsecure, must be changed when frontends
# are refactored
except exceptions.UnknownEntityError:
return True # entity was not connected
if entity in client._otr_context_manager.contexts:
otrctx = client._otr_context_manager.getContextForUser(entity)
otrctx = client._otr_context_manager.get_context_for_user(entity)
otrctx.disconnect()
return True

View file

@ -83,7 +83,7 @@ class PubsubEncryption:
def __init__(self, host):
log.info(_("OpenPGP for XMPP Pubsub plugin initialization"))
host.registerNamespace("oxps", NS_OXPS)
host.register_namespace("oxps", NS_OXPS)
self.host = host
self._p = host.plugins["XEP-0060"]
self._h = host.plugins["XEP-0334"]
@ -94,32 +94,32 @@ class PubsubEncryption:
"messageReceived",
self._message_received_trigger,
)
host.bridge.addMethod(
"psSecretShare",
host.bridge.add_method(
"ps_secret_share",
".plugin",
in_sign="sssass",
out_sign="",
method=self._ps_secret_share,
async_=True,
)
host.bridge.addMethod(
"psSecretRevoke",
host.bridge.add_method(
"ps_secret_revoke",
".plugin",
in_sign="sssass",
out_sign="",
method=self._ps_secret_revoke,
async_=True,
)
host.bridge.addMethod(
"psSecretRotate",
host.bridge.add_method(
"ps_secret_rotate",
".plugin",
in_sign="ssass",
out_sign="",
method=self._ps_secret_rotate,
async_=True,
)
host.bridge.addMethod(
"psSecretsList",
host.bridge.add_method(
"ps_secrets_list",
".plugin",
in_sign="sss",
out_sign="s",
@ -127,10 +127,10 @@ class PubsubEncryption:
async_=True,
)
def getHandler(self, client):
def get_handler(self, client):
return PubsubEncryption_Handler()
async def profileConnecting(self, client):
async def profile_connecting(self, client):
client.__storage = persistent.LazyPersistentBinaryDict(
IMPORT_NAME, client.profile
)
@ -239,7 +239,7 @@ class PubsubEncryption:
) -> defer.Deferred:
return defer.ensureDeferred(
self.revoke(
self.host.getClient(profile_key),
self.host.get_client(profile_key),
jid.JID(service) if service else None,
node,
secret_id,
@ -267,7 +267,7 @@ class PubsubEncryption:
"""
if service is None:
service = client.jid.userhostJID()
node_uri = uri.buildXMPPUri("pubsub", path=service.full(), node=node)
node_uri = uri.build_xmpp_uri("pubsub", path=service.full(), node=node)
shared_secrets = await self.load_secrets(client, node_uri)
if not shared_secrets:
raise exceptions.NotFound(f"No shared secret is known for {node_uri}")
@ -327,7 +327,7 @@ class PubsubEncryption:
message_elt["from"] = client.jid.full()
message_elt["to"] = recipient.full()
message_elt.addChild((openpgp_elt))
self._h.addHintElements(message_elt, [self._h.HINT_STORE])
self._h.add_hint_elements(message_elt, [self._h.HINT_STORE])
client.send(message_elt)
def _ps_secret_share(
@ -340,7 +340,7 @@ class PubsubEncryption:
) -> defer.Deferred:
return defer.ensureDeferred(
self.share_secrets(
self.host.getClient(profile_key),
self.host.get_client(profile_key),
jid.JID(recipient),
jid.JID(service) if service else None,
node,
@ -377,7 +377,7 @@ class PubsubEncryption:
message_elt["from"] = client.jid.full()
message_elt["to"] = recipient.full()
message_elt.addChild((openpgp_elt))
self._h.addHintElements(message_elt, [self._h.HINT_STORE])
self._h.add_hint_elements(message_elt, [self._h.HINT_STORE])
client.send(message_elt)
shared_secret.shared_with.add(recipient)
@ -399,7 +399,7 @@ class PubsubEncryption:
"""
if service is None:
service = client.jid.userhostJID()
node_uri = uri.buildXMPPUri("pubsub", path=service.full(), node=node)
node_uri = uri.build_xmpp_uri("pubsub", path=service.full(), node=node)
shared_secrets = await self.load_secrets(client, node_uri)
if shared_secrets is None:
# no secret shared yet, let's generate one
@ -429,7 +429,7 @@ class PubsubEncryption:
) -> defer.Deferred:
return defer.ensureDeferred(
self.rotate_secret(
self.host.getClient(profile_key),
self.host.get_client(profile_key),
jid.JID(service) if service else None,
node,
[jid.JID(r) for r in recipients] or None
@ -453,7 +453,7 @@ class PubsubEncryption:
"""
if service is None:
service = client.jid.userhostJID()
node_uri = uri.buildXMPPUri("pubsub", path=service.full(), node=node)
node_uri = uri.build_xmpp_uri("pubsub", path=service.full(), node=node)
shared_secrets = await self.load_secrets(client, node_uri)
if shared_secrets is None:
shared_secrets = {}
@ -489,7 +489,7 @@ class PubsubEncryption:
) -> defer.Deferred:
d = defer.ensureDeferred(
self.list_shared_secrets(
self.host.getClient(profile_key),
self.host.get_client(profile_key),
jid.JID(service) if service else None,
node,
)
@ -512,7 +512,7 @@ class PubsubEncryption:
"""
if service is None:
service = client.jid.userhostJID()
node_uri = uri.buildXMPPUri("pubsub", path=service.full(), node=node)
node_uri = uri.build_xmpp_uri("pubsub", path=service.full(), node=node)
shared_secrets = await self.load_secrets(client, node_uri)
if shared_secrets is None:
raise exceptions.NotFound(f"No shared secrets found for {node_uri}")
@ -541,7 +541,7 @@ class PubsubEncryption:
f"ignoring invalid <revoke> element: {e}\n{revoke_elt.toXml()}"
)
return
node_uri = uri.buildXMPPUri("pubsub", path=service.full(), node=node)
node_uri = uri.build_xmpp_uri("pubsub", path=service.full(), node=node)
shared_secrets = await self.load_secrets(client, node_uri)
if shared_secrets is None:
log.warning(
@ -604,7 +604,7 @@ class PubsubEncryption:
shared_secret = SharedSecret(
id=secret_id, key=key, timestamp=timestamp, origin=sender, revoked=revoked
)
node_uri = uri.buildXMPPUri("pubsub", path=service.full(), node=node)
node_uri = uri.build_xmpp_uri("pubsub", path=service.full(), node=node)
shared_secrets = await self.load_secrets(client, node_uri)
if shared_secrets is None:
shared_secrets = {}
@ -636,7 +636,7 @@ class PubsubEncryption:
) -> bool:
if not items or not extra.get("encrypted"):
return True
node_uri = uri.buildXMPPUri("pubsub", path=service.full(), node=node)
node_uri = uri.build_xmpp_uri("pubsub", path=service.full(), node=node)
shared_secrets = await self.load_secrets(client, node_uri)
if shared_secrets is None:
shared_secrets = {}
@ -713,7 +713,7 @@ class PubsubEncryption:
)
continue
if shared_secrets is None:
node_uri = uri.buildXMPPUri("pubsub", path=service.full(), node=node)
node_uri = uri.build_xmpp_uri("pubsub", path=service.full(), node=node)
shared_secrets = await self.load_secrets(client, node_uri)
if shared_secrets is None:
log.warning(

View file

@ -55,13 +55,13 @@ class PTE:
def __init__(self, host):
log.info(_("Pubsub Targeted Encryption plugin initialization"))
host.registerNamespace("pte", NS_PTE)
host.register_namespace("pte", NS_PTE)
self.host = host
self._o = host.plugins["XEP-0384"]
host.trigger.add("XEP-0060_publish", self._publish_trigger)
host.trigger.add("XEP-0060_items", self._items_trigger)
def getHandler(self, client):
def get_handler(self, client):
return PTE_Handler()
async def _publish_trigger(

View file

@ -66,7 +66,7 @@ class PubsubSigning:
def __init__(self, host):
log.info(_("Pubsub Signing plugin initialization"))
host.registerNamespace("pubsub-signing", NS_PUBSUB_SIGNING)
host.register_namespace("pubsub-signing", NS_PUBSUB_SIGNING)
self.host = host
self._p = host.plugins["XEP-0060"]
self._ox = host.plugins["XEP-0373"]
@ -75,8 +75,8 @@ class PubsubSigning:
"signature", NS_PUBSUB_SIGNING, self.signature_get, self.signature_set
)
host.trigger.add("XEP-0060_publish", self._publish_trigger)
host.bridge.addMethod(
"psSignatureCheck",
host.bridge.add_method(
"ps_signature_check",
".plugin",
in_sign="sssss",
out_sign="s",
@ -84,7 +84,7 @@ class PubsubSigning:
async_=True,
)
def getHandler(self, client):
def get_handler(self, client):
return PubsubSigning_Handler()
def get_data_to_sign(
@ -137,7 +137,7 @@ class PubsubSigning:
) -> defer.Deferred:
d = defer.ensureDeferred(
self.check(
self.host.getClient(profile_key),
self.host.get_client(profile_key),
jid.JID(service),
node,
item_id,
@ -155,7 +155,7 @@ class PubsubSigning:
item_id: str,
signature_data: Dict[str, Any],
) -> Dict[str, Any]:
items, __ = await self._p.getItems(
items, __ = await self._p.get_items(
client, service, node, item_ids=[item_id]
)
if not items != 1:
@ -254,7 +254,7 @@ class PubsubSigning:
if item_elt is None:
node = attachments_data["node"]
item_id = attachments_data["id"]
items, __ = await self._p.getItems(
items, __ = await self._p.get_items(
client, service, node, item_ids=[item_id]
)
if not items != 1:

View file

@ -317,7 +317,7 @@ class XHTMLParser(object):
setattr(
self,
"parser_h{}".format(i),
lambda elt, buf, level=i: self.parserHeading(elt, buf, level),
lambda elt, buf, level=i: self.parser_heading(elt, buf, level),
)
def parser_a(self, elt, buf):
@ -331,7 +331,7 @@ class XHTMLParser(object):
# we don't want empty values
raise KeyError
except KeyError:
self.parserGeneric(elt, buf)
self.parser_generic(elt, buf)
else:
buf.append("~~{}~~".format(id_))
return
@ -358,7 +358,7 @@ class XHTMLParser(object):
title = elt["title"]
except KeyError:
log.debug("Acronyme without title, using generic parser")
self.parserGeneric(elt, buf)
self.parser_generic(elt, buf)
return
buf.append("??{}|{}??".format(str(elt), title))
@ -370,7 +370,7 @@ class XHTMLParser(object):
if len(children) == 1 and children[0].name == "p":
elt = children[0]
tmp_buf = []
self.parseChildren(elt, tmp_buf)
self.parse_children(elt, tmp_buf)
blockquote = "> " + "\n> ".join("".join(tmp_buf).split("\n"))
buf.append(blockquote)
@ -379,23 +379,23 @@ class XHTMLParser(object):
def parser_code(self, elt, buf):
buf.append("@@")
self.parseChildren(elt, buf)
self.parse_children(elt, buf)
buf.append("@@")
def parser_del(self, elt, buf):
buf.append("--")
self.parseChildren(elt, buf)
self.parse_children(elt, buf)
buf.append("--")
def parser_div(self, elt, buf):
if elt.getAttribute("class") == "footnotes":
self.parserFootnote(elt, buf)
self.parser_footnote(elt, buf)
else:
self.parseChildren(elt, buf, block=True)
self.parse_children(elt, buf, block=True)
def parser_em(self, elt, buf):
buf.append("''")
self.parseChildren(elt, buf)
self.parse_children(elt, buf)
buf.append("''")
def parser_h6(self, elt, buf):
@ -449,7 +449,7 @@ class XHTMLParser(object):
def parser_ins(self, elt, buf):
buf.append("++")
self.parseChildren(elt, buf)
self.parse_children(elt, buf)
buf.append("++")
def parser_li(self, elt, buf):
@ -474,14 +474,14 @@ class XHTMLParser(object):
buf.extend(bullets)
buf.append(" ")
self.parseChildren(elt, buf)
self.parse_children(elt, buf)
buf.append("\n")
def parser_ol(self, elt, buf):
self.parserList(elt, buf, FLAG_OL)
self.parser_list(elt, buf, FLAG_OL)
def parser_p(self, elt, buf):
self.parseChildren(elt, buf)
self.parse_children(elt, buf)
buf.append("\n\n")
def parser_pre(self, elt, buf):
@ -513,11 +513,11 @@ class XHTMLParser(object):
buf.append("}}")
def parser_span(self, elt, buf):
self.parseChildren(elt, buf, block=True)
self.parse_children(elt, buf, block=True)
def parser_strong(self, elt, buf):
buf.append("__")
self.parseChildren(elt, buf)
self.parse_children(elt, buf)
buf.append("__")
def parser_sup(self, elt, buf):
@ -535,7 +535,7 @@ class XHTMLParser(object):
note_id = url[url.find("#") + 1 :]
if not note_id:
log.warning("bad link found in footnote")
self.parserGeneric(elt, buf)
self.parser_generic(elt, buf)
return
# this looks like a footnote
buf.append("$$")
@ -543,14 +543,14 @@ class XHTMLParser(object):
self.footnotes[note_id] = len(buf) - 1
buf.append("$$")
else:
self.parserGeneric(elt, buf)
self.parser_generic(elt, buf)
def parser_ul(self, elt, buf):
self.parserList(elt, buf, FLAG_UL)
self.parser_list(elt, buf, FLAG_UL)
def parserList(self, elt, buf, type_):
def parser_list(self, elt, buf, type_):
self.flags.append(type_)
self.parseChildren(elt, buf, block=True)
self.parse_children(elt, buf, block=True)
idx = 0
for flag in reversed(self.flags):
idx -= 1
@ -561,14 +561,14 @@ class XHTMLParser(object):
if idx == 0:
raise exceptions.InternalError("flag has been removed by an other parser")
def parserHeading(self, elt, buf, level):
def parser_heading(self, elt, buf, level):
buf.append((6 - level) * "!")
for child in elt.children:
# we ignore other elements for a Hx title
self.parserText(child, buf)
self.parser_text(child, buf)
buf.append("\n")
def parserFootnote(self, elt, buf):
def parser_footnote(self, elt, buf):
for elt in elt.elements():
# all children other than <p/> are ignored
if elt.name == "p":
@ -587,11 +587,11 @@ class XHTMLParser(object):
a_idx = elt.children.index(a_elt)
dummy_elt.children = elt.children[a_idx + 1 :]
note_buf = []
self.parseChildren(dummy_elt, note_buf)
self.parse_children(dummy_elt, note_buf)
# now we can replace the placeholder
buf[note_idx] = "".join(note_buf)
def parserText(self, txt, buf, keep_whitespaces=False):
def parser_text(self, txt, buf, keep_whitespaces=False):
txt = str(txt)
if not keep_whitespaces:
# we get text and only let one inter word space
@ -601,12 +601,12 @@ class XHTMLParser(object):
buf.append(txt)
return txt
def parserGeneric(self, elt, buf):
def parser_generic(self, elt, buf):
# as dotclear wiki syntax handle arbitrary XHTML code
# we use this feature to add elements that we don't know
buf.append("\n\n///html\n{}\n///\n\n".format(elt.toXml()))
def parseChildren(self, elt, buf, block=False):
def parse_children(self, elt, buf, block=False):
first_visible = True
for child in elt.children:
if not block and not first_visible and buf and buf[-1][-1] not in (" ", "\n"):
@ -616,7 +616,7 @@ class XHTMLParser(object):
self._parse(child, buf)
first_visible = False
else:
appended = self.parserText(child, buf)
appended = self.parser_text(child, buf)
if appended:
first_visible = False
@ -626,7 +626,7 @@ class XHTMLParser(object):
if style and elt_name not in ELT_WITH_STYLE:
# if we have style we use generic parser to put raw HTML
# to avoid losing it
parser = self.parserGeneric
parser = self.parser_generic
else:
try:
parser = getattr(self, "parser_{}".format(elt_name))
@ -634,7 +634,7 @@ class XHTMLParser(object):
log.debug(
"Can't find parser for {} element, using generic one".format(elt.name)
)
parser = self.parserGeneric
parser = self.parser_generic
parser(elt, buf)
def parse(self, elt):
@ -666,13 +666,13 @@ class DCWikiSyntax(object):
self._dc_parser = DCWikiParser()
self._xhtml_parser = XHTMLParser()
self._stx = self.host.plugins["TEXT_SYNTAXES"]
self._stx.addSyntax(
self.SYNTAX_NAME, self.parseWiki, self.parseXHTML, [self._stx.OPT_NO_THREAD]
self._stx.add_syntax(
self.SYNTAX_NAME, self.parse_wiki, self.parse_xhtml, [self._stx.OPT_NO_THREAD]
)
def parseWiki(self, wiki_stx):
def parse_wiki(self, wiki_stx):
div_elt = self._dc_parser.parse(wiki_stx)
return div_elt.toXml()
def parseXHTML(self, xhtml):
def parse_xhtml(self, xhtml):
return self._xhtml_parser.parseString(xhtml)

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