<commit_before>"""
hermes.chatroom
~~~~~~~~~~~~~~~

This module contains the base chatroom functionality for Hermes.
"""

import sys
import re
import xmpp
import logging

logger = logging.getLogger(__name__)

class Chatroom(object):
    """Base chatroom class. Implements default broadcast logic and handles basic chatroom commands."""

    #static property that can hold a list of regular expression/method name pairs. Each incoming message
    #is tested against each regex. On a match, the associated method is invoked to handle the message
    #instead of the standard message-handling pipeline.
    command_patterns = ()

    def __init__(self, name, params):
        self.command_patterns = []
        for pattern in type(self).command_patterns:
            self.command_patterns.append((re.compile(pattern[0]), pattern[1]))

        self.name = name
        self.params = params
        self.jid = xmpp.protocol.JID(self.params['JID'])

    def connect(self):
        """Connect to the chatroom's server, sets up handlers, invites members as needed."""
        self.client = xmpp.Client(self.jid.getDomain(), debug=[])
        conn = self.client.connect(server=self.params['SERVER'])
        if not conn:
            raise Exception("could not connect to server")

        auth = self.client.auth(self.jid.getNode(), self.params['PASSWORD'])
        if not auth:
            raise Exception("could not authenticate as chat server")

        #self.client.RegisterDisconnectHandler(self.on_disconnect)
        self.client.RegisterHandler('message', self.on_message)
        self.client.RegisterHandler('presence',self.on_presence)
        self.client.sendInitPresence(requestRoster=0)

        roster =  self.client.getRoster()
        for m in self.params['MEMBERS']:
            self.invite_user(m, roster=roster)

    def get_member(self, jid, default=None):
        """Get a chatroom member by JID"""
        member = filter(lambda m: m['JID'] == jid, self.params['MEMBERS'])
        if len(member) == 1:
            return member[0]
        elif len(member) == 0:
            return default
        else:
            raise Exception('Multple members have the same JID of [%s]' % (jid,))

    def is_member(self, m):
        """Check if a user is a member of the chatroom"""
        if isinstance(m, basestring):
            jid = m
        else:
            jid = m['JID']

        return len(filter(lambda m: m['JID'] == jid and m['STATUS'] in ('ACTIVE', 'INVITED'), self.params['MEMBERS'])) > 0

    def invite_user(self, new_member, inviter=None, roster=None):
        """Invites a new member to the chatroom"""
        roster = roster or self.client.getRoster()
        jid = new_member['JID']

        if jid in roster.keys() and roster.getSubscription(jid) == 'both':
            new_member['STATUS'] = 'ACTIVE'
            if inviter:
                self.send_message('%s is already a member' % (jid,), inviter)
        else:
            new_member['STATUS'] = 'INVITED'
            self.broadcast('inviting %s to the room' % (jid,))

            #Add nickname according to http://xmpp.org/extensions/xep-0172.html
            subscribe_presence = xmpp.dispatcher.Presence(to=jid, typ='subscribe')
            if 'NICK' in self.params:
                subscribe_presence.addChild(name='nick', namespace=xmpp.protocol.NS_NICK, payload=self.params['NICK'])
            self.client.send(subscribe_presence)

        if not self.is_member(new_member):
            new_member.setdefault('NICK', jid.split('@')[0])
            self.params['MEMBERS'].append(new_member)

    def kick_user(self, jid):
        """Kicks a member from the chatroom. Kicked user will receive no more messages."""
        for member in filter(lambda m: m['JID'] == jid, self.params['MEMBERS']):
            member['STATUS'] = 'KICKED'
            self.send_message('You have been kicked from %s' % (self.name,), member)

            self.client.sendPresence(jid=member['JID'], typ='unsubscribed')
            self.client.sendPresence(jid=member['JID'], typ='unsubscribe')
            self.broadcast('kicking %s from the room' % (jid,))

    def send_message(self, body, to, quiet=False, html_body=None):
        """Send a message to a single member"""
        if to.get('MUTED'):
            to['QUEUED_MESSAGES'].append(body)
        else:
            if not quiet:
                logger.info('message on %s to %s: %s' % (self.name, to['JID'], body))

            message = xmpp.protocol.Message(to=to['JID'], body=body, typ='chat')
            if html_body:
                html = xmpp.Node('html', {'xmlns': 'http://jabber.org/protocol/xhtml-im'})
                html.addChild(node=xmpp.simplexml.XML2Node("<body xmlns='http://www.w3.org/1999/xhtml'>" + html_body.encode('utf-8') + "</body>"))
                message.addChild(node=html)

            self.client.send(message)

    def broadcast(self, body, html_body=None, exclude=()):
        """Broadcast a message to users in the chatroom"""
        logger.info('broadcast on %s: %s' % (self.name, body,))
        for member in filter(lambda m: m['STATUS'] == 'ACTIVE' and m not in exclude, self.params['MEMBERS']):
            logger.debug(member['JID'])
            self.send_message(body, member, html_body=html_body, quiet=True)

    ### Command handlers ###

    def do_marco(self, sender, body, args):
        """Respond with 'polo' to the user"""<commit_msg>adding old bug fix from other dev machine<commit_after>"""
hermes.chatroom
~~~~~~~~~~~~~~~

This module contains the base chatroom functionality for Hermes.
"""

import sys
import re
import xmpp
import logging

logger = logging.getLogger(__name__)

class Chatroom(object):
    """Base chatroom class. Implements default broadcast logic and handles basic chatroom commands."""

    #static property that can hold a list of regular expression/method name pairs. Each incoming message
    #is tested against each regex. On a match, the associated method is invoked to handle the message
    #instead of the standard message-handling pipeline.
    command_patterns = ()

    def __init__(self, name, params):
        self.command_patterns = []
        for pattern in type(self).command_patterns:
            self.command_patterns.append((re.compile(pattern[0]), pattern[1]))

        self.name = name
        self.params = params
        self.jid = xmpp.protocol.JID(self.params['JID'])

    def connect(self):
        """Connect to the chatroom's server, sets up handlers, invites members as needed."""
        self.client = xmpp.Client(self.jid.getDomain(), debug=[])
        conn = self.client.connect(server=self.params['SERVER'])
        if not conn:
            raise Exception("could not connect to server")

        auth = self.client.auth(self.jid.getNode(), self.params['PASSWORD'])
        if not auth:
            raise Exception("could not authenticate as chat server")

        #self.client.RegisterDisconnectHandler(self.on_disconnect)
        self.client.RegisterHandler('message', self.on_message)
        self.client.RegisterHandler('presence',self.on_presence)
        self.client.sendInitPresence(requestRoster=0)

        roster =  self.client.getRoster()
        for m in self.params['MEMBERS']:
            self.invite_user(m, roster=roster)

    def get_member(self, jid, default=None):
        """Get a chatroom member by JID"""
        member = filter(lambda m: m['JID'] == jid, self.params['MEMBERS'])
        if len(member) == 1:
            return member[0]
        elif len(member) == 0:
            return default
        else:
            raise Exception('Multple members have the same JID of [%s]' % (jid,))

    def is_member(self, m):
        """Check if a user is a member of the chatroom"""
        if isinstance(m, basestring):
            jid = m
        else:
            jid = m['JID']

        return len(filter(lambda m: m['JID'] == jid and m['STATUS'] in ('ACTIVE', 'INVITED'), self.params['MEMBERS'])) > 0

    def invite_user(self, new_member, inviter=None, roster=None):
        """Invites a new member to the chatroom"""
        roster = roster or self.client.getRoster()
        jid = new_member['JID']

        if jid in roster.keys() and roster.getSubscription(jid) == 'both':
            new_member['STATUS'] = 'ACTIVE'
            if inviter:
                self.send_message('%s is already a member' % (jid,), inviter)
        else:
            new_member['STATUS'] = 'INVITED'
            self.broadcast('inviting %s to the room' % (jid,))

            #Add nickname according to http://xmpp.org/extensions/xep-0172.html
            subscribe_presence = xmpp.dispatcher.Presence(to=jid, typ='subscribe')
            if 'NICK' in self.params:
                subscribe_presence.addChild(name='nick', namespace=xmpp.protocol.NS_NICK, payload=self.params['NICK'])
            self.client.send(subscribe_presence)

        if not self.is_member(new_member):
            new_member.setdefault('NICK', jid.split('@')[0])
            self.params['MEMBERS'].append(new_member)

    def kick_user(self, jid):
        """Kicks a member from the chatroom. Kicked user will receive no more messages."""
        for member in filter(lambda m: m['JID'] == jid, self.params['MEMBERS']):
            member['STATUS'] = 'KICKED'
            self.send_message('You have been kicked from %s' % (self.name,), member)

            self.client.sendPresence(jid=member['JID'], typ='unsubscribed')
            self.client.sendPresence(jid=member['JID'], typ='unsubscribe')
            self.broadcast('kicking %s from the room' % (jid,))

    def send_message(self, body, to, quiet=False, html_body=None):
        """Send a message to a single member"""
        if to.get('MUTED'):
            to['QUEUED_MESSAGES'].append(body)
        else:
            if not quiet:
                logger.info('message on %s to %s: %s' % (self.name, to['JID'], body))

            message = xmpp.protocol.Message(to=to['JID'], body=body, typ='chat')
            if html_body:
                html = xmpp.Node('html', {'xmlns': 'http://jabber.org/protocol/xhtml-im'})
                html.addChild(node=xmpp.simplexml.XML2Node("<body xmlns='http://www.w3.org/1999/xhtml'>" + html_body.encode('utf-8') + "</body>"))
                message.addChild(node=html)

            self.client.send(message)

    def broadcast(self, body, html_body=None, exclude=()):
        """Broadcast a message to users in the chatroom"""
        logger.info('broadcast on %s: %s' % (self.name, body,))
        for member in filter(lambda m: m.get('STATUS') == 'ACTIVE' and m not in exclude, self.params['MEMBERS']):
            logger.debug(member['JID'])
            self.send_message(body, member, html_body=html_body, quiet=True)

    ### Command handlers ###

    def do_marco(self, sender, body, args):
        """Respond with 'polo' to the user"""
{'fraction_non_alphanumeric': 0.13639712654264138, 'fraction_numerical': 0.003499723706023209, 'mean_word_length': 2.6872665534804754, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 6}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6915292', 'n_tokens_mistral': 3328, 'n_tokens_neox': 3217, 'n_words': 848}