Mercurial > libervia-backend
comparison src/plugins/plugin_xep_0045.py @ 1082:246712d2e7bc
plugin XEP-0045, text_commands: add some commands:
- handle generic failure in text_commands
- fix command /leave and a logging message
- add commands /kick /ban /affiliate
author | souliane <souliane@mailoo.org> |
---|---|
date | Mon, 23 Jun 2014 15:42:56 +0200 |
parents | 1513511a0586 |
children | e8731b02f5ea |
comparison
equal
deleted
inserted
replaced
1081:5d89fecdf667 | 1082:246712d2e7bc |
---|---|
43 "main": "XEP_0045", | 43 "main": "XEP_0045", |
44 "handler": "yes", | 44 "handler": "yes", |
45 "description": _("""Implementation of Multi-User Chat""") | 45 "description": _("""Implementation of Multi-User Chat""") |
46 } | 46 } |
47 | 47 |
48 AFFILIATIONS = ('owner', 'admin', 'member', 'none', 'outcast') | |
49 | |
48 | 50 |
49 class UnknownRoom(Exception): | 51 class UnknownRoom(Exception): |
50 pass | 52 pass |
51 | 53 |
54 | |
52 class NotReadyYet(Exception): | 55 class NotReadyYet(Exception): |
53 pass | 56 pass |
57 | |
54 | 58 |
55 class XEP_0045(object): | 59 class XEP_0045(object): |
56 # TODO: this plugin is messy, need a big cleanup/refactoring | 60 # TODO: this plugin is messy, need a big cleanup/refactoring |
57 | 61 |
58 def __init__(self, host): | 62 def __init__(self, host): |
123 if hasattr(failure.value, "condition") and failure.value.condition == 'conflict': | 127 if hasattr(failure.value, "condition") and failure.value.condition == 'conflict': |
124 # we have a nickname conflict, we try again with "_" suffixed to current nickname | 128 # we have a nickname conflict, we try again with "_" suffixed to current nickname |
125 nick += '_' | 129 nick += '_' |
126 return self.clients[profile].join(room_jid, nick, history_options, password).addCallbacks(self.__room_joined, self.__err_joining_room, callbackKeywords={'profile': profile}, errbackArgs=[room_jid, nick, history_options, password, profile]) | 130 return self.clients[profile].join(room_jid, nick, history_options, password).addCallbacks(self.__room_joined, self.__err_joining_room, callbackKeywords={'profile': profile}, errbackArgs=[room_jid, nick, history_options, password, profile]) |
127 mess = D_("Error while joining the room %s" % room_jid.userhost()) | 131 mess = D_("Error while joining the room %s" % room_jid.userhost()) |
132 try: | |
133 mess += " with condition '%s'" % failure.value.condition | |
134 except AttributeError: | |
135 pass | |
128 log.error(mess) | 136 log.error(mess) |
129 self.host.bridge.newAlert(mess, D_("Group chat error"), "ERROR", profile) | 137 self.host.bridge.newAlert(mess, D_("Group chat error"), "ERROR", profile) |
130 raise failure | 138 raise failure |
131 | 139 |
132 def getRoomsJoined(self, profile_key=C.PROF_KEY_NONE): | 140 def getRoomsJoined(self, profile_key=C.PROF_KEY_NONE): |
373 | 381 |
374 def getHandler(self, profile): | 382 def getHandler(self, profile): |
375 self.clients[profile] = SatMUCClient(self) | 383 self.clients[profile] = SatMUCClient(self) |
376 return self.clients[profile] | 384 return self.clients[profile] |
377 | 385 |
386 def kick(self, nick, room_jid, options={}, profile_key=C.PROF_KEY_NONE): | |
387 """ | |
388 Kick a participant from the room | |
389 @param nick (str): nick of the user to kick | |
390 @param room_jid_s (JID): jid of the room | |
391 @param options (dict): attribute with extra info (reason, password) as in #XEP-0045 | |
392 @param profile_key (str): %(doc_profile_key)s | |
393 """ | |
394 profile = self.host.memory.getProfileName(profile_key) | |
395 if not self.__check_profile(profile): | |
396 raise exceptions.ProfileUnknownError("Unknown or disconnected profile") | |
397 if room_jid.userhost() not in self.clients[profile].joined_rooms: | |
398 raise UnknownRoom("This room has not been joined") | |
399 return self.clients[profile].kick(room_jid, nick, reason=options.get('reason', None)) | |
400 | |
401 def ban(self, entity_jid, room_jid, options={}, profile_key=C.PROF_KEY_NONE): | |
402 """ | |
403 Ban an entity from the room | |
404 @param entity_jid (JID): bare jid of the entity to be banned | |
405 @param room_jid_s (JID): jid of the room | |
406 @param options: attribute with extra info (reason, password) as in #XEP-0045 | |
407 @param profile_key (str): %(doc_profile_key)s | |
408 """ | |
409 assert(not entity_jid.resource) | |
410 assert(not room_jid.resource) | |
411 profile = self.host.memory.getProfileName(profile_key) | |
412 if not self.__check_profile(profile): | |
413 raise exceptions.ProfileUnknownError("Unknown or disconnected profile") | |
414 if room_jid.userhost() not in self.clients[profile].joined_rooms: | |
415 raise UnknownRoom("This room has not been joined") | |
416 return self.clients[profile].ban(room_jid, entity_jid, reason=options.get('reason', None)) | |
417 | |
418 def affiliate(self, entity_jid, room_jid, options=None, profile_key=C.PROF_KEY_NONE): | |
419 """ | |
420 Change the affiliation of an entity | |
421 @param entity_jid (JID): bare jid of the entity | |
422 @param room_jid_s (JID): jid of the room | |
423 @param options: attribute with extra info (reason, nick) as in #XEP-0045 | |
424 @param profile_key (str): %(doc_profile_key)s | |
425 """ | |
426 assert(not entity_jid.resource) | |
427 assert(not room_jid.resource) | |
428 assert('affiliation' in options) | |
429 profile = self.host.memory.getProfileName(profile_key) | |
430 if not self.__check_profile(profile): | |
431 raise exceptions.ProfileUnknownError("Unknown or disconnected profile") | |
432 if room_jid.userhost() not in self.clients[profile].joined_rooms: | |
433 raise UnknownRoom("This room has not been joined") | |
434 # TODO: handles reason and nick | |
435 return self.clients[profile].modifyAffiliationList(room_jid, [entity_jid], options['affiliation']) | |
436 | |
378 # Text commands # | 437 # Text commands # |
379 | 438 |
380 def cmd_nick(self, mess_data, profile): | 439 def cmd_nick(self, mess_data, profile): |
381 """change nickname""" | 440 """change nickname""" |
382 log.debug("Catched nick command") | 441 log.debug("Catched nick command") |
426 return False | 485 return False |
427 | 486 |
428 def cmd_part(self, mess_data, profile): | 487 def cmd_part(self, mess_data, profile): |
429 """just a synonym of /leave""" | 488 """just a synonym of /leave""" |
430 return self.cmd_leave(mess_data, profile) | 489 return self.cmd_leave(mess_data, profile) |
490 | |
491 def cmd_kick(self, mess_data, profile): | |
492 """kick a room member | |
493 | |
494 @command (group): (nick) | |
495 - nick: the nick of the person to kick | |
496 """ | |
497 log.debug("Catched kick command") | |
498 | |
499 if mess_data['type'] != "groupchat": | |
500 self.host.plugins[C.TEXT_CMDS].feedBackWrongContext('kick', 'groupchat', mess_data, profile) | |
501 return False | |
502 | |
503 options = mess_data["unparsed"].strip().split() | |
504 try: | |
505 nick = options[0] | |
506 assert(self.isNickInRoom(mess_data["to"], nick, profile)) | |
507 except (IndexError, AssertionError): | |
508 feedback = _(u"You must provide a member's nick to kick.") | |
509 self.host.plugins[C.TEXT_CMDS].feedBack(feedback, mess_data, profile) | |
510 return False | |
511 | |
512 d = self.kick(nick, mess_data["to"], {} if len(options) == 1 else {'reason': options[1]}, profile) | |
513 | |
514 def cb(dummy): | |
515 mess_data['message'] = _('%s has been kicked') % nick | |
516 if len(options) > 1: | |
517 mess_data['message'] += _(' for the following reason: %s') % options[1] | |
518 return True | |
519 d.addCallback(cb) | |
520 return d | |
521 | |
522 def cmd_ban(self, mess_data, profile): | |
523 """ban an entity from the room | |
524 | |
525 @command (group): (JID) [reason] | |
526 - JID: the JID of the entity to ban | |
527 - reason: the reason why this entity is being banned | |
528 """ | |
529 log.debug("Catched ban command") | |
530 | |
531 if mess_data['type'] != "groupchat": | |
532 self.host.plugins[C.TEXT_CMDS].feedBackWrongContext('ban', 'groupchat', mess_data, profile) | |
533 return False | |
534 | |
535 options = mess_data["unparsed"].strip().split() | |
536 try: | |
537 jid_s = options[0] | |
538 entity_jid = jid.JID(jid_s).userhostJID() | |
539 assert(entity_jid.user) | |
540 assert(entity_jid.host) | |
541 except (IndexError, jid.InvalidFormat, AssertionError): | |
542 feedback = _(u"You must provide a valid JID to ban, like in '/ban contact@example.net'") | |
543 self.host.plugins[C.TEXT_CMDS].feedBack(feedback, mess_data, profile) | |
544 return False | |
545 | |
546 d = self.ban(entity_jid, mess_data["to"], {} if len(options) == 1 else {'reason': options[1]}, profile) | |
547 | |
548 def cb(dummy): | |
549 mess_data['message'] = _('%s has been banned') % entity_jid | |
550 if len(options) > 1: | |
551 mess_data['message'] += _(' for the following reason: %s') % options[1] | |
552 return True | |
553 d.addCallback(cb) | |
554 return d | |
555 | |
556 def cmd_affiliate(self, mess_data, profile): | |
557 """affiliate an entity to the room | |
558 | |
559 @command (group): (JID) [owner|admin|member|none|outcast] | |
560 - JID: the JID of the entity to affiliate | |
561 - owner: grant owner privileges | |
562 - admin: grant admin privileges | |
563 - member: grant member privileges | |
564 - none: reset entity privileges | |
565 - outcast: ban entity | |
566 """ | |
567 log.debug("Catched affiliate command") | |
568 | |
569 if mess_data['type'] != "groupchat": | |
570 self.host.plugins[C.TEXT_CMDS].feedBackWrongContext('affiliate', 'groupchat', mess_data, profile) | |
571 return False | |
572 | |
573 options = mess_data["unparsed"].strip().split() | |
574 try: | |
575 jid_s = options[0] | |
576 entity_jid = jid.JID(jid_s).userhostJID() | |
577 assert(entity_jid.user) | |
578 assert(entity_jid.host) | |
579 except (IndexError, jid.InvalidFormat, AssertionError): | |
580 feedback = _(u"You must provide a valid JID to affiliate, like in '/affiliate contact@example.net member'") | |
581 self.host.plugins[C.TEXT_CMDS].feedBack(feedback, mess_data, profile) | |
582 return False | |
583 | |
584 affiliation = options[1] if len(options) > 1 else 'none' | |
585 if affiliation not in AFFILIATIONS: | |
586 feedback = _(u"You must provide a valid affiliation: %s") % ' '.join(AFFILIATIONS) | |
587 self.host.plugins[C.TEXT_CMDS].feedBack(feedback, mess_data, profile) | |
588 return False | |
589 | |
590 d = self.affiliate(entity_jid, mess_data["to"], {'affiliation': affiliation}, profile) | |
591 | |
592 def cb(dummy): | |
593 mess_data['message'] = _('New affiliation for %(entity)s: %(affiliation)s') % {'entity': entity_jid, 'affiliation': affiliation} | |
594 return True | |
595 d.addCallback(cb) | |
596 return d | |
431 | 597 |
432 def cmd_title(self, mess_data, profile): | 598 def cmd_title(self, mess_data, profile): |
433 """change room's subject""" | 599 """change room's subject""" |
434 log.debug("Catched title command") | 600 log.debug("Catched title command") |
435 | 601 |
528 if user.nick == room.nick: | 694 if user.nick == room.nick: |
529 # we left the room | 695 # we left the room |
530 room_jid_s = room.roomJID.userhost() | 696 room_jid_s = room.roomJID.userhost() |
531 log.info(_("Room [%(room)s] left (%(profile)s))") % {"room": room_jid_s, | 697 log.info(_("Room [%(room)s] left (%(profile)s))") % {"room": room_jid_s, |
532 "profile": self.parent.profile}) | 698 "profile": self.parent.profile}) |
533 self.host.memory.delEntityCache(room.roomJID, self.parent.profile) | 699 self.host.memory.delEntityCache(room.roomJID, profile_key=self.parent.profile) |
534 del self.plugin_parent.clients[self.parent.profile].joined_rooms[room_jid_s] | 700 del self.plugin_parent.clients[self.parent.profile].joined_rooms[room_jid_s] |
535 self.host.bridge.roomLeft(room.roomJID.userhost(), self.parent.profile) | 701 self.host.bridge.roomLeft(room.roomJID.userhost(), self.parent.profile) |
536 else: | 702 else: |
537 log.debug(_("user %(nick)s left room (%(room_id)s)") % {'nick': user.nick, 'room_id': room.occupantJID.userhost()}) | 703 log.debug(_("user %(nick)s left room (%(room_id)s)") % {'nick': user.nick, 'room_id': room.occupantJID.userhost()}) |
538 user_data = {'entity': user.entity.full() if user.entity else '', 'affiliation': user.affiliation, 'role': user.role} | 704 user_data = {'entity': user.entity.full() if user.entity else '', 'affiliation': user.affiliation, 'role': user.role} |