-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathmuc.py
203 lines (157 loc) · 6.76 KB
/
muc.py
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
"""
Ludolph: Monitoring Jabber bot
Copyright (C) 2015-2017 Erigones, s. r. o.
This file is part of Ludolph.
See the file LICENSE for copying permission.
"""
import logging
from sleekxmpp.exceptions import IqError
from ludolph import __version__
from ludolph.command import CommandError, PermissionDenied, command
from ludolph.web import webhook, request, abort
from ludolph.plugins.plugin import LudolphPlugin
logger = logging.getLogger(__name__)
class Muc(LudolphPlugin):
"""
Multi-user chat room commands.
"""
__version__ = __version__
room_motd = None
salutations = True
persistent_attrs = ('room_motd',)
def __init__(self, xmpp, config, reinit=False, **kwargs):
"""Do not load the plugin if the room option is disabled"""
if not xmpp.room:
raise RuntimeError('Multi-user chat support is disabled in config file')
super(Muc, self).__init__(xmpp, config, reinit=reinit, **kwargs)
def __post_init__(self):
# Process config file
self.salutations = self.get_boolean_value(self.config.get('salutations', True))
if self.room_motd is None:
self.room_motd = self.config.get('motd', None)
# Register event handlers for entering and leaving the MUC room
self.xmpp.register_event_handler('muc_user_online', self._room_joined)
self.xmpp.register_event_handler('muc_user_offline', self._room_left)
def __destroy__(self):
# Deregister event handlers for entering and leaving the MUC room
self.xmpp.deregister_event_handler('muc_user_online', self._room_joined)
self.xmpp.deregister_event_handler('muc_user_offline', self._room_left)
def _room_joined(self, presence):
"""Process an online event stanza from a chat room"""
muc = presence['muc']
if self.salutations:
self.xmpp.msg_send(presence['from'].bare, 'Hello %s!' % muc['nick'], mtype='groupchat')
if self.room_motd is not None:
# Send motd to new user
logger.info('Sending motd to incoming MUC room user "%s" via private MUC message', muc['jid'])
self._send_private_msg(presence['from'], self.room_motd, msubject='Message of the day')
def _room_left(self, presence):
"""Process an offline presence stanza from a chat room"""
muc = presence['muc']
if self.salutations:
self.xmpp.msg_send(presence['from'].bare, 'Bye bye %s' % muc['nick'], mtype='groupchat')
def _get_room_jid(self, nick):
"""Return room JID"""
return '%s/%s' % (self.xmpp.room, nick)
def _get_nick(self, user):
"""Get nick from JID or nick and check if user is in chat room"""
nick = None
if '@' in user:
nick = self.xmpp.get_room_nick(user)
elif self.xmpp.is_nick_in_room(user):
nick = user
return nick
def _send_private_msg(self, mto, mbody, msubject=None):
"""Send private message"""
return self.xmpp.msg_send(mto, mbody, mfrom=self.xmpp.boundjid.full, mtype='chat', msubject=msubject)
def _set_room_subject(self, text, mfrom=None):
"""Set room subject"""
msg = self.xmpp.client.Message()
msg['to'] = self.xmpp.room
msg['from'] = mfrom
msg['type'] = 'groupchat'
# noinspection PyProtectedMember
msg._set_sub_text('subject', text or '', keep=True)
try:
msg.send()
except IqError as e:
raise CommandError('Room topic update failed: __%s__' % getattr(e, 'condition', str(e)))
@command(user_required=False, room_user_required=True)
def invite(self, msg, user=None):
"""
Invite user or yourself to multi-user chat room.
Usage: invite [JID]
"""
if not user:
user = self.xmpp.get_jid(msg)
if not self.xmpp.is_jid_room_user(user):
raise CommandError('User **%s** is not allowed to access the MUC room' % user)
self.xmpp.muc.invite(self.xmpp.room, user)
return 'Inviting **%s** to MUC room %s' % (user, self.xmpp.room)
# noinspection PyUnusedLocal
@command(user_required=False, room_user_required=True, room_admin_required=True)
def kick(self, msg, user):
"""
Kick user from multi-user chat room (room admin only).
Usage: kick <JID>
"""
nick = self._get_nick(user)
if not nick:
raise CommandError('User **%s** is not in MUC room' % user)
try:
self.xmpp.muc.setRole(self.xmpp.room, nick, 'none')
except (IqError, ValueError) as e:
err = getattr(e, 'condition', str(e))
raise CommandError('User **%s** could not be kicked from MUC room: __%s__' % (user, err))
return 'User **%s** kicked from MUC room' % user
@command(user_required=False, room_user_required=True)
def motd(self, msg, action=None, text=None):
"""
Show, set or remove message of the day.
Show message of the day (room user only).
Usage: motd
Set message of the day (room admin only).
Usage: motd set <text>
Delete message of the day and disable automatic announcements (room admin only).
Usage: motd del
"""
if action:
if not self.xmpp.is_jid_room_admin(self.xmpp.get_jid(msg)):
raise PermissionDenied
if action == 'del':
self.room_motd = None
return 'MOTD successfully deleted'
elif action == 'set':
if not text:
raise CommandError('Missing text')
# Get original version from message body (strip command and sub-command)
self.room_motd = msg['body'].lstrip().split(None, 2)[-1]
# Announce new motd into room
self.xmpp.msg_send(self.xmpp.room, self.room_motd, mtype='groupchat')
return 'MOTD successfully updated'
else:
raise CommandError('Invalid action')
if self.room_motd is None:
return '(MOTD disabled)'
else:
return self.room_motd
# noinspection PyUnusedLocal
@command(user_required=False, room_admin_required=True)
def topic(self, msg, text=''):
"""
Set room subject (room admin only).
Usage: topic [text]
"""
self._set_room_subject(text)
return 'Room topic updated'
@webhook('/room', methods=('POST',))
def roomtalk(self):
"""
Send message to chat room.
"""
msg = request.forms.get('msg', None)
if not msg:
logger.warning('Missing msg parameter in room request')
abort(400, 'Missing msg parameter')
self.xmpp.msg_send(self.xmpp.room, msg, mtype='groupchat')
return 'Message sent'