slidge 0.1.0b2__py3-none-any.whl → 0.1.1__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (155) hide show
  1. slidge/__init__.py +55 -31
  2. slidge/__main__.py +118 -116
  3. slidge/command/__init__.py +28 -0
  4. slidge/command/adhoc.py +258 -0
  5. slidge/command/admin.py +193 -0
  6. slidge/command/base.py +441 -0
  7. slidge/command/categories.py +3 -0
  8. slidge/command/chat_command.py +288 -0
  9. slidge/command/register.py +179 -0
  10. slidge/command/user.py +250 -0
  11. slidge/contact/__init__.py +8 -0
  12. slidge/contact/contact.py +452 -0
  13. slidge/contact/roster.py +192 -0
  14. slidge/core/__init__.py +2 -0
  15. slidge/core/cache.py +183 -0
  16. slidge/core/config.py +216 -0
  17. slidge/core/gateway/__init__.py +3 -0
  18. slidge/core/gateway/base.py +895 -0
  19. slidge/core/gateway/caps.py +63 -0
  20. slidge/core/gateway/delivery_receipt.py +52 -0
  21. slidge/core/gateway/disco.py +80 -0
  22. slidge/core/gateway/mam.py +75 -0
  23. slidge/core/gateway/muc_admin.py +35 -0
  24. slidge/core/gateway/ping.py +66 -0
  25. slidge/core/gateway/presence.py +95 -0
  26. slidge/core/gateway/registration.py +53 -0
  27. slidge/core/gateway/search.py +102 -0
  28. slidge/core/gateway/session_dispatcher.py +789 -0
  29. slidge/core/gateway/vcard_temp.py +130 -0
  30. slidge/core/mixins/__init__.py +19 -0
  31. slidge/core/mixins/attachment.py +506 -0
  32. slidge/core/mixins/avatar.py +167 -0
  33. slidge/core/mixins/base.py +31 -0
  34. slidge/core/mixins/disco.py +130 -0
  35. slidge/core/mixins/lock.py +31 -0
  36. slidge/core/mixins/message.py +398 -0
  37. slidge/core/mixins/message_maker.py +154 -0
  38. slidge/core/mixins/presence.py +217 -0
  39. slidge/core/mixins/recipient.py +43 -0
  40. slidge/core/pubsub.py +282 -116
  41. slidge/core/session.py +595 -372
  42. slidge/group/__init__.py +10 -0
  43. slidge/group/archive.py +125 -0
  44. slidge/group/bookmarks.py +163 -0
  45. slidge/group/participant.py +458 -0
  46. slidge/group/room.py +1103 -0
  47. slidge/migration.py +18 -0
  48. slidge/slixfix/__init__.py +68 -0
  49. slidge/{util/xep_0084 → slixfix/link_preview}/__init__.py +3 -5
  50. slidge/slixfix/link_preview/link_preview.py +17 -0
  51. slidge/slixfix/link_preview/stanza.py +99 -0
  52. slidge/slixfix/roster.py +60 -0
  53. slidge/{util → slixfix}/xep_0077/register.py +14 -2
  54. slidge/slixfix/xep_0077/stanza.py +104 -0
  55. slidge/{util → slixfix}/xep_0100/gateway.py +25 -15
  56. slidge/slixfix/xep_0100/stanza.py +9 -0
  57. slidge/slixfix/xep_0153/__init__.py +10 -0
  58. slidge/slixfix/xep_0153/stanza.py +25 -0
  59. slidge/slixfix/xep_0153/vcard_avatar.py +23 -0
  60. slidge/slixfix/xep_0264/__init__.py +5 -0
  61. slidge/slixfix/xep_0264/stanza.py +36 -0
  62. slidge/slixfix/xep_0264/thumbnail.py +23 -0
  63. slidge/slixfix/xep_0292/__init__.py +5 -0
  64. slidge/slixfix/xep_0292/vcard4.py +100 -0
  65. slidge/slixfix/xep_0313/__init__.py +12 -0
  66. slidge/slixfix/xep_0313/mam.py +262 -0
  67. slidge/slixfix/xep_0313/stanza.py +359 -0
  68. slidge/slixfix/xep_0317/__init__.py +5 -0
  69. slidge/slixfix/xep_0317/hats.py +17 -0
  70. slidge/slixfix/xep_0317/stanza.py +28 -0
  71. slidge/{util → slixfix}/xep_0356_old/privilege.py +9 -7
  72. slidge/slixfix/xep_0424/__init__.py +9 -0
  73. slidge/slixfix/xep_0424/retraction.py +77 -0
  74. slidge/slixfix/xep_0424/stanza.py +28 -0
  75. slidge/slixfix/xep_0490/__init__.py +8 -0
  76. slidge/slixfix/xep_0490/mds.py +47 -0
  77. slidge/slixfix/xep_0490/stanza.py +17 -0
  78. slidge/util/__init__.py +4 -6
  79. slidge/util/archive_msg.py +61 -0
  80. slidge/util/conf.py +206 -0
  81. slidge/util/db.py +57 -76
  82. slidge/util/schema.sql +126 -0
  83. slidge/util/sql.py +508 -0
  84. slidge/util/test.py +215 -25
  85. slidge/util/types.py +177 -4
  86. slidge/util/util.py +225 -59
  87. slidge-0.1.1.dist-info/METADATA +110 -0
  88. slidge-0.1.1.dist-info/RECORD +96 -0
  89. {slidge-0.1.0b2.dist-info → slidge-0.1.1.dist-info}/WHEEL +1 -1
  90. slidge/core/contact.py +0 -891
  91. slidge/core/gateway.py +0 -916
  92. slidge/plugins/discord/__init__.py +0 -90
  93. slidge/plugins/discord/client.py +0 -108
  94. slidge/plugins/discord/session.py +0 -162
  95. slidge/plugins/dummy.py +0 -203
  96. slidge/plugins/facebook.py +0 -493
  97. slidge/plugins/hackernews.py +0 -213
  98. slidge/plugins/mattermost/__init__.py +0 -1
  99. slidge/plugins/mattermost/api.py +0 -280
  100. slidge/plugins/mattermost/gateway.py +0 -365
  101. slidge/plugins/mattermost/websocket.py +0 -252
  102. slidge/plugins/signal/__init__.py +0 -3
  103. slidge/plugins/signal/contact.py +0 -106
  104. slidge/plugins/signal/gateway.py +0 -282
  105. slidge/plugins/signal/session.py +0 -448
  106. slidge/plugins/signal/txt.py +0 -53
  107. slidge/plugins/skype.py +0 -325
  108. slidge/plugins/steam.py +0 -310
  109. slidge/plugins/telegram/__init__.py +0 -5
  110. slidge/plugins/telegram/client.py +0 -228
  111. slidge/plugins/telegram/config.py +0 -12
  112. slidge/plugins/telegram/contact.py +0 -176
  113. slidge/plugins/telegram/gateway.py +0 -150
  114. slidge/plugins/telegram/session.py +0 -256
  115. slidge/util/xep_0030/__init__.py +0 -13
  116. slidge/util/xep_0030/disco.py +0 -811
  117. slidge/util/xep_0030/stanza/__init__.py +0 -7
  118. slidge/util/xep_0030/stanza/info.py +0 -270
  119. slidge/util/xep_0030/stanza/items.py +0 -147
  120. slidge/util/xep_0030/static.py +0 -467
  121. slidge/util/xep_0055/__init__.py +0 -5
  122. slidge/util/xep_0055/search.py +0 -75
  123. slidge/util/xep_0055/stanza.py +0 -10
  124. slidge/util/xep_0077/stanza.py +0 -71
  125. slidge/util/xep_0084/avatar.py +0 -137
  126. slidge/util/xep_0084/stanza.py +0 -104
  127. slidge/util/xep_0115/__init__.py +0 -12
  128. slidge/util/xep_0115/caps.py +0 -379
  129. slidge/util/xep_0115/stanza.py +0 -16
  130. slidge/util/xep_0115/static.py +0 -137
  131. slidge/util/xep_0292/__init__.py +0 -1
  132. slidge/util/xep_0292/stanza.py +0 -167
  133. slidge/util/xep_0292/vcard4.py +0 -75
  134. slidge/util/xep_0333/__init__.py +0 -10
  135. slidge/util/xep_0333/markers.py +0 -96
  136. slidge/util/xep_0333/stanza.py +0 -34
  137. slidge/util/xep_0356/__init__.py +0 -7
  138. slidge/util/xep_0356/permissions.py +0 -35
  139. slidge/util/xep_0356/privilege.py +0 -160
  140. slidge/util/xep_0356/stanza.py +0 -44
  141. slidge/util/xep_0363/__init__.py +0 -16
  142. slidge/util/xep_0363/http_upload.py +0 -215
  143. slidge/util/xep_0363/stanza.py +0 -46
  144. slidge/util/xep_0461/__init__.py +0 -6
  145. slidge/util/xep_0461/reply.py +0 -48
  146. slidge/util/xep_0461/stanza.py +0 -47
  147. slidge-0.1.0b2.dist-info/METADATA +0 -171
  148. slidge-0.1.0b2.dist-info/RECORD +0 -81
  149. /slidge/{plugins/__init__.py → py.typed} +0 -0
  150. /slidge/{util → slixfix}/xep_0077/__init__.py +0 -0
  151. /slidge/{util → slixfix}/xep_0100/__init__.py +0 -0
  152. /slidge/{util → slixfix}/xep_0356_old/__init__.py +0 -0
  153. /slidge/{util → slixfix}/xep_0356_old/stanza.py +0 -0
  154. {slidge-0.1.0b2.dist-info → slidge-0.1.1.dist-info}/LICENSE +0 -0
  155. {slidge-0.1.0b2.dist-info → slidge-0.1.1.dist-info}/entry_points.txt +0 -0
@@ -1,160 +0,0 @@
1
- import logging
2
- import typing
3
- from collections import defaultdict
4
-
5
- from slixmpp import JID, Iq, Message
6
- from slixmpp.plugins.base import BasePlugin
7
- from slixmpp.types import JidStr
8
- from slixmpp.xmlstream import StanzaBase
9
- from slixmpp.xmlstream.handler import Callback
10
- from slixmpp.xmlstream.matcher import StanzaPath
11
-
12
- from . import stanza
13
- from .permissions import MessagePermission, Permissions, RosterAccess
14
-
15
- log = logging.getLogger(__name__)
16
-
17
-
18
- # noinspection PyPep8Naming
19
- class XEP_0356(BasePlugin):
20
- """
21
- XEP-0356: Privileged Entity
22
-
23
- Events:
24
-
25
- ::
26
-
27
- privileges_advertised -- Received message/privilege from the server
28
- """
29
-
30
- name = "xep_0356"
31
- description = "XEP-0356: Privileged Entity (slidge)"
32
- dependencies = {"xep_0297"}
33
- stanza = stanza
34
-
35
- granted_privileges: defaultdict[JidStr, Permissions] = defaultdict(Permissions)
36
-
37
- def plugin_init(self):
38
- if not self.xmpp.is_component:
39
- log.error("XEP 0356 is only available for components")
40
- return
41
-
42
- stanza.register()
43
-
44
- self.xmpp.register_handler(
45
- Callback(
46
- "Privileges",
47
- StanzaPath("message/privilege"),
48
- self._handle_privilege,
49
- )
50
- )
51
-
52
- def plugin_end(self):
53
- self.xmpp.remove_handler("Privileges")
54
-
55
- def _handle_privilege(self, msg: StanzaBase):
56
- """
57
- Called when the XMPP server advertise the component's privileges.
58
-
59
- Stores the privileges in this instance's granted_privileges attribute (a dict)
60
- and raises the privileges_advertised event
61
- """
62
- for perm in msg["privilege"]["perms"]:
63
- setattr(
64
- self.granted_privileges[msg.get_from()], perm["access"], perm["type"]
65
- )
66
- log.debug(f"Privileges: {self.granted_privileges}")
67
- self.xmpp.event("privileges_advertised")
68
-
69
- def send_privileged_message(self, msg: Message):
70
- if self.granted_privileges[msg.get_from().domain].message != MessagePermission.OUTGOING:
71
- raise PermissionError(
72
- "The server hasn't authorized us to send messages on behalf of other users"
73
- )
74
- else:
75
- self._make_privileged_message(msg).send()
76
-
77
- def _make_privileged_message(self, msg: Message):
78
- server = msg.get_from().domain
79
- wrapped = self.xmpp.make_message(mto=server, mfrom=self.xmpp.boundjid.bare)
80
- wrapped["privilege"]["forwarded"].append(msg)
81
- return wrapped
82
-
83
- def _make_get_roster(self, jid: typing.Union[JID, str], **iq_kwargs):
84
- return self.xmpp.make_iq_get(
85
- queryxmlns="jabber:iq:roster",
86
- ifrom=self.xmpp.boundjid.bare,
87
- ito=jid,
88
- **iq_kwargs,
89
- )
90
-
91
- def _make_set_roster(
92
- self,
93
- jid: typing.Union[JID, str],
94
- roster_items: dict,
95
- **iq_kwargs,
96
- ):
97
- iq = self.xmpp.make_iq_set(
98
- ifrom=self.xmpp.boundjid.bare,
99
- ito=jid,
100
- **iq_kwargs,
101
- )
102
- iq["roster"]["items"] = roster_items
103
- return iq
104
-
105
- async def get_roster(self, jid: typing.Union[JID, str], **send_kwargs) -> Iq:
106
- """
107
- Return the roster of user on the server the component has privileged access to.
108
-
109
- Raises ValueError if the server did not advertise the corresponding privileges
110
-
111
- :param jid: user we want to fetch the roster from
112
- """
113
- if isinstance(jid, str):
114
- jid = JID(jid)
115
- if self.granted_privileges[jid.domain].roster not in (
116
- RosterAccess.GET,
117
- RosterAccess.BOTH,
118
- ):
119
- raise PermissionError(
120
- "The server did not grant us privileges to get rosters"
121
- )
122
- else:
123
- return await self._make_get_roster(jid).send(**send_kwargs)
124
-
125
- async def set_roster(
126
- self, jid: typing.Union[JID, str], roster_items: dict, **send_kwargs
127
- ) -> Iq:
128
- """
129
- Return the roster of user on the server the component has privileged access to.
130
-
131
- Raises ValueError if the server did not advertise the corresponding privileges
132
-
133
- :param jid: user we want to add or modify roster items
134
- :param roster_items: a dict containing the roster items' JIDs as keys and
135
- nested dicts containing names, subscriptions and groups.
136
- Example:
137
- {
138
- "friend1@example.com": {
139
- "name": "Friend 1",
140
- "subscription": "both",
141
- "groups": ["group1", "group2"],
142
- },
143
- "friend2@example.com": {
144
- "name": "Friend 2",
145
- "subscription": "from",
146
- "groups": ["group3"],
147
- },
148
- }
149
- """
150
- if isinstance(jid, str):
151
- jid = JID(jid)
152
- if self.granted_privileges[jid.domain].roster not in (
153
- RosterAccess.GET,
154
- RosterAccess.BOTH,
155
- ):
156
- raise PermissionError(
157
- "The server did not grant us privileges to set rosters"
158
- )
159
- else:
160
- return await self._make_set_roster(jid, roster_items).send(**send_kwargs)
@@ -1,44 +0,0 @@
1
- from slixmpp.plugins.xep_0297 import Forwarded
2
- from slixmpp.stanza import Message
3
- from slixmpp.xmlstream import ElementBase, register_stanza_plugin
4
-
5
-
6
- class Privilege(ElementBase):
7
- namespace = "urn:xmpp:privilege:2"
8
- name = "privilege"
9
- plugin_attrib = "privilege"
10
-
11
- def permission(self, access):
12
- for perm in self["perms"]:
13
- if perm["access"] == access:
14
- return perm["type"]
15
-
16
- def roster(self):
17
- return self.permission("roster")
18
-
19
- def message(self):
20
- return self.permission("message")
21
-
22
- def presence(self):
23
- return self.permission("presence")
24
-
25
- def add_perm(self, access, type_):
26
- # This should only be needed for servers, so maybe out of scope for slixmpp
27
- perm = Perm()
28
- perm["type"] = type_
29
- perm["access"] = access
30
- self.append(perm)
31
-
32
-
33
- class Perm(ElementBase):
34
- namespace = "urn:xmpp:privilege:2"
35
- name = "perm"
36
- plugin_attrib = "perm"
37
- plugin_multi_attrib = "perms"
38
- interfaces = {"type", "access"}
39
-
40
-
41
- def register():
42
- register_stanza_plugin(Message, Privilege)
43
- register_stanza_plugin(Privilege, Forwarded)
44
- register_stanza_plugin(Privilege, Perm, iterable=True)
@@ -1,16 +0,0 @@
1
- # slixmpp: The Slick XMPP Library
2
- # Copyright (C) 2018 Emmanuel Gil Peyrot
3
- # This file is part of slixmpp.
4
- # See the file LICENSE for copying permission.
5
- from slixmpp.plugins.base import register_plugin
6
-
7
- from .http_upload import (
8
- XEP_0363,
9
- FileTooBig,
10
- FileUploadError,
11
- HTTPError,
12
- UploadServiceNotFound,
13
- )
14
- from .stanza import Get, Header, Put, Request, Slot
15
-
16
- register_plugin(XEP_0363)
@@ -1,215 +0,0 @@
1
- # slixmpp: The Slick XMPP Library
2
- # Copyright (C) 2018 Emmanuel Gil Peyrot
3
- # This file is part of slixmpp.
4
- # See the file LICENSE for copying permission.
5
-
6
- import logging
7
- import os.path
8
- from asyncio import Future
9
- from mimetypes import guess_type
10
- from pathlib import Path
11
- from typing import IO, Optional, Union
12
-
13
- from aiohttp import ClientSession
14
- from slixmpp import JID, __version__
15
- from slixmpp.plugins import BasePlugin
16
- from slixmpp.plugins.xep_0363 import Get, Header, Put, Request, Slot, stanza
17
- from slixmpp.stanza import Iq
18
- from slixmpp.xmlstream import register_stanza_plugin
19
- from slixmpp.xmlstream.handler import Callback
20
- from slixmpp.xmlstream.matcher import StanzaPath
21
-
22
- log = logging.getLogger(__name__)
23
-
24
- class FileUploadError(Exception):
25
- pass
26
-
27
- class UploadServiceNotFound(FileUploadError):
28
- """
29
- Raised if no upload service can be found.
30
- """
31
-
32
- class FileTooBig(FileUploadError):
33
- """
34
- Raised if the file size is above advertised server limits.
35
-
36
- args:
37
-
38
- - size of the file
39
- - max file size allowed
40
- """
41
- def __str__(self):
42
- return 'File size too large: {} (max: {} bytes)' \
43
- .format(self.args[0], self.args[1])
44
-
45
- class HTTPError(FileUploadError):
46
- """
47
- Raised when we receive an HTTP error response during upload.
48
-
49
- args:
50
-
51
- - HTTP Error code
52
- - Content of the HTTP response
53
- """
54
- def __str__(self):
55
- return 'Could not upload file: %d (%s)' % (self.args[0], self.args[1])
56
-
57
- class XEP_0363(BasePlugin):
58
- """
59
- XEP-0363: HTTP File Upload
60
- """
61
-
62
- name = 'xep_0363'
63
- description = 'XEP-0363: HTTP File Upload'
64
- dependencies = {'xep_0030', 'xep_0128'}
65
- stanza = stanza
66
- default_config = {
67
- 'upload_service': None,
68
- 'max_file_size': float('+inf'),
69
- 'default_content_type': 'application/octet-stream',
70
- }
71
- upload_service : Optional[JID]
72
- max_file_size: float
73
-
74
- def plugin_init(self):
75
- register_stanza_plugin(Iq, Request)
76
- register_stanza_plugin(Iq, Slot)
77
- register_stanza_plugin(Slot, Put)
78
- register_stanza_plugin(Slot, Get)
79
- register_stanza_plugin(Put, Header, iterable=True)
80
-
81
- self.xmpp.register_handler(
82
- Callback('HTTP Upload Request',
83
- StanzaPath('iq@type=get/http_upload_request'),
84
- self._handle_request))
85
-
86
- def plugin_end(self):
87
- self.xmpp.remove_handler('HTTP Upload Request')
88
- self.xmpp['xep_0030'].del_feature(feature=Request.namespace)
89
-
90
- def session_bind(self, jid):
91
- self.xmpp.plugin['xep_0030'].add_feature(Request.namespace)
92
-
93
- def _handle_request(self, iq):
94
- self.xmpp.event('http_upload_request', iq)
95
-
96
- async def find_upload_service(self, domain: Optional[JID] = None, **iqkwargs) -> Optional[Iq]:
97
- """Find an upload service on a domain (our own by default).
98
-
99
- :param domain: Domain to disco to find a service.
100
- """
101
- if domain is None and self.xmpp.is_component:
102
- domain = self.xmpp.server_host
103
-
104
- results = await self.xmpp['xep_0030'].get_info_from_domain(domain=domain)
105
-
106
- candidates = []
107
- for info in results:
108
- if not info['disco_info']:
109
- continue
110
- for identity in info['disco_info']['identities']:
111
- if identity[0] == 'store' and identity[1] == 'file':
112
- candidates.append(info)
113
- for info in candidates:
114
- for feature in info['disco_info']['features']:
115
- if feature == Request.namespace:
116
- return info
117
- else:
118
- return None # for mypy...
119
-
120
- def request_slot(self, jid: JID, filename: Union[Path, str], size: int,
121
- content_type: Optional[str] = None, *,
122
- ifrom: Optional[JID] = None, **iqkwargs) -> Future:
123
- """Request an HTTP upload slot from a service.
124
-
125
- :param jid: Service to request the slot from.
126
- :param filename: Name of the file that will be uploaded.
127
- :param size: size of the file in bytes.
128
- :param content_type: Type of the file that will be uploaded.
129
- """
130
- if ifrom is None:
131
- ifrom = self.xmpp.boundjid
132
- iq = self.xmpp.make_iq_get(ito=jid, ifrom=ifrom)
133
- request = iq['http_upload_request']
134
- request['filename'] = str(filename)
135
- request['size'] = str(size)
136
- request['content-type'] = content_type or self.default_content_type
137
- return iq.send(**iqkwargs)
138
-
139
- async def upload_file(self, filename: Union[Path, str], size: Optional[int] = None,
140
- content_type: Optional[str] = None, *,
141
- input_file: Optional[IO[bytes]]=None,
142
- domain: Optional[JID] = None,
143
- **iqkwargs) -> str:
144
- '''Helper function which does all of the uploading discovery and
145
- process.
146
-
147
- :param filename: Path to the file to upload (or only the name if
148
- ``input_file`` is provided.
149
- :param size: size of the file in bytes.
150
- :param content_type: Type of the file that will be uploaded.
151
- :param input_file: Binary file stream on the file.
152
- :param domain: Domain to query to find an HTTP upload service.
153
- :raises .UploadServiceNotFound: If slixmpp is unable to find an
154
- an available upload service.
155
- :raises .FileTooBig: If the filesize is above what is accepted by
156
- the service.
157
- :raises .HTTPError: If there is an error in the HTTP operation.
158
- :returns: The URL of the uploaded file.
159
- '''
160
- timeout = iqkwargs.get('timeout', None)
161
- if self.upload_service is None:
162
- info_iq = await self.find_upload_service(
163
- domain=domain, **iqkwargs
164
- )
165
- if info_iq is None:
166
- raise UploadServiceNotFound()
167
- self.upload_service = info_iq['from']
168
- for form in info_iq['disco_info'].iterables:
169
- values = form['values']
170
- if values['FORM_TYPE'] == ['urn:xmpp:http:upload:0']:
171
- try:
172
- self.max_file_size = int(values['max-file-size'])
173
- except (TypeError, ValueError):
174
- log.error('Invalid max size received from HTTP File Upload service')
175
- self.max_file_size = float('+inf')
176
- break
177
-
178
- if input_file is None:
179
- input_file = open(filename, 'rb')
180
-
181
- if size is None:
182
- size = input_file.seek(0, 2)
183
- input_file.seek(0)
184
-
185
- if size > self.max_file_size:
186
- raise FileTooBig(size, self.max_file_size)
187
-
188
- if content_type is None:
189
- content_type = guess_type(filename)[0]
190
- if content_type is None:
191
- content_type = self.default_content_type
192
-
193
- basename = os.path.basename(filename)
194
- slot_iq = await self.request_slot(self.upload_service, basename, size,
195
- content_type, **iqkwargs)
196
- slot = slot_iq['http_upload_slot']
197
-
198
- headers = {
199
- 'Content-Length': str(size),
200
- 'Content-Type': content_type or self.default_content_type,
201
- **{header['name']: header['value'] for header in slot['put']['headers']}
202
- }
203
-
204
- # Do the actual upload here.
205
- async with ClientSession(headers={'User-Agent': 'slixmpp ' + __version__}) as session:
206
- response = await session.put(
207
- slot['put']['url'],
208
- data=input_file,
209
- headers=headers,
210
- timeout=timeout)
211
- if response.status >= 400:
212
- raise HTTPError(response.status, await response.text())
213
- log.debug('Response code: %d (%s)', response.status, await response.text())
214
- response.close()
215
- return slot['get']['url']
@@ -1,46 +0,0 @@
1
-
2
- # slixmpp: The Slick XMPP Library
3
- # Copyright (C) 2018 Emmanuel Gil Peyrot
4
- # This file is part of slixmpp.
5
- # See the file LICENSE for copying permission.
6
- from slixmpp.xmlstream import ElementBase
7
-
8
-
9
- class Request(ElementBase):
10
- plugin_attrib = 'http_upload_request'
11
- name = 'request'
12
- namespace = 'urn:xmpp:http:upload:0'
13
- interfaces = {'filename', 'size', 'content-type'}
14
-
15
- class Slot(ElementBase):
16
- plugin_attrib = 'http_upload_slot'
17
- name = 'slot'
18
- namespace = 'urn:xmpp:http:upload:0'
19
-
20
- class Put(ElementBase):
21
- plugin_attrib = 'put'
22
- name = 'put'
23
- namespace = 'urn:xmpp:http:upload:0'
24
- interfaces = {'url'}
25
-
26
- class Get(ElementBase):
27
- plugin_attrib = 'get'
28
- name = 'get'
29
- namespace = 'urn:xmpp:http:upload:0'
30
- interfaces = {'url'}
31
-
32
- class Header(ElementBase):
33
- plugin_attrib = 'header'
34
- name = 'header'
35
- namespace = 'urn:xmpp:http:upload:0'
36
- plugin_multi_attrib = 'headers'
37
- interfaces = {'name', 'value'}
38
-
39
- def get_value(self):
40
- return self.xml.text
41
-
42
- def set_value(self, value):
43
- self.xml.text = value
44
-
45
- def del_value(self):
46
- self.xml.text = ''
@@ -1,6 +0,0 @@
1
- from slixmpp.plugins.base import register_plugin
2
-
3
- from .reply import XEP_0461
4
- from .stanza import *
5
-
6
- register_plugin(XEP_0461)
@@ -1,48 +0,0 @@
1
- from slixmpp.plugins import BasePlugin
2
- from slixmpp.types import JidStr
3
- from slixmpp.xmlstream import StanzaBase
4
- from slixmpp.xmlstream.handler import Callback
5
- from slixmpp.xmlstream.matcher import StanzaPath
6
-
7
- from . import stanza
8
-
9
-
10
- class XEP_0461(BasePlugin):
11
- """XEP-0461: Message Replies"""
12
-
13
- name = "xep_0461"
14
- description = "XEP-0461: Message Replies"
15
-
16
- dependencies = {"xep_0030"}
17
- stanza = stanza
18
- namespace = stanza.NS
19
-
20
- def plugin_init(self) -> None:
21
- stanza.register_plugins()
22
- self.xmpp.register_handler(
23
- Callback(
24
- "Message replied to",
25
- StanzaPath("message/reply"),
26
- self._handle_reply_to_message,
27
- )
28
- )
29
-
30
- def plugin_end(self):
31
- self.xmpp.plugin["xep_0030"].del_feature(feature=stanza.NS)
32
-
33
- def session_bind(self, jid):
34
- self.xmpp.plugin["xep_0030"].add_feature(feature=stanza.NS)
35
-
36
- def _handle_reply_to_message(self, msg: StanzaBase):
37
- self.xmpp.event("message_reply", msg)
38
-
39
- def send_reply(self, reply_to: JidStr, reply_id: str, **msg_kwargs):
40
- """
41
-
42
- :param reply_to: Full JID of the quoted author
43
- :param reply_id: ID of the message to reply to
44
- """
45
- msg = self.xmpp.make_message(**msg_kwargs)
46
- msg["reply"]["to"] = reply_to
47
- msg["reply"]["id"] = reply_id
48
- msg.send()
@@ -1,47 +0,0 @@
1
- from slixmpp.stanza import Message
2
- from slixmpp.xmlstream import ElementBase, register_stanza_plugin
3
-
4
- NS = "urn:xmpp:reply:0"
5
-
6
-
7
- class Reply(ElementBase):
8
- namespace = NS
9
- name = "reply"
10
- plugin_attrib = "reply"
11
- interfaces = {"id", "to"}
12
-
13
-
14
- class FeatureFallBack(ElementBase):
15
- # should also be a multi attrib
16
- namespace = "urn:xmpp:feature-fallback:0"
17
- name = "fallback"
18
- plugin_attrib = "feature_fallback"
19
- interfaces = {"for"}
20
-
21
- def get_stripped_body(self):
22
- # only works for a single fallback_body attrib
23
- start = self["fallback_body"]["start"]
24
- end = self["fallback_body"]["end"]
25
- body = self.parent()["body"]
26
- try:
27
- start = int(start)
28
- end = int(end)
29
- except ValueError:
30
- return body
31
- else:
32
- return body[:start] + body[end:]
33
-
34
-
35
- class FallBackBody(ElementBase):
36
- # According to https://xmpp.org/extensions/inbox/compatibility-fallback.html
37
- # this should be a multi_attrib *but* since it's a protoXEP, we'll see...
38
- namespace = FeatureFallBack.namespace
39
- name = "body"
40
- plugin_attrib = "fallback_body"
41
- interfaces = {"start", "end"}
42
-
43
-
44
- def register_plugins():
45
- register_stanza_plugin(Message, Reply)
46
- register_stanza_plugin(Message, FeatureFallBack)
47
- register_stanza_plugin(FeatureFallBack, FallBackBody)