comparison sat/tools/common/data_objects.py @ 3310:e4121a1f2399

tools (common/data_objects): removed deprecated code: `BlogItem`, `BlogItems` and `parsePubSubMetadata` are not needed anymore with the new blog data serialisation.
author Goffi <goffi@goffi.org>
date Thu, 16 Jul 2020 09:07:26 +0200
parents 9f0e28137cd0
children be6d91572633
comparison
equal deleted inserted replaced
3309:71761e9fb984 3310:e4121a1f2399
1 #!/usr/bin/env python3 1 #!/usr/bin/env python3
2 2
3 3 # SàT: an XMPP client
4 # SAT: a jabber client
5 # Copyright (C) 2009-2020 Jérôme Poisson (goffi@goffi.org) 4 # Copyright (C) 2009-2020 Jérôme Poisson (goffi@goffi.org)
6 5
7 # This program is free software: you can redistribute it and/or modify 6 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU Affero General Public License as published by 7 # it under the terms of the GNU Affero General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or 8 # the Free Software Foundation, either version 3 of the License, or
30 29
31 from sat.tools.common import uri as xmpp_uri 30 from sat.tools.common import uri as xmpp_uri
32 import urllib.request, urllib.parse, urllib.error 31 import urllib.request, urllib.parse, urllib.error
33 32
34 q = lambda value: urllib.parse.quote(value.encode("utf-8"), safe="@") 33 q = lambda value: urllib.parse.quote(value.encode("utf-8"), safe="@")
35
36
37 def parsePubSubMetadata(metadata, items):
38 """Helper method to have nicer metadata while doing a PubSub request
39
40 The "rsm_index" and "rsm_count" keys will be converted to int
41 The "mam_stable" and "mam_complete" keys will be converted to boolean
42 A "complete" key can have the following values:
43 - True: we are on the last page, i.e. last items have been received
44 - False: we are not on the last page
45 - None: we don't have enough data fo know our position in the pagination
46 @param metadata(dict): dict retrieved fro bridge with request metadata
47 @param items(list): items retrieved (used to determine "complete" value)
48 @return (dict): parsed metadata
49 """
50 data = {}
51 assert "complete" not in metadata
52
53 for key, value in metadata.items():
54 if key in ("rsm_index", "rsm_count"):
55 value = int(value)
56 elif key == "mam_stable":
57 value = C.bool(value)
58 elif key == "mam_complete":
59 key = "complete"
60 value = C.bool(value)
61 data[key] = value
62 if "complete" not in data:
63 index = data.get("rsm_index")
64 count = data.get("rsm_count")
65 if index is None or count is None:
66 # we don't have enough information to know if the data is complete or not
67 data["complete"] = None
68 else:
69 # normally we have a strict equality here but XEP-0059 states
70 # that index MAY be approximative, so just in case…
71 data["complete"] = index + len(items) >= count
72 return data
73
74
75 class BlogItem(object):
76 def __init__(self, mb_data, parent, deserialise=True):
77 """
78 @param deserialise(bool): if True, mb_data is a serialised string which must
79 be deserialised
80 """
81 # FIXME: deserialise should not be done here, but before BlogItem is called
82 if deserialise:
83 self.mb_data = data_format.deserialise(mb_data)
84 else:
85 self.mb_data = mb_data
86 self.parent = parent
87 self._comments = None
88 self._comments_items_list = None
89
90 def json(self):
91 ret = {}
92 for attr in (
93 "id", "atom_id", "uri", "published", "updated", "language", "author",
94 "author_jid", "author_jid_verified", "author_email", "tags", "groups",
95 "title", "title_xhtml", "content", "content_xhtml", "comments",
96 "comments_service", "comments_node", "comments_items_list"
97 ):
98 value = getattr(self, attr)
99 if value is not None:
100 ret[attr] = value
101 return ret
102
103 @property
104 def id(self):
105 return self.mb_data.get("id")
106
107 @property
108 def atom_id(self):
109 return self.mb_data.get("atom_id")
110
111 @property
112 def uri(self):
113 node = self.parent.node
114 service = self.parent.service
115 return xmpp_uri.buildXMPPUri(
116 "pubsub", subtype="microblog", path=service, node=node, item=self.id
117 )
118
119 @property
120 def published(self):
121 return self.mb_data.get("published")
122
123 @property
124 def updated(self):
125 return self.mb_data.get("updated")
126
127 @property
128 def language(self):
129 return self.mb_data.get("language")
130
131 @property
132 def author(self):
133 return self.mb_data.get("author")
134
135 @property
136 def author_jid(self):
137 return self.mb_data.get("author_jid")
138
139 @property
140 def author_jid_verified(self):
141 return self.mb_data.get("author_jid_verified")
142
143 @property
144 def author_email(self):
145 return self.mb_data.get("author_email")
146
147 @property
148 def tags(self):
149 return self.mb_data.get('tags', [])
150
151 @property
152 def groups(self):
153 return self.mb_data.get('groups', [])
154
155 @property
156 def title(self):
157 return self.mb_data.get("title")
158
159 @property
160 def title_xhtml(self):
161 try:
162 return safe(self.mb_data["title_xhtml"])
163 except KeyError:
164 return None
165
166 @property
167 def content(self):
168 return self.mb_data.get("content")
169
170 @property
171 def content_xhtml(self):
172 try:
173 return safe(self.mb_data["content_xhtml"])
174 except KeyError:
175 return None
176
177 @property
178 def comments(self):
179 if self._comments is None:
180 self._comments = data_format.dict2iterdict(
181 "comments", self.mb_data, ("node", "service")
182 )
183 return self._comments
184
185 @property
186 def comments_service(self):
187 return self.mb_data.get("comments_service")
188
189 @property
190 def comments_node(self):
191 return self.mb_data.get("comments_node")
192
193 @property
194 def comments_items_list(self):
195 return [] if self._comments_items_list is None else self._comments_items_list
196
197 def appendCommentsItems(self, items):
198 """append comments items to self.comments_items"""
199 if self._comments_items_list is None:
200 self._comments_items_list = []
201 self._comments_items_list.append(items)
202
203
204 class BlogItems(object):
205 def __init__(self, mb_data, deserialise=True):
206 """
207 @param deserialise(bool): if True, mb_data is a serialised string which must
208 be deserialised
209 """
210 # FIXME: deserialise should not be done here, but before BlogItem is called
211 self.items = [BlogItem(i, self, deserialise=deserialise) for i in mb_data[0]]
212 self.metadata = parsePubSubMetadata(mb_data[1], self.items)
213
214 def json(self):
215 ret = {
216 "items": [i.json() for i in self.items],
217 }
218 for attr in ("service", "node", "uri", "with_rsm"):
219 ret[attr] = getattr(self, attr)
220 if self.with_rsm:
221 for attr in ("rsm_first", "rsm_last", "rsm_index", "rsm_count", "complete"):
222 ret[attr] = getattr(self, attr)
223
224 return ret
225
226 @property
227 def service(self):
228 return self.metadata["service"]
229
230 @property
231 def node(self):
232 return self.metadata["node"]
233
234 @property
235 def uri(self):
236 return self.metadata["uri"]
237
238 @property
239 def with_rsm(self):
240 """Return True if RSM is activated on this request"""
241 return "rsm_first" in self.metadata
242
243 @property
244 def rsm_first(self):
245 return self.metadata["rsm_first"]
246
247 @property
248 def rsm_last(self):
249 return self.metadata["rsm_last"]
250
251 @property
252 def rsm_index(self):
253 return self.metadata["rsm_index"]
254
255 @property
256 def rsm_count(self):
257 return self.metadata["rsm_count"]
258
259 @property
260 def complete(self):
261 return self.metadata["complete"]
262
263 def __len__(self):
264 return self.items.__len__()
265
266 def __missing__(self, key):
267 return self.items.__missing__(key)
268
269 def __getitem__(self, key):
270 return self.items.__getitem__(key)
271
272 def __iter__(self):
273 return self.items.__iter__()
274
275 def __reversed__(self):
276 return self.items.__reversed__()
277
278 def __contains__(self, item):
279 return self.items.__contains__(item)
280 34
281 35
282 class Message(object): 36 class Message(object):
283 def __init__(self, msg_data): 37 def __init__(self, msg_data):
284 self._uid = msg_data[0] 38 self._uid = msg_data[0]