Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
99 commits
Select commit Hold shift + click to select a range
ed0515d
Create client to run commands
dedaldino3d Nov 4, 2020
53bae9e
Serialize response
dedaldino3d Nov 4, 2020
48be356
Authenticate request
dedaldino3d Nov 4, 2020
a75c5c3
After initial commit
dedaldino3d Nov 4, 2020
b5f24b0
Add README.md
dedaldino3d Nov 4, 2020
ca4bc48
Changed LICENSE
dedaldino3d Nov 4, 2020
bdc17b4
Create & move files to src and defaults
dedaldino3d Nov 4, 2020
bad7750
Implement methods
dedaldino3d Nov 4, 2020
362fb80
Add custom exceptions
dedaldino3d Nov 4, 2020
f82f2e0
Create API as base class
dedaldino3d Nov 4, 2020
175a7b6
Add Enum class in arguments
dedaldino3d Nov 4, 2020
966ef68
Add api.py(use for APIArgument)
dedaldino3d Nov 4, 2020
506d1a9
Move core & defaults to src
dedaldino3d Nov 4, 2020
2cb9ce2
Base Exception to ValueError
dedaldino3d Nov 4, 2020
3edc4f2
Create Serializers definitions
dedaldino3d Nov 4, 2020
b1a52bd
Add constants and change LICENSE
dedaldino3d Nov 4, 2020
f6623e5
Create a package to contain abstract base classes
dedaldino3d Nov 5, 2020
2846573
Add implementation of a base class for API
dedaldino3d Nov 6, 2020
ee749af
Add muc serializers
dedaldino3d Nov 6, 2020
1d8c3ad
Add muc enums
dedaldino3d Nov 6, 2020
12cc443
Add muc arguments
dedaldino3d Nov 6, 2020
f3239bd
Declare muc room options serializers in __init__
dedaldino3d Nov 6, 2020
332432c
Implement base methods for xml-rpc calls in top APIClient
dedaldino3d Nov 6, 2020
ee34ae3
Add UserAlreadyRegistered Exception
dedaldino3d Nov 6, 2020
fcc6d09
Add critical methods in client to make xml-rpc calls
dedaldino3d Nov 6, 2020
8045aed
Rename src to ejabberd_python3d. - Add import in __init__
dedaldino3d Nov 6, 2020
9004f33
Add external authentication for ejabberd from django based on ejabber…
dedaldino3d Nov 6, 2020
269123f
Add idea in gitignore
dedaldino3d Nov 13, 2020
8929e9c
Add __init__ in abc
dedaldino3d Nov 13, 2020
04787d8
Implement new base methods in EjabberdBaseAPI
dedaldino3d Nov 13, 2020
1aa4055
Update LICENSE (author codename). :(
dedaldino3d Nov 13, 2020
216004c
Add utils
dedaldino3d Nov 13, 2020
9c74ed1
Override new methods
dedaldino3d Nov 13, 2020
bd5a86c
Implement new methods
dedaldino3d Nov 13, 2020
b0e92a1
Refactor code (code cleanup)
dedaldino3d Nov 13, 2020
49f6b8b
Add requirements
dedaldino3d Nov 13, 2020
9dd22f7
Add AUTHORS
dedaldino3d Nov 13, 2020
68c4a76
Add MANIFEST.in
dedaldino3d Nov 13, 2020
10cc87a
setup project
dedaldino3d Nov 13, 2020
08c8826
use methods, first argument in _call_api
dedaldino3d Nov 14, 2020
dfd8d9d
Update imports, change argument in GetRoster
dedaldino3d Nov 14, 2020
33a849b
Change superclass from ABCMeta to ABC, update imports
dedaldino3d Nov 16, 2020
af48c3c
Change send_message signature, subject is not required now. Update im…
dedaldino3d Nov 16, 2020
a788b01
Add CheckPassword & DeleteExpiredMessages in methods
dedaldino3d Nov 16, 2020
cb4509e
Add DeleteOldMessages & DeleteOldUsers in methods
dedaldino3d Nov 16, 2020
1d3679e
Add DeleteOldUsersVhost & GetCookie in methods
dedaldino3d Nov 16, 2020
f7c5235
Add GetLogLevel & GetVcard in methods
dedaldino3d Nov 16, 2020
b2ea3bb
Add GetVcard2Multi & GetVcard2 in methods
dedaldino3d Nov 16, 2020
82ee002
Add KickSession & IncomingS2SNumber in methods
dedaldino3d Nov 16, 2020
a27e048
Add ListCluster, ModulesInstalled & ModulesAvailable in methods
dedaldino3d Nov 16, 2020
b3f9f1c
Remove num_cative_users from client and Add NumResources & OutgoingS2…
dedaldino3d Nov 16, 2020
c09dfdb
Add PushAllToAll & ProcessRosterItems in methods
dedaldino3d Nov 16, 2020
cc83573
Add RegisteredVhosts & ReloadConfig in methods
dedaldino3d Nov 16, 2020
2b0d129
Delete remove_node from client and Add ResourceNum & ReopenLog in met…
dedaldino3d Nov 16, 2020
4890d54
Add SendStanzaC2S & Restart in methods
dedaldino3d Nov 16, 2020
2e9cb7d
Add new classes in methods.py, Add loglevel options, Create enums to …
dedaldino3d Nov 16, 2020
d005e03
Add SetVcard & SetPresence in methods
dedaldino3d Nov 16, 2020
7a8e8d5
Add SetVcardMulti & SetVcard2 in methods
dedaldino3d Nov 16, 2020
39db0c7
Add SrgDelete & SrgCreate in methods
dedaldino3d Nov 16, 2020
c36d813
Add SrgGetMembers & SrgGetInfo in methods
dedaldino3d Nov 16, 2020
96c6d2c
Add SrgUserDel, SrgUserAdd & SrgList in methods
dedaldino3d Nov 16, 2020
428069b
Add Stats & StatsHost in methods
dedaldino3d Nov 16, 2020
973d39a
Add statuses in methods
dedaldino3d Nov 16, 2020
56c7498
Add Stop & StopKindly in methods
dedaldino3d Nov 16, 2020
c157e67
Add UpdateList, Update & UpdateSql in methods, Add update_sql in client
dedaldino3d Nov 16, 2020
6ce0f2b
Add UserResources in methods
dedaldino3d Nov 16, 2020
9290e52
Finish implementation of some methods, finish add update_sql method i…
dedaldino3d Nov 16, 2020
e53f75a
Create a script to extract TODOS
dedaldino3d Nov 16, 2020
606ec24
raise NotImplementedError in all methods and remove unused methods in…
dedaldino3d Nov 16, 2020
b241dfb
rename superclass ==> subclass in api.py
dedaldino3d Nov 16, 2020
f433c41
Move TODOS.md to root directory, update algorithm to extract TODOS
dedaldino3d Nov 16, 2020
b9d878c
Rename auth ==> ejabberd_auth (avoid problems in django installed apps)
dedaldino3d Nov 21, 2020
ac3ae21
add ejabberd_auth to __init__ file
dedaldino3d Nov 21, 2020
f2f97df
Remove invalid classifier and wrong github link to repository
dedaldino3d Nov 22, 2020
6144ed3
Change __version__ in setup file
dedaldino3d Nov 22, 2020
c84034c
Change argument in add_rosteritem(localserver => localhost, server =>…
dedaldino3d Nov 22, 2020
c0854e4
Add method get_subscribers
dedaldino3d Nov 22, 2020
940a53a
Add method get_user_rooms
dedaldino3d Nov 22, 2020
fd9db46
Finish subscription implimentation, added new serializers and arguments
dedaldino3d Nov 22, 2020
4bf07e5
Add create_room_with_opts(not finished)
dedaldino3d Nov 22, 2020
05848a4
Use django 3.0 or high instead 3.1
dedaldino3d Nov 24, 2020
0ab9248
Update version in setup
dedaldino3d Nov 24, 2020
d0d9b2e
Add docstrings in methods, Update arguments in some methods and abc
dedaldino3d Dec 4, 2020
5854602
Change version in setup.py
dedaldino3d Dec 4, 2020
98c90fe
Add get_room_occupants
dedaldino3d Jan 4, 2021
f6c3ec7
Alter change_password method signature
dedaldino3d Jan 4, 2021
5461980
Add backup method
dedaldino3d Jan 4, 2021
acf3ece
Add change_room_option & remove change_room_option TODO
dedaldino3d Jan 4, 2021
2e6fb0d
Add compile & remove compile TODO
dedaldino3d Jan 4, 2021
93cee6e
Add convert_to_scram & remove convert_to_scram TODO
dedaldino3d Jan 4, 2021
4901e98
Add convert_to_yaml method
dedaldino3d Jan 4, 2021
d6867a8
Add create_rooms_file method
dedaldino3d Jan 4, 2021
f434718
Add delete_mnesia method
dedaldino3d Jan 4, 2021
c35a918
Add delete_old_mam_messages method
dedaldino3d Jan 4, 2021
e98dfb1
Remove delete_room TODO
dedaldino3d Jan 4, 2021
7a387d9
Add destroy_rooms_file method
dedaldino3d Jan 4, 2021
8379785
Add dump method
dedaldino3d Jan 4, 2021
b61092f
README updated
dedaldino3d Jan 4, 2021
4ff4474
Start implementation of tests & update muc/enums
dedaldino3d Jun 3, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ __pycache__/
*.py[cod]
*$py.class

# PyCharm
.idea/
# C extensions
*.so

Expand Down
4 changes: 4 additions & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
## AUTHORS
======================================

* Dedaldino Antonio, 3D - dedaldinoantonio7@gmail.com
142 changes: 21 additions & 121 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,121 +1,21 @@
Creative Commons Legal Code

CC0 1.0 Universal

CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.

Statement of Purpose

The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").

Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.

For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.

1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:

i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.

2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.

3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.

4. Limitations and Disclaimers.

a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.
The MIT License (MIT)

Copyright (c) 2020 Dedaldino Antonio, a.k.a 3D

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
3 changes: 3 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
include LICENSE
include README.md
include requirements.txt
53 changes: 53 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
**A python lib to run ejabberd XML-RPC commands**

**Features**
<ul>
<li>Execute XML-RPC commands</li>
<li>External authentication</li>
<li>Register Users</li>
<li>Delete Users</li>
<li>Create Rooms</li>
<li>Subscribe to Rooms</li>
<li>Send Messages</li>
<li> and many others features, ... .</li>
</ul>

#### How to install
When working with python its a common approach to use a virtualenv to encapsulate all dependencies.
First create a virtual environment:
__if you have virtualenv installed run this code__
```python
virtualenv ejabberd_python3d_venv
```
__if not, so install with this code:__
````python
pip install virtualenv
````
and then install **ejabberd_python3d** lib:
```python
pip install ejabberd_python3d
```

To get the most updated version, you'll need to clone this repository:
````git
git clone http://github.com/Dedaldino3D/ejabberd_python3d.git
````
Run
````python
python setup.py
````

After installation is completed, create a client instance:

````python
from ejabberd_python3d.client import EjabberdAPIClient

client = EjabberdAPIClient('localhost','dedaldino','123456')
users = client.registered_users('localhost')
# assuming that you have an user registered (the admin)
print(users) # [dedaldino]
client.register('dedaldino3d','localhost','nopassword')
users = client.registered_users('localhost')
print(users) # ['dedaldino3d']
````

122 changes: 122 additions & 0 deletions TODOS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# METHODS TO IMPLEMENT
### TODO def backup(self, file): Store the database to backup file
### TODO def change_room_option(self, name, service, option, value)
### TODO def compile(self, file):
### TODO def convert_to_scram(self, host):
### TODO def convert_to_yaml(self, in, out):
### TODO def create_room(self, name, service, host):
### TODO def create_room_with_opts(self, name, service, host, options):
### TODO def create_rooms_file(self, file):
### TODO def delete_mnesia(self, host):
### TODO def delete_old_mam_messages(self, type, days):
### TODO def destroy_room(self, name, service):
### TODO def destroy_rooms_file(self, file):
### TODO def dump(self, file):
### TODO def dump_table(self, file, table):
### TODO def export2sql(self, host, file):
### TODO def export_piefxis(self, dir):
### TODO def export_piefxis_host(self, dir, host):
### TODO def gen_html_doc_for_commands(self, file, regexp, examples):
### TODO def gen_markdown_doc_for_commands(self, file, regexp, examples):
### TODO def get_offline_count(self):
### TODO def get_room_affiliations(self, name, service):
### TODO def get_room_occupants(self, name, service):
### TODO def get_room_occupants_number(self, name, service):
### TODO def get_room_options(self, name, service):
### TODO get_subscribers(self, name, service):
### TODO get_user_rooms(self, user, host):
### TODO def import_dir(self, file):
### TODO def import_file(self, file):
### TODO def import_piefxis(self, file):
### TODO def import_prosody(self, dir) Import data from Prosody
### TODO def install_fallback(self, file):
### TODO def join_cluster(self, node):
### TODO def leave_cluster(self, node):
### TODO def load(self, file):
### TODO def mnesia_change_nodename(self,
### TODO def module_check(self, module):
### TODO def module_install(self, module):
### TODO def module_uninstall(self, module):
### TODO def module_upgrade(self, module):
### TODO def modules_update_specs(self):
### TODO def muc_online_rooms(self, host):
### TODO def muc_unregister_nick(self, nick):
### TODO def privacy_set(self, user, host, xmlquery):
### TODO def private_get(self, user, host, element, ns):
### TODO def private_set(self, user, host, element):
### TODO def push_roster(self, file, user, host):
### TODO def push_roster_all(self, file):
### TODO def restore(self, file):
### TODO def rooms_unused_destroy(self, host, days):
### TODO def rooms_unused_list(self, host, days):
### TODO def rotate_log(self):
### TODO def send_direct_invitation(self,
### TODO def send_stanza(self, from, to, stanza):
### TODO def set_room_affiliation(self, name, service, jid, affiliation):
### TODO def subscribe_room(self, user, nick, room, nodes):
### TODO def unsubscribe_room(self, user, room):
### TODO: add argument options: [{name::string,value::string}]: List of options
### TODO: nodes must be separated by commas, so therefore you can use an array and before send transform arguments
### TODO: some arguments is not required
### TODO: name is between: registeredusers onlineusers onlineusersnode uptimeseconds processes
### TODO: name is between: registeredusers onlineusers
### TODO def backup(self, file): Store the database to backup file
### TODO def change_room_option(self, name, service, option, value)
### TODO def compile(self, file):
### TODO def convert_to_scram(self, host):
### TODO def convert_to_yaml(self, in, out):
### TODO def create_room(self, name, service, host):
### TODO def create_room_with_opts(self, name, service, host, options):
### TODO def create_rooms_file(self, file):
### TODO def delete_mnesia(self, host):
### TODO def delete_old_mam_messages(self, type, days):
### TODO def destroy_room(self, name, service):
### TODO def destroy_rooms_file(self, file):
### TODO def dump(self, file):
### TODO def dump_table(self, file, table):
### TODO def export2sql(self, host, file):
### TODO def export_piefxis(self, dir):
### TODO def export_piefxis_host(self, dir, host):
### TODO def gen_html_doc_for_commands(self, file, regexp, examples):
### TODO def gen_markdown_doc_for_commands(self, file, regexp, examples):
### TODO def get_offline_count(self):
### TODO def get_room_affiliations(self, name, service):
### TODO def get_room_occupants(self, name, service):
### TODO def get_room_occupants_number(self, name, service):
### TODO def get_room_options(self, name, service):
### TODO get_subscribers(self, name, service):
### TODO get_user_rooms(self, user, host):
### TODO def import_dir(self, file):
### TODO def import_file(self, file):
### TODO def import_piefxis(self, file):
### TODO def import_prosody(self, dir) Import data from Prosody
### TODO def install_fallback(self, file):
### TODO def join_cluster(self, node):
### TODO def leave_cluster(self, node):
### TODO def load(self, file):
### TODO def mnesia_change_nodename(self,
### TODO def module_check(self, module):
### TODO def module_install(self, module):
### TODO def module_uninstall(self, module):
### TODO def module_upgrade(self, module):
### TODO def modules_update_specs(self):
### TODO def muc_online_rooms(self, host):
### TODO def muc_unregister_nick(self, nick):
### TODO def privacy_set(self, user, host, xmlquery):
### TODO def private_get(self, user, host, element, ns):
### TODO def private_set(self, user, host, element):
### TODO def push_roster(self, file, user, host):
### TODO def push_roster_all(self, file):
### TODO def restore(self, file):
### TODO def rooms_unused_destroy(self, host, days):
### TODO def rooms_unused_list(self, host, days):
### TODO def rotate_log(self):
### TODO def send_direct_invitation(self,
### TODO def send_stanza(self, from, to, stanza):
### TODO def set_room_affiliation(self, name, service, jid, affiliation):
### TODO def subscribe_room(self, user, nick, room, nodes):
### TODO def unsubscribe_room(self, user, room):

## Generics TODOS
### TODO: add endpoint parameter
### TODO: add it to logger
2 changes: 2 additions & 0 deletions ejabberd_python3d/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from ejabberd_python3d import client, serializers, ejabberd_auth
from ejabberd_python3d import muc, abc, defaults
Empty file.
Loading