def xmppBrute0x00(ip, usernames, passwords, port, delay): #client = Client(str(ip)) #client.connect(server=(str(ip), port)) found = False for username in usernames: for password in passwords: try: client = Client(username, password) client.connect((str(ip), port)) if client.auth(username, password): client.sendInitPresence() found = True data = username + " : " + password save_data(database, module, lvl1, lvl2, lvl3, name, data) print(G + ' [+] Username: %s | Password found: %s\n' % (username, password)) client.disconnect() except Exception as e: print(R + " [-] Error caught! Name: " + str(e)) except KeyboardInterrupt: client.disconnect() if not found: data = "Nothing found." save_data(database, module, lvl1, lvl2, lvl3, name, data) sys.exit(1) except Exception: print(GR + " [*] Checking : " + C + "Username: {} | ".format(username) + B + "Password: {} ".format(password) + R + "| Incorrect!\n") sleep(delay) if not found: data = "Nothing found." save_data(database, module, lvl1, lvl2, lvl3, name, data)
def __init__(self): ClientXMPP.__init__(self, FCM_JID, FCM_SERVER_KEY, sasl_mech="PLAIN") self.add_event_handler("session_start", self.start) self.auto_reconnect = False self.connect((FCM_SERVER_IP, FCM_SERVER_PORT), use_tls=True, reattempt=True) print("Connected!!") self.process(block=True) print("Process Done!!")
def __init__(self, *args): ConfigurableComponent.__init__(self, "XMPPBOT", *args) if self.config.get('password', None) is None: self.config.password = std_uuid() self.config.save() ClientXMPP.__init__(self, self.config.jid, self.config.password) self.add_event_handler("session_start", self.session_start) self.add_event_handler("message", self.message) # Discard SSL Error self.add_event_handler("ssl_invalid_cert", self.discard) # If you wanted more functionality, here's how to register plugins: # self.register_plugin('xep_0030') # Service Discovery # self.register_plugin('xep_0199') # XMPP Ping # Here's how to access plugins once you've registered them: # self['xep_0030'].add_feature('echo_demo') # If you are working with an OpenFire server, you will # need to use a different SSL version: # import ssl # self.ssl_version = ssl.PROTOCOL_SSLv3 import ssl self.ssl_version = ssl.PROTOCOL_SSLv23 self.log('Connecting bot to ejabberd') self.connect(use_tls=True) self.log('Processing ejabberd connection') self.process(block=False) self.auto_authorize = True self.auto_subscribe = True self.send_presence(pfrom='claptrap@localhost', pstatus='Curiouser and curiouser!', pshow='xa') self.fireEvent(cli_register_event('test_xmpp_send', cli_test_xmpp_send)) self.log("Started")
def __init__(self, active_alerter, alerter_model): ''' Constructor :param active_alerter: The parent alerter for the chat :param alerter_model: The database alerter model associated with the bot ''' # Initialises the connection ClientXMPP.__init__(self, '{}@{}/{}'.format(alerter_model.username, Constants.CHAT_SERVER, Constants.CHAT_RESOURCE), 'AIR_{}'.format(alerter_model.password)) # Automatically add new friends? self.auto_authorize = None self.auto_subscribe = True self.auto_reconnect = True self.ssl_version = ssl.PROTOCOL_SSLv3 # Add the event handlers self.add_event_handler('session_start', self.session_start) self.add_event_handler('message', self.got_message) self.add_event_handler('got_online', self.got_online) self.add_event_handler('got_offline', self.got_offline) self.add_event_handler('presence_subscribe', self.presence_subscribe) self.add_event_handler('presence_unsubscribe', self.presence_unsubscribe) self.add_event_handler('disconnected', self.disconnected) self.add_event_handler('failed_auth', self.failed_auth) # Presence change events self.add_event_handler('presence_available', self.handle_presence) self.add_event_handler('presence_dnd', self.handle_presence) self.add_event_handler('presence_xa', self.handle_presence) self.add_event_handler('presence_chat', self.handle_presence) self.add_event_handler('presence_away', self.handle_presence) self.alerter = active_alerter self.model = alerter_model
def connect(self): """Perform a connection to the server. This function is designed to work internally, but calls to connect handlers when connection is sucessful. """ if self.client: return self.client self.client = ClientXMPP(self.jid, self.password) # Install event handlers self.client.add_event_handler("groupchat_message", self.handle_muc_message) self.client.add_event_handler("session_start", self.handle_session_start) self.client.add_event_handler("message", self.handle_message) self.client.add_event_handler("changed_status", self.handle_changed_status) if self.ignore_ssl_cert: self.client.add_event_handler("ssl_invalid_cert", self.handle_invalid_cert) # Add plug-ins self.client.register_plugin("xep_0030") # Service Discovery self.client.register_plugin("xep_0004") # Data Forms self.client.register_plugin("xep_0060") # PubSub self.client.register_plugin("xep_0199") # XMPP Ping self.client.register_plugin("xep_0045") # Multi-User Chat if self.client.connect(self.server or ()): if self.use_tls: self.log.info("starting TLS...") self.client.start_tls() self.log.info("connected to %s, port %d" % self.server) else: raise WhistlerConnectionError("Unable to connect to %s:%d" % self.server) self.run_handler(EVENT_CONNECT) return self.client
def _handle_stream_features(self, features): if 'starttls' in features['features']: # Reset stream features after starttls self._stream_features = { 'starttls': features['starttls'], } else: # New stream features encountered self._stream_features.update(features.get_features()) found_tags = set([re.match('{.*}(.*)', n.tag).groups(1)[0] for n in features.xml.getchildren()]) unhandled = found_tags - set(features.get_features().keys()) if unhandled: log.error("Unhandled stream features: %s", sorted(unhandled)) return ClientXMPP._handle_stream_features(self, features)
def _handle_stream_features(self, features): if 'starttls' in features[ 'features']: # Reset stream features after starttls self._stream_features = { 'starttls': features['starttls'], } else: # New stream features encountered self._stream_features.update(features.get_features()) found_tags = set([ re.match('{.*}(.*)', n.tag).groups(1)[0] for n in features.xml.getchildren() ]) unhandled = found_tags - set(features.get_features().keys()) if unhandled: log.error("Unhandled stream features: %s", sorted(unhandled)) return ClientXMPP._handle_stream_features(self, features)
def connect(self): """Perform a connection to the server. This function is designed to work internally, but calls to connect handlers when connection is sucessful. """ if self.client: return self.client self.client = ClientXMPP(self.jid, self.password) # Install event handlers self.client.add_event_handler("groupchat_message", self.handle_muc_message) self.client.add_event_handler("session_start", self.handle_session_start) self.client.add_event_handler("message", self.handle_message) self.client.add_event_handler("changed_status", self.handle_changed_status) if self.ignore_ssl_cert: self.client.add_event_handler("ssl_invalid_cert", self.handle_invalid_cert) # Add plug-ins self.client.register_plugin("xep_0030") # Service Discovery self.client.register_plugin("xep_0004") # Data Forms self.client.register_plugin("xep_0060") # PubSub self.client.register_plugin("xep_0199") # XMPP Ping self.client.register_plugin("xep_0045") # Multi-User Chat if len(self.server) == 2: domain, port = self.server self.client._expected_server_name = domain if self.client.connect(self.server or ()): if self.use_tls: self.log.info("starting TLS...") self.client.start_tls() self.log.info("connected to %s, port %d" % self.server) else: raise WhistlerConnectionError("Unable to connect to %s:%d" % self.server) self.run_handler(EVENT_CONNECT) return self.client
def connect_soc(self): ClientXMPP.connect(self, address=(self.host, self.port), reattempt=True, use_tls=True, use_ssl=False)
def __init__(self, jid, password, room, nick, mq): self.nick = nick self.room = room self.jid = JID(jid) bot = ClientXMPP(jid, password) # disable ipv6 for now since we're getting errors using it bot.use_ipv6 = False bot.add_event_handler('session_start', self.on_start) bot.add_event_handler('message', self.on_message) bot.register_plugin('xep_0045') self._muc = bot.plugin['xep_0045'] bot.register_plugin('xep_0199') bot.plugin['xep_0199'].enable_keepalive(30, 30) resource = 'sweetiewatch' + self.randomstr() self.mq = mq if not bot.connect(): raise 'could not connect' bot.process() self._bot = bot
class WhistlerBot(object): """Main Whistler bot class. The main WhistlerBot class handle the bot behaviour and perform subcall to specific command handler when a command is received in a configured MUC channel. """ def __init__(self, jid, password, server=None, rooms=None, resource=None, mention=None, log=None, users=[], use_tls=False, ignore_ssl_cert=True): """Initialize a Whistler bot. Create a new :class:`WhistlerBot` object, the :func:`__init__` receive the following parameters: :param `jid`: a valid JID atom to identify the bot user. :param `password`: a plaintext password to identify the bot user. :param `server`: a tuple in the form *server*, *port* which sepcify the host to connect to, if not provided the server then use the JID domain instead. :param `rooms`: a :class:`list` of rooms to be autojoin in. :param `resource`: the XMPP resource string, or autogenerated one if not provided. :param `log`: a :class:`WhistlerLog` to log bot messages to, or *stdout* if none is provided. :param `users`: a :class:`set` of valid JID as strings which identify master users. :param use_tls: if set to true, try to use TLS where available :param ignore_ssl_cert: if set to false raise an exception when certificate do not match with hostname or any other kind of invalid certificate. """ self.user = jid self.jid = jid self.password = password self.server = server self.log = log or WhistlerLog() self.use_tls = use_tls self.ignore_ssl_cert = ignore_ssl_cert self._initial_users = users self.handlers = { EVENT_CONNECT: [], EVENT_DISCONNECT: [], EVENT_REGISTER: [], EVENT_JOIN: [], EVENT_LEAVE: [], EVENT_UNREGISTER: [], EVENT_MESSAGE: [], EVENT_MUC_MESSAGE: [], EVENT_MUC_COMMAND: [], EVENT_CHANGE_STATUS: []} self.client = None self.resource = resource or self.__class__.__name__.lower() + \ str(random.getrandbits(32)) self.mention = mention or self.resource self.jid += "/" + self.resource self._rooms = set(rooms or []) @property def users(self): """Users in the bot roster (administrators) A property which return an iterator over users in bot roster, that is administrative users or valid users to admin the bot. """ return filter(lambda x:x not in self._rooms, self.client.roster[self.user].keys()) @property def roster(self): """Bot roster""" return self.client.roster @property def rooms(self): """Return a list of rooms where bot are joined in.""" return self.client["xep_0045"].rooms.keys() def run_handler(self, event, *args, **kwargs): """Performs the handler actions related with specified event.""" for handler in self.handlers[event]: handler(*args, **kwargs) def register_handler(self, typ, fun): """Register a new handler to whistler. The handler is a function which will be executed on certain actions. :param `typ`: The type of the handler, can be one of following: * connect: *on connect* handler, * disconnect: *on disconnect* handler, * register: *on register user* handler. :param `fun`: a function to be executed, which receive almost an instance of class :class:`WhistlerBot` as parameter. The register type also receive a JID in string notation of the registered user. """ self.handlers[typ].append(fun) def unregister_handler(self, typ, fun): """Unregister a previously registerd handler.""" self.handlers[typ].remove(fun) def set_subject(self, room, subject): """Set a new subject on specified room.""" if room in self._rooms: mesg = "Whistler set subject to: %s" % subject self.client.send_message(room, mesg, subject, "groupchat") def send(self, to, mesg, typ="chat", subject=None): self.client.send_message(to, mesg, subject, typ) def register_plugin(self, plugin_name): """Register a new SleekXMPP plugin.""" if not self.client: raise WhistlerError("No client connected") self.client.register_plugin(plugin_name) def handle_invalid_cert(self, pem_cert): """Handle a invalid certification request.""" self.log.warning("Invalid certificated found, but continue anyway.") def connect(self): """Perform a connection to the server. This function is designed to work internally, but calls to connect handlers when connection is sucessful. """ if self.client: return self.client self.client = ClientXMPP(self.jid, self.password) # Install event handlers self.client.add_event_handler("groupchat_message", self.handle_muc_message) self.client.add_event_handler("session_start", self.handle_session_start) self.client.add_event_handler("message", self.handle_message) self.client.add_event_handler("changed_status", self.handle_changed_status) if self.ignore_ssl_cert: self.client.add_event_handler("ssl_invalid_cert", self.handle_invalid_cert) # Add plug-ins self.client.register_plugin("xep_0030") # Service Discovery self.client.register_plugin("xep_0004") # Data Forms self.client.register_plugin("xep_0060") # PubSub self.client.register_plugin("xep_0199") # XMPP Ping self.client.register_plugin("xep_0045") # Multi-User Chat if len(self.server) == 2: domain, port = self.server self.client._expected_server_name = domain if self.client.connect(self.server or ()): if self.use_tls: self.log.info("starting TLS...") self.client.start_tls() self.log.info("connected to %s, port %d" % self.server) else: raise WhistlerConnectionError("Unable to connect to %s:%d" % self.server) self.run_handler(EVENT_CONNECT) return self.client def handle_changed_status(self, presence): self.run_handler(EVENT_CHANGE_STATUS, presence) def handle_session_start(self, event): self.client.get_roster() self.client.send_presence() [self.join_room(room) for room in self._rooms] for user in self._initial_users: self.register_user(user) def register_command(self, cmdname, cmdfun): """Register a new command. This function in intended to provide a way to add commands on-the-fly, when :class:`WhistlerBot` is alreay instanced. :param `cmdname`: a name to this command. :param `cmdfun`: a callback which can accept three arguments, which will be usd when command called. """ setattr(self, "cmd_%s" % cmdname, cmdfun) def start(self): """Start bot operation. Connect to the XMPP server and start the bot, it will be serving requests until the stopping is requested, using :func:`stop` function. """ if not self.connect(): raise WhistlerConnectionError("unknown error") self.client.process(threaded=False) def stop(self): """Stop bot operation. Stop serving requests. This function also destroys the current connection, if existed. """ self.disconnect() def is_validuser(self, jid): """Check for whether an user is valid. Check whether the specified user is registered as valid user in the bot, according to :func:`register_user` and :func:`unregister_user` functions. """ return (jid not in self._rooms and jid in self.client.roster[self.user].keys()) or \ (jid in self._initial_users) def register_user(self, jid, subscription="both"): """Register an user as valid user for the bot.""" self.client.update_roster(jid, subscription=subscription) self.run_handler(EVENT_REGISTER, jid) def unregister_user(self, jid, subscription="remove"): """Unregister an user as valid user for the bot.""" self.client.update_roster(jid, subscription=subscription) self.run_handler(EVENT_UNREGISTER, jid) def reply(self, to, message): """Send a reply to an specified message, using a new message one. :param `to`: a message to be replied :param `message`: a string with the reply. """ to.reply(message).send() def get_room_nicks(self, room): """Return a dict with the nicks in room as keys. Values contains data about these nicks.""" return self.client.plugin["xep_0045"].rooms[room] def handle_muc_message(self, message): """Handle any received group chat message. :param message: Message received from the MUC room. """ body = message["body"] self.run_handler(EVENT_MUC_MESSAGE, message, None) if not body or (body[0] != COMMAND_CHAR \ and not body.startswith(self.mention + ", ") \ and not body.startswith(self.mention + ": ") \ and not body.startswith("@" + self.mention)): # None to handle return if body[0] == COMMAND_CHAR: command_n = body.split()[0][1:] arguments = body.split()[1:] else: command_n = body.split()[1] arguments = body.split()[2:] command = getattr(self, "cmd_%s" % command_n, None) message.command = command if command: self.log.info("muc command %s %r" % (command_n, arguments)) result = command(message, arguments) if result is not None: if isinstance(result, list): for r in result: self.reply(message, r) elif isinstance(result, basestring): self.reply(message, result) self.run_handler(EVENT_MUC_COMMAND, message, arguments) def handle_message(self, message): """Handle a direct chat message. :param message: Message received from some user. """ if not message["body"]: return self.run_handler(EVENT_MESSAGE, message, None) if message["type"] == "groupchat": # discard muc messages here. return body = message["body"].split() command_n = body[0] arguments = body[1:] command = getattr(self, "cmd_%s" % command_n, None) if command: self.log.info("chat command %s %r" % (command_n, arguments)) result = command(message, arguments) if result is not None: if isinstance(result, list): for r in result: self.reply(message, r) elif isinstance(result, basestring): self.reply(message, result) def join(self, rooms, resource=None): """Join several rooms at once. :param rooms: Iterable with room JIDs as strings. :param resource: If given, nickname (resource) used in rooms. """ [self.join_room(room, resource) for room in rooms] def leave(self, rooms, resource=None): """Leave several rooms at once. :param rooms: Iterable with rooms JIDs as strings. :param resource: If given, nickname (resource) used in rooms. """ [self.leave_room(room, resource) for room in rooms] def join_room(self, room, resource=None): """Join a Multi-User Chat (MUC) room. Make the bot join a MUC room. If a nick different from the resource name is to be used, it can be specified. This allows for several bots to be in the same room. :param `room`: The room name. :param `resource`: A resource name for the bot in the room. """ self.client.plugin["xep_0045"].joinMUC(room, resource or self.resource, maxhistory="1") self.run_handler(EVENT_JOIN, room) def disconnect(self): """Disconnect from the server. Leave all rooms, sets bot presence to unavailable, and closes the connection to the server. """ self.log.info("Shutting down the bot...") self.run_handler(EVENT_DISCONNECT) self.client.disconnect() def leave_room(self, room, resource=None): """Leaves a Multi-User Chat (MUC) room. :param `room`: the room name to leave. :param `resource`: the resource which leaves. """ self.client.plugin["xep_0045"].leaveMUC(room, resource or self.resource) self.run_handler(EVENT_LEAVE, room)
def __init__(self, jid, password, room, nick, mq): self.nick = nick self.room = room self.jid = JID(jid) bot = ClientXMPP(jid, password) bot.add_event_handler('session_start', self.on_start) bot.add_event_handler('message', self.on_message) bot.register_plugin('xep_0045') self._muc = bot.plugin['xep_0045'] bot.register_plugin('xep_0199') bot.plugin['xep_0199'].enable_keepalive(30, 30) resource = 'sweetiewatch' + self.randomstr() self.mq = mq if not bot.connect(): raise 'could not connect' bot.process() self._bot = bot
class WhistlerBot(object): """Main Whistler bot class. The main WhistlerBot class handle the bot behaviour and perform subcall to specific command handler when a command is received in a configured MUC channel. """ def __init__(self, jid, password, server=None, rooms=None, resource=None, mention=None, log=None, users=[], use_tls=False, ignore_ssl_cert=True): """Initialize a Whistler bot. Create a new :class:`WhistlerBot` object, the :func:`__init__` receive the following parameters: :param `jid`: a valid JID atom to identify the bot user. :param `password`: a plaintext password to identify the bot user. :param `server`: a tuple in the form *server*, *port* which sepcify the host to connect to, if not provided the server then use the JID domain instead. :param `rooms`: a :class:`list` of rooms to be autojoin in. :param `resource`: the XMPP resource string, or autogenerated one if not provided. :param `log`: a :class:`WhistlerLog` to log bot messages to, or *stdout* if none is provided. :param `users`: a :class:`set` of valid JID as strings which identify master users. :param use_tls: if set to true, try to use TLS where available :param ignore_ssl_cert: if set to false raise an exception when certificate do not match with hostname or any other kind of invalid certificate. """ self.user = jid self.jid = jid self.password = password self.server = server self.log = log or WhistlerLog() self.use_tls = use_tls self.ignore_ssl_cert = ignore_ssl_cert self._initial_users = users self.handlers = { EVENT_CONNECT: [], EVENT_DISCONNECT: [], EVENT_REGISTER: [], EVENT_JOIN: [], EVENT_LEAVE: [], EVENT_UNREGISTER: [], EVENT_MESSAGE: [], EVENT_MUC_MESSAGE: [], EVENT_MUC_COMMAND: [], EVENT_CHANGE_STATUS: []} self.client = None self.resource = resource or self.__class__.__name__.lower() + \ str(random.getrandbits(32)) self.mention = mention or self.resource self.jid += "/" + self.resource self._rooms = set(rooms or []) @property def users(self): """Users in the bot roster (administrators) A property which return an iterator over users in bot roster, that is administrative users or valid users to admin the bot. """ return filter(lambda x:x not in self._rooms, self.client.roster[self.user].keys()) @property def roster(self): """Bot roster""" return self.client.roster @property def rooms(self): """Return a list of rooms where bot are joined in.""" return self.client["xep_0045"].rooms.keys() def run_handler(self, event, *args, **kwargs): """Performs the handler actions related with specified event.""" for handler in self.handlers[event]: handler(*args, **kwargs) def register_handler(self, typ, fun): """Register a new handler to whistler. The handler is a function which will be executed on certain actions. :param `typ`: The type of the handler, can be one of following: * connect: *on connect* handler, * disconnect: *on disconnect* handler, * register: *on register user* handler. :param `fun`: a function to be executed, which receive almost an instance of class :class:`WhistlerBot` as parameter. The register type also receive a JID in string notation of the registered user. """ self.handlers[typ].append(fun) def unregister_handler(self, typ, fun): """Unregister a previously registerd handler.""" self.handlers[typ].remove(fun) def set_subject(self, room, subject): """Set a new subject on specified room.""" if room in self._rooms: mesg = "Whistler set subject to: %s" % subject self.client.send_message(room, mesg, subject, "groupchat") def send(self, to, mesg, typ="chat", subject=None): self.client.send_message(to, mesg, subject, typ) def register_plugin(self, plugin_name): """Register a new SleekXMPP plugin.""" if not self.client: raise WhistlerError("No client connected") self.client.register_plugin(plugin_name) def handle_invalid_cert(self, pem_cert): """Handle a invalid certification request.""" self.log.warning("Invalid certificated found, but continue anyway.") def connect(self): """Perform a connection to the server. This function is designed to work internally, but calls to connect handlers when connection is sucessful. """ if self.client: return self.client self.client = ClientXMPP(self.jid, self.password) # Install event handlers self.client.add_event_handler("groupchat_message", self.handle_muc_message) self.client.add_event_handler("session_start", self.handle_session_start) self.client.add_event_handler("message", self.handle_message) self.client.add_event_handler("changed_status", self.handle_changed_status) if self.ignore_ssl_cert: self.client.add_event_handler("ssl_invalid_cert", self.handle_invalid_cert) # Add plug-ins self.client.register_plugin("xep_0030") # Service Discovery self.client.register_plugin("xep_0004") # Data Forms self.client.register_plugin("xep_0060") # PubSub self.client.register_plugin("xep_0199") # XMPP Ping self.client.register_plugin("xep_0045") # Multi-User Chat if self.client.connect(self.server or ()): if self.use_tls: self.log.info("starting TLS...") self.client.start_tls() self.log.info("connected to %s, port %d" % self.server) else: raise WhistlerConnectionError("Unable to connect to %s:%d" % self.server) self.run_handler(EVENT_CONNECT) return self.client def handle_changed_status(self, presence): self.run_handler(EVENT_CHANGE_STATUS, presence) def handle_session_start(self, event): self.client.get_roster() self.client.send_presence() [self.join_room(room) for room in self._rooms] for user in self._initial_users: self.register_user(user) def register_command(self, cmdname, cmdfun): """Register a new command. This function in intended to provide a way to add commands on-the-fly, when :class:`WhistlerBot` is alreay instanced. :param `cmdname`: a name to this command. :param `cmdfun`: a callback which can accept three arguments, which will be usd when command called. """ setattr(self, "cmd_%s" % cmdname, cmdfun) def start(self): """Start bot operation. Connect to the XMPP server and start the bot, it will be serving requests until the stopping is requested, using :func:`stop` function. """ if not self.connect(): raise WhistlerConnectionError("unknown error") self.client.process(threaded=False) def stop(self): """Stop bot operation. Stop serving requests. This function also destroys the current connection, if existed. """ self.disconnect() def is_validuser(self, jid): """Check for whether an user is valid. Check whether the specified user is registered as valid user in the bot, according to :func:`register_user` and :func:`unregister_user` functions. """ return (jid not in self._rooms and jid in self.client.roster[self.user].keys()) or \ (jid in self._initial_users) def register_user(self, jid, subscription="both"): """Register an user as valid user for the bot.""" self.client.update_roster(jid, subscription=subscription) self.run_handler(EVENT_REGISTER, jid) def unregister_user(self, jid, subscription="remove"): """Unregister an user as valid user for the bot.""" self.client.update_roster(jid, subscription=subscription) self.run_handler(EVENT_UNREGISTER, jid) def reply(self, to, message): """Send a reply to an specified message, using a new message one. :param `to`: a message to be replied :param `message`: a string with the reply. """ to.reply(message).send() def get_room_nicks(self, room): """Return a dict with the nicks in room as keys. Values contains data about these nicks.""" return self.client.plugin["xep_0045"].rooms[room] def handle_muc_message(self, message): """Handle any received group chat message. :param message: Message received from the MUC room. """ body = message["body"] self.run_handler(EVENT_MUC_MESSAGE, message, None) if not body or (body[0] != COMMAND_CHAR \ and not body.startswith(self.mention + ", ") \ and not body.startswith(self.mention + ": ") \ and not body.startswith("@" + self.mention)): # None to handle return if body[0] == COMMAND_CHAR: command_n = body.split()[0][1:] arguments = body.split()[1:] else: command_n = body.split()[1] arguments = body.split()[2:] command = getattr(self, "cmd_%s" % command_n, None) message.command = command if command: self.log.info("muc command %s %r" % (command_n, arguments)) result = command(message, arguments) if result is not None: if isinstance(result, list): for r in result: self.reply(message, r) elif isinstance(result, basestring): self.reply(message, result) self.run_handler(EVENT_MUC_COMMAND, message, arguments) def handle_message(self, message): """Handle a direct chat message. :param message: Message received from some user. """ if not message["body"]: return self.run_handler(EVENT_MESSAGE, message, None) if message["type"] == "groupchat": # discard muc messages here. return body = message["body"].split() command_n = body[0] arguments = body[1:] command = getattr(self, "cmd_%s" % command_n, None) if command: self.log.info("chat command %s %r" % (command_n, arguments)) result = command(message, arguments) if result is not None: if isinstance(result, list): for r in result: self.reply(message, r) elif isinstance(result, basestring): self.reply(message, result) def join(self, rooms, resource=None): """Join several rooms at once. :param rooms: Iterable with room JIDs as strings. :param resource: If given, nickname (resource) used in rooms. """ [self.join_room(room, resource) for room in rooms] def leave(self, rooms, resource=None): """Leave several rooms at once. :param rooms: Iterable with rooms JIDs as strings. :param resource: If given, nickname (resource) used in rooms. """ [self.leave_room(room, resource) for room in rooms] def join_room(self, room, resource=None): """Join a Multi-User Chat (MUC) room. Make the bot join a MUC room. If a nick different from the resource name is to be used, it can be specified. This allows for several bots to be in the same room. :param `room`: The room name. :param `resource`: A resource name for the bot in the room. """ self.client.plugin["xep_0045"].joinMUC(room, resource or self.resource, maxhistory="1") self.run_handler(EVENT_JOIN, room) def disconnect(self): """Disconnect from the server. Leave all rooms, sets bot presence to unavailable, and closes the connection to the server. """ self.log.info("Shutting down the bot...") self.run_handler(EVENT_DISCONNECT) self.client.disconnect() def leave_room(self, room, resource=None): """Leaves a Multi-User Chat (MUC) room. :param `room`: the room name to leave. :param `resource`: the resource which leaves. """ self.client.plugin["xep_0045"].leaveMUC(room, resource or self.resource) self.run_handler(EVENT_LEAVE, room)