3462
+ − 1 #!/usr/bin/env python3
+ − 2
+ − 3 # SàT plugin to send invitations for Pubsub
+ − 4 # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org)
+ − 5
+ − 6 # This program is free software: you can redistribute it and/or modify
+ − 7 # it under the terms of the GNU Affero General Public License as published by
+ − 8 # the Free Software Foundation, either version 3 of the License, or
+ − 9 # (at your option) any later version.
+ − 10
+ − 11 # This program is distributed in the hope that it will be useful,
+ − 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
+ − 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ − 14 # GNU Affero General Public License for more details.
+ − 15
+ − 16 # You should have received a copy of the GNU Affero General Public License
+ − 17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
+ − 18
+ − 19 from typing import Optional
+ − 20 from twisted.internet import defer
+ − 21 from twisted.words.protocols.jabber import jid
+ − 22 from twisted.words.xish import domish
+ − 23 from sat.core.i18n import _
+ − 24 from sat.core.constants import Const as C
+ − 25 from sat.core.log import getLogger
+ − 26 from sat.core.xmpp import SatXMPPEntity
+ − 27 from sat.tools import utils
+ − 28 from sat.tools.common import data_format
+ − 29
+ − 30 log = getLogger ( __name__ )
+ − 31
+ − 32
+ − 33 PLUGIN_INFO = {
+ − 34 C . PI_NAME : "Pubsub Invitation" ,
+ − 35 C . PI_IMPORT_NAME : "PUBSUB_INVITATION" ,
+ − 36 C . PI_TYPE : "EXP" ,
+ − 37 C . PI_PROTOCOLS : [],
+ − 38 C . PI_DEPENDENCIES : [ "XEP-0060" , "INVITATION" ],
+ − 39 C . PI_RECOMMENDATIONS : [],
+ − 40 C . PI_MAIN : "PubsubInvitation" ,
+ − 41 C . PI_HANDLER : "no" ,
+ − 42 C . PI_DESCRIPTION : _ ( "Invitations for pubsub based features" ),
+ − 43 }
+ − 44
+ − 45
+ − 46 class PubsubInvitation :
+ − 47
+ − 48 def __init__ ( self , host ):
+ − 49 log . info ( _ ( "Pubsub Invitation plugin initialization" ))
+ − 50 self . host = host
+ − 51 self . _p = host . plugins [ "XEP-0060" ]
+ − 52 # namespace to handler map
+ − 53 self . _ns_handler = {}
+ − 54 host . bridge . addMethod (
+ − 55 "psInvite" ,
+ − 56 ".plugin" ,
+ − 57 in_sign = "sssssss" ,
+ − 58 out_sign = "" ,
+ − 59 method = self . _sendPubsubInvitation ,
+ − 60 async_ = True
+ − 61 )
+ − 62
+ − 63 def register (
+ − 64 self ,
+ − 65 namespace : str ,
+ − 66 handler
+ − 67 ) -> None :
+ − 68 self . _ns_handler [ namespace ] = handler
+ − 69 self . host . plugins [ "INVITATION" ] . registerNamespace ( namespace , self . onInvitation )
+ − 70
+ − 71 def _sendPubsubInvitation (
+ − 72 self , invitee_jid_s , service_s , node , item_id = None ,
+ − 73 name = None , extra_s = '' , profile_key = C . PROF_KEY_NONE ):
+ − 74 client = self . host . getClient ( profile_key )
+ − 75 invitee_jid = jid . JID ( invitee_jid_s )
+ − 76 service = jid . JID ( service_s )
+ − 77 extra = data_format . deserialise ( extra_s )
+ − 78 return defer . ensureDeferred (
+ − 79 self . invite (
+ − 80 client ,
+ − 81 invitee_jid ,
+ − 82 service ,
+ − 83 node ,
+ − 84 item_id or None ,
+ − 85 name = name or None ,
+ − 86 extra = extra
+ − 87 )
+ − 88 )
+ − 89
+ − 90 async def invite (
+ − 91 self ,
+ − 92 client : SatXMPPEntity ,
+ − 93 invitee_jid : jid . JID ,
+ − 94 service : jid . JID ,
+ − 95 node : str ,
+ − 96 item_id : Optional [ str ] = None ,
+ − 97 name : str = '' ,
+ − 98 extra : Optional [ dict ] = None ,
+ − 99 ) -> None :
+ − 100 if extra is None :
+ − 101 extra = {}
+ − 102 else :
+ − 103 namespace = extra . get ( "namespace" )
+ − 104 if namespace :
+ − 105 try :
+ − 106 handler = self . _ns_handler [ namespace ]
+ − 107 preflight = handler . invitePreflight
+ − 108 except KeyError :
+ − 109 pass
+ − 110 except AttributeError :
+ − 111 log . debug ( f "no invitePreflight method found for { namespace !r} " )
+ − 112 else :
+ − 113 await utils . asDeferred (
+ − 114 preflight ,
+ − 115 client , invitee_jid , service , node , item_id , name , extra
+ − 116 )
+ − 117 if item_id is None :
+ − 118 item_id = extra . pop ( "default_item_id" , None )
+ − 119
+ − 120 # we authorize our invitee to see the nodes of interest
+ − 121 await self . _p . setNodeAffiliations ( client , service , node , { invitee_jid : "member" })
+ − 122 log . debug ( f "affiliation set on { service } 's { node !r} node" )
+ − 123
+ − 124 # now we send the invitation
+ − 125 self . host . plugins [ "INVITATION" ] . sendPubsubInvitation (
+ − 126 client ,
+ − 127 invitee_jid ,
+ − 128 service ,
+ − 129 node ,
+ − 130 item_id ,
+ − 131 name = name or None ,
+ − 132 extra = extra
+ − 133 )
+ − 134
+ − 135 async def onInvitation (
+ − 136 self ,
+ − 137 client : SatXMPPEntity ,
+ − 138 namespace : str ,
+ − 139 name : str ,
+ − 140 extra : dict ,
+ − 141 service : jid . JID ,
+ − 142 node : str ,
+ − 143 item_id : Optional [ str ],
+ − 144 item_elt : domish . Element
+ − 145 ) -> None :
+ − 146 if extra is None :
+ − 147 extra = {}
+ − 148 try :
+ − 149 handler = self . _ns_handler [ namespace ]
+ − 150 preflight = handler . onInvitationPreflight
+ − 151 except KeyError :
+ − 152 pass
+ − 153 except AttributeError :
+ − 154 log . debug ( f "no onInvitationPreflight method found for { namespace !r} " )
+ − 155 else :
+ − 156 await utils . asDeferred (
+ − 157 preflight ,
+ − 158 client , namespace , name , extra , service , node , item_id , item_elt
+ − 159 )
+ − 160 if item_id is None :
+ − 161 item_id = extra . pop ( "default_item_id" , None )
+ − 162 creator = extra . pop ( "creator" , False )
+ − 163 element = extra . pop ( "element" , None )
+ − 164 if not name :
+ − 165 name = extra . pop ( "name" , "" )
+ − 166
+ − 167 return self . host . plugins [ 'LIST_INTEREST' ] . registerPubsub (
+ − 168 client , namespace , service , node , item_id , creator ,
+ − 169 name , element , extra )