From d07083bff6cf6608a5f109372902b966b23f2dc0 Mon Sep 17 00:00:00 2001 From: Goffi Date: Fri, 30 Jun 2017 00:04:47 +0200 Subject: [PATCH] plugin events, invitations + jp (event/create, invitation/invitee/invite): several emails addresses can now be specified for a single invitation: if several addresses are specified, the same invitation (same ID and data) is sent to all the addresses --- frontends/src/jp/cmd_event.py | 7 +++++-- frontends/src/jp/cmd_invitation.py | 10 +++++++--- src/plugins/plugin_exp_events.py | 8 +++++--- src/plugins/plugin_misc_invitations.py | 21 ++++++++++++++++----- 4 files changed, 33 insertions(+), 13 deletions(-) diff --git a/frontends/src/jp/cmd_event.py b/frontends/src/jp/cmd_event.py index 97ad26da..d73bdfc7 100644 --- a/frontends/src/jp/cmd_event.py +++ b/frontends/src/jp/cmd_event.py @@ -204,7 +204,7 @@ class InviteeInvite(base.CommandBase): def add_parser_options(self): self.parser.add_argument("-i", "--item", type=base.unicode_decoder, default=u'', help=_(u"ID of the PubSub Item")) - self.parser.add_argument("-e", "--email", type=base.unicode_decoder, default='', help='email to send the invitation to (if --no-email is set, email will just be saved)') + self.parser.add_argument("-e", "--email", action="append", type=base.unicode_decoder, default=[], help='email(s) to send the invitation to') self.parser.add_argument("-n", "--name", type=base.unicode_decoder, default='', help='name of the invitee') self.parser.add_argument("-N", "--host-name", type=base.unicode_decoder, default='', help='name of the host') self.parser.add_argument("-l", "--lang", type=base.unicode_decoder, default='', help='main language spoken by the invitee') @@ -214,12 +214,15 @@ class InviteeInvite(base.CommandBase): def start(self): common.checkURI(self.args) + email = self.args.email[0] if self.args.email else None + emails_extra = self.args.email[1:] self.host.bridge.eventInvite( self.args.service, self.args.node, self.args.item, - self.args.email, + email, + emails_extra, self.args.name, self.args.host_name, self.args.lang, diff --git a/frontends/src/jp/cmd_invitation.py b/frontends/src/jp/cmd_invitation.py index 345916e9..ba77b8ef 100644 --- a/frontends/src/jp/cmd_invitation.py +++ b/frontends/src/jp/cmd_invitation.py @@ -22,6 +22,7 @@ import base from sat.core.i18n import _ from sat_frontends.jp.constants import Const as C from sat.tools.common.ansi import ANSI as A +from sat.tools.common import data_format from functools import partial __commands__ = ["Invitation"] @@ -38,7 +39,7 @@ class Create(base.CommandBase): self.parser.add_argument("-P", "--password", type=base.unicode_decoder, default='', help='password of the invitee profile/XMPP account (default: generate one)') self.parser.add_argument("-n", "--name", type=base.unicode_decoder, default='', help='name of the invitee') self.parser.add_argument("-N", "--host-name", type=base.unicode_decoder, default='', help='name of the host') - self.parser.add_argument("-e", "--email", type=base.unicode_decoder, default='', help='email to send the invitation to (if --no-email is set, email will just be saved)') + self.parser.add_argument("-e", "--email", action="append", type=base.unicode_decoder, default=[], help='email(s) to send the invitation to (if --no-email is set, email will just be saved)') self.parser.add_argument("--no-email", action="store_true", help='do NOT send invitation email') self.parser.add_argument("-l", "--lang", type=base.unicode_decoder, default='', help='main language spoken by the invitee') self.parser.add_argument("-u", "--url", type=base.unicode_decoder, default='', help='template to construct the URL') @@ -58,20 +59,23 @@ class Create(base.CommandBase): def start(self): extra = dict(self.args.extra) - email = self.args.email + email = self.args.email[0] if self.args.email else None + emails_extra = self.args.email[1:] if self.args.no_email: if email: extra['email'] = email + data_format.iter2dict(u'emails_extra', emails_extra) else: if not email: self.parser.error(_(u'you need to specify an email address to send email invitation')) self.host.bridge.invitationCreate( + email, + emails_extra, self.args.jid, self.args.password, self.args.name, self.args.host_name, - email, self.args.lang, self.args.url, self.args.subject, diff --git a/src/plugins/plugin_exp_events.py b/src/plugins/plugin_exp_events.py index d6d47fb7..e16c2c6c 100755 --- a/src/plugins/plugin_exp_events.py +++ b/src/plugins/plugin_exp_events.py @@ -74,7 +74,7 @@ class Events(object): in_sign='ssa{ss}s', out_sign='', method=self._eventInviteeSet, async=True) - host.bridge.addMethod("eventInvite", ".plugin", in_sign='sssssssssss', out_sign='', + host.bridge.addMethod("eventInvite", ".plugin", in_sign='ssssassssssss', out_sign='', method=self._invite, async=True) @@ -320,10 +320,12 @@ class Events(object): item_elt = pubsub.Item(id=client.jid.userhost(), payload=event_elt) return self._p.publish(client, service, node, items=[item_elt]) - def _invite(self, service, node, id_=NS_EVENT, email=u'', name=u'', host_name=u'', language=u'', url_template=u'', + def _invite(self, service, node, id_=NS_EVENT, email=u'', emails_extra=None, name=u'', host_name=u'', language=u'', url_template=u'', message_subject=u'', message_body=u'', profile_key=C.PROF_KEY_NONE): client = self.host.getClient(profile_key) - kwargs = {u'profile': client.profile} + kwargs = {u'profile': client.profile, + u'emails_extra': [unicode(e) for e in emails_extra] + } for key in ("email", "name", "host_name", "language", "url_template", "message_subject", "message_body"): value = locals()[key] kwargs[key] = unicode(value) diff --git a/src/plugins/plugin_misc_invitations.py b/src/plugins/plugin_misc_invitations.py index 1393daa6..d23d577f 100644 --- a/src/plugins/plugin_misc_invitations.py +++ b/src/plugins/plugin_misc_invitations.py @@ -24,6 +24,7 @@ from sat.core.log import getLogger log = getLogger(__name__) import shortuuid from sat.tools import utils +from sat.tools.common import data_format from twisted.internet import defer from twisted.words.protocols.jabber import jid from twisted.words.protocols.jabber import error @@ -51,7 +52,8 @@ KEY_CREATED = u'created' KEY_LAST_CONNECTION = u'last_connection' KEY_GUEST_PROFILE = u'guest_profile' KEY_PASSWORD = u'password' -EXTRA_RESERVED = {KEY_ID, KEY_JID, KEY_CREATED, u'jid_', u'jid', KEY_LAST_CONNECTION, KEY_GUEST_PROFILE, KEY_PASSWORD} +KEY_EMAILS_EXTRA = u'emails_extra' +EXTRA_RESERVED = {KEY_ID, KEY_JID, KEY_CREATED, u'jid_', u'jid', KEY_LAST_CONNECTION, KEY_GUEST_PROFILE, KEY_PASSWORD, KEY_EMAILS_EXTRA} DEFAULT_SUBJECT = D_(u"You have been invited by {host_name} to {app_name}") DEFAULT_BODY = D_(u"""Hello {name}! @@ -72,7 +74,7 @@ class InvitationsPlugin(object): log.info(_(u"plugin Invitations initialization")) self.host = host self.invitations = persistent.LazyPersistentBinaryDict(u'invitations') - host.bridge.addMethod("invitationCreate", ".plugin", in_sign='sssssssssa{ss}s', out_sign='a{ss}', + host.bridge.addMethod("invitationCreate", ".plugin", in_sign='sasssssssssa{ss}s', out_sign='a{ss}', method=self._create, async=True) host.bridge.addMethod("invitationGet", ".plugin", in_sign='s', out_sign='a{ss}', @@ -90,16 +92,21 @@ class InvitationsPlugin(object): raise ValueError(_(u"You can't use following key(s) in extra, they are reserved: {}").format( u', '.join(EXTRA_RESERVED.intersection(extra)))) - def _create(self, jid_=u'', password=u'', name=u'', host_name=u'', email=u'', language=u'', url_template=u'', message_subject=u'', message_body=u'', extra=None, profile=u''): + def _create(self, email=u'', emails_extra=None, jid_=u'', password=u'', name=u'', host_name=u'', language=u'', url_template=u'', message_subject=u'', message_body=u'', extra=None, profile=u''): # XXX: we don't use **kwargs here to keep arguments name for introspection with D-Bus bridge + if emails_extra is None: + emails_extra = [] if extra is None: extra = {} else: extra = {unicode(k): unicode(v) for k,v in extra.iteritems()} + kwargs = {"extra": extra, + KEY_EMAILS_EXTRA: [unicode(e) for e in emails_extra] + } + # we need to be sure that values are unicode, else they won't be pickled correctly with D-Bus - kwargs = {"extra": extra} for key in ("jid_", "password", "name", "host_name", "email", "language", "url_template", "message_subject", "message_body", "profile"): value = locals()[key] if value: @@ -168,6 +175,9 @@ class InvitationsPlugin(object): self.checkExtra(extra) email = kwargs.pop(u'email', None) + emails_extra = kwargs.pop(u'emails_extra', []) + if not email and emails_extra: + raise ValueError(_(u'You need to provide a main email address before using emails_extra')) if email is not None and not 'url_template' in kwargs and not 'message_body' in kwargs: raise ValueError(_(u"You need to provide url_template if you use default message body")) @@ -248,6 +258,7 @@ class InvitationsPlugin(object): if email is not None: extra[u'email'] = email + data_format.iter2dict(KEY_EMAILS_EXTRA, extra) url_template = kwargs.pop(u'url_template', '') format_args = { u'uuid': id_, @@ -276,7 +287,7 @@ class InvitationsPlugin(object): yield sat_email.sendEmail( self.host, - [email], + [email] + emails_extra, (kwargs.pop(u'message_subject', None) or DEFAULT_SUBJECT).format(**format_args), (kwargs.pop(u'message_body', None) or DEFAULT_BODY).format(**format_args), )