1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
# Copyright (C) 2018 Philipp Hörist <philipp AT hoerist.com>
#
# This file is part of nbxmpp.
#
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import annotations
from typing import TYPE_CHECKING
from nbxmpp.errors import MalformedStanzaError
from nbxmpp.modules.base import BaseModule
from nbxmpp.modules.bookmarks.util import build_conference_node
from nbxmpp.modules.bookmarks.util import parse_bookmark
from nbxmpp.modules.util import finalize
from nbxmpp.modules.util import raise_if_error
from nbxmpp.namespaces import Namespace
from nbxmpp.protocol import JID
from nbxmpp.protocol import Message
from nbxmpp.protocol import NodeProcessed
from nbxmpp.structs import BookmarkData
from nbxmpp.structs import MessageProperties
from nbxmpp.structs import StanzaHandler
from nbxmpp.task import iq_request_task
if TYPE_CHECKING:
from nbxmpp.client import Client
BOOKMARK_OPTIONS = {
"pubsub#notify_delete": "true",
"pubsub#notify_retract": "true",
"pubsub#persist_items": "true",
"pubsub#max_items": "max",
"pubsub#access_model": "whitelist",
"pubsub#send_last_published_item": "never",
}
class NativeBookmarks(BaseModule):
_depends = {
"retract": "PubSub",
"publish": "PubSub",
"request_items": "PubSub",
}
def __init__(self, client: Client) -> None:
BaseModule.__init__(self, client)
self._client = client
self.handlers = [
StanzaHandler(
name="message",
callback=self._process_pubsub_bookmarks,
ns=Namespace.PUBSUB_EVENT,
priority=16,
),
]
def _process_pubsub_bookmarks(
self, _client: Client, _stanza: Message, properties: MessageProperties
) -> None:
if not properties.is_pubsub_event:
return
if properties.pubsub_event.node != Namespace.BOOKMARKS_1:
return
item = properties.pubsub_event.item
if item is None:
# Retract, Deleted or Purged
return
try:
bookmark_item = parse_bookmark(item)
except MalformedStanzaError as error:
self._log.warning(error)
self._log.warning(error.stanza)
raise NodeProcessed
pubsub_event = properties.pubsub_event._replace(data=bookmark_item)
self._log.info("Received bookmark item from: %s", properties.jid)
self._log.info(bookmark_item)
properties.pubsub_event = pubsub_event
@iq_request_task
def request_bookmarks(self):
_task = yield
items = yield self.request_items(Namespace.BOOKMARKS_1)
raise_if_error(items)
bookmarks: list[BookmarkData] = []
for item in items:
try:
bookmark_item = parse_bookmark(item)
except MalformedStanzaError as error:
self._log.warning(error)
self._log.warning(error.stanza)
continue
bookmarks.append(bookmark_item)
for bookmark in bookmarks:
self._log.info(bookmark)
yield bookmarks
@iq_request_task
def retract_bookmark(self, bookmark_jid: JID):
task = yield
self._log.info("Retract Bookmark: %s", bookmark_jid)
result = yield self.retract(Namespace.BOOKMARKS_1, str(bookmark_jid))
yield finalize(task, result)
@iq_request_task
def store_bookmarks(self, bookmarks: list[BookmarkData]):
_task = yield
self._log.info("Store Bookmarks")
for bookmark in bookmarks:
self.publish(
Namespace.BOOKMARKS_1,
build_conference_node(bookmark),
id_=str(bookmark.jid),
options=BOOKMARK_OPTIONS,
force_node_options=True,
)
yield True
|