<commit_before>import os,json,logging,websocket,requests,time,thread
from .config import slackurl,event_types

logging.basicConfig(level=logging.WARN)
log = logging.getLogger('slacksocket')

class SlackSocketEventNameError(NameError):
    """
    Invalid name
    """
    pass

class SlackSocketAPIError(RuntimeError):
    """
    Error response from Slack API
    """
    pass

#TODO: create a common slack api request object

class SlackEvent(object):
    """
    SlackEvent is an event received from the Slack RTM API
    params:
     - event(dict)
    attributes:
     - type: Slack event type
     - time: UTC time event was received 
    """
    def __init__(self,event):
        self.type = event['type']
        self.time = int(time.time())
        self.json = json.dumps(event)
        self.event = event

class SlackSocket(object):
    """
    SlackSocket class provides a streaming interface to the Slack Real Time
    Messaging API
    params:
     - slacktoken(str): token to authenticate with slack
     - translate(bool): yield events with human-readable names
        rather than id. default true
    """
    def __init__(self,slacktoken,translate=True):
        if type(translate) != bool:
            raise TypeError('translate must be a boolean')
        self.events = []
        self.token = slacktoken
        self.translate = translate
        self.team,self.user = self._auth_test()
        self.thread = thread.start_new_thread(self.open,())

    def open(self):
        ws = websocket.WebSocketApp(self._get_websocket_url(),
                                    on_message = self._event_handler,
                                    on_error   = self._error_handler,
                                    on_open    = self._open_handler,
                                    on_close   = self._exit_handler)
        ws.run_forever()

    def get_event(self,event_filter='all'):
        """
        return event object in the order received or block until an event is
        received and return it.
        params:
         - event_filter(list): Slack event type(s) to filter by. Excluding a
            filter returns all slack events. See https://api.slack.com/events
            for a listing of valid event types.
        """
        #validate event filter
        if event_filter == 'all':
            event_filter = event_types

        if type(event_filter) != list:
            raise TypeError('event_filter must be given as a list')

        for f in event_filter:
            if f not in event_types:
                raise SlackSocketEventNameError('unknown event type %s\n \
                             see https://api.slack.com/events' % event_filter)

        #return or block until we have something to return
        while True:
            try:
                e = self.events.pop(0)
                if e.type in event_filter:
                    return e
            except IndexError:
                pass

    #######
    # Internal Methods
    #######

    def _get_websocket_url(self):
        """
        retrieve a fresh websocket url from slack api
        """
        r = requests.get(slackurl['rtm'],params={'token':self.token})
        rj = r.json()
        if not rj['ok']:
            raise SlackSocketAPIError('Error from slack api:\n %s' % r.text)

        return rj['url']

    def _auth_test(self):
        """
        Perform API auth test and get our user and team
        """
        r = requests.get(slackurl['test'],params={'token':self.token})
        rj = r.json()
        if not rj['ok']:
            raise SlackSocketAPIError('Error from slack api:\n %s' % r.text)
        
        if self.translate:
            return (rj['team'],rj['user'])
        else:
            return (rj['team_id'],rj['user_id'])

    def _lookup_user(self,user_id):
        """
        Look up a username from user id
        """
        if user_id == 'USLACKBOT':
            return "slackbot"

        r = requests.get(slackurl['users'],params={'token':self.token})
        rj = r.json()
        if not rj['ok']:
            log.critical('error from slack api:\n %s' % r)

        for user in rj['members']:
            if user['id'] == user_id:
                return user['name']
        else:
            return "unknown"

    def _lookup_channel(self,channel_id):
        """
        Look up a channelname from channel id
        """
        for channel_type in ['channels','groups','ims']:
            r = requests.get(slackurl[channel_type],params={'token':self.token})
            rj = r.json()
            if not rj['ok']:
                log.critical('error from slack api:\n %s' % r)
            for channel in rj[channel_type]:
                if channel['id'] == channel_id:
                    if channel_type == 'ims':
                        return { 'channel_type' : channel_type,
                                 'channel_name' : self._lookup_user(channel['user']) }
                    else:
                        return { 'channel_type' : channel_type,
                                 'channel_name' : channel['name'] }
        #if no matches were found
        return { 'channel_type' : 'unknown',
                 'channel_name' : 'unknown' }

    #######
    # Handlers
    #######
<commit_msg>update slackevent description, add todo items<commit_after>import os,json,logging,websocket,requests,time,thread
from .config import slackurl,event_types

logging.basicConfig(level=logging.WARN)
log = logging.getLogger('slacksocket')

class SlackSocketEventNameError(NameError):
    """
    Invalid name
    """
    pass

class SlackSocketAPIError(RuntimeError):
    """
    Error response from Slack API
    """
    pass

#TODO: create a common slack api request object

class SlackEvent(object):
    """
    Event received from the Slack RTM API
    params:
     - event(dict)
    attributes:
     - type: Slack event type
     - time: UTC time event was received 
    """
    def __init__(self,event):
        self.type = event['type']
        self.time = int(time.time())
        self.json = json.dumps(event)
        self.event = event

class SlackSocket(object):
    """
    SlackSocket class provides a streaming interface to the Slack Real Time
    Messaging API
    params:
     - slacktoken(str): token to authenticate with slack
     - translate(bool): yield events with human-readable names
        rather than id. default true
    """
    def __init__(self,slacktoken,translate=True):
        if type(translate) != bool:
            raise TypeError('translate must be a boolean')
        self.events = []
        self.token = slacktoken
        self.translate = translate
        self.team,self.user = self._auth_test()
        self.thread = thread.start_new_thread(self.open,())

    def open(self):
        ws = websocket.WebSocketApp(self._get_websocket_url(),
                                    on_message = self._event_handler,
                                    on_error   = self._error_handler,
                                    on_open    = self._open_handler,
                                    on_close   = self._exit_handler)
        ws.run_forever()

    def get_event(self,event_filter='all'):
        """
        return event object in the order received or block until an event is
        received and return it.
        params:
         - event_filter(list): Slack event type(s) to filter by. Excluding a
            filter returns all slack events. See https://api.slack.com/events
            for a listing of valid event types.
        """
        #validate event filter
        if event_filter == 'all':
            event_filter = event_types

        if type(event_filter) != list:
            raise TypeError('event_filter must be given as a list')

        for f in event_filter:
            if f not in event_types:
                raise SlackSocketEventNameError('unknown event type %s\n \
                             see https://api.slack.com/events' % event_filter)

        #return or block until we have something to return
        while True:
            try:
                e = self.events.pop(0)
                if e.type in event_filter:
                    return e
            except IndexError:
                pass

    #######
    # Internal Methods
    #######

    def _get_websocket_url(self):
        """
        retrieve a fresh websocket url from slack api
        """
        r = requests.get(slackurl['rtm'],params={'token':self.token})
        rj = r.json()
        if not rj['ok']:
            raise SlackSocketAPIError('Error from slack api:\n %s' % r.text)

        return rj['url']

    def _auth_test(self):
        """
        Perform API auth test and get our user and team
        """
        r = requests.get(slackurl['test'],params={'token':self.token})
        rj = r.json()
        if not rj['ok']:
            raise SlackSocketAPIError('Error from slack api:\n %s' % r.text)
        
        if self.translate:
            return (rj['team'],rj['user'])
        else:
            return (rj['team_id'],rj['user_id'])

    #TODO: add ability for lookup via id and cname
    def _lookup_user(self,user_id):
        """
        Look up a username from user id
        """
        if user_id == 'USLACKBOT':
            return "slackbot"

        r = requests.get(slackurl['users'],params={'token':self.token})
        rj = r.json()
        if not rj['ok']:
            log.critical('error from slack api:\n %s' % r)

        for user in rj['members']:
            if user['id'] == user_id:
                return user['name']
        else:
            return "unknown"

    #TODO: add ability for lookup via id and cname
    def _lookup_channel(self,channel_id):
        """
        Look up a channelname from channel id
        """
        for channel_type in ['channels','groups','ims']:
            r = requests.get(slackurl[channel_type],params={'token':self.token})
            rj = r.json()
            if not rj['ok']:
                log.critical('error from slack api:\n %s' % r)
            for channel in rj[channel_type]:
                if channel['id'] == channel_id:
                    if channel_type == 'ims':
                        return { 'channel_type' : channel_type,
                                 'channel_name' : self._lookup_user(channel['user']) }
                    else:
                        return { 'channel_type' : channel_type,
                                 'channel_name' : channel['name'] }
        #if no matches were found
        return { 'channel_type' : 'unknown',
                 'channel_name' : 'unknown' }

    #######
    # Handlers
    #######

{'fraction_non_alphanumeric': 0.10722676440184194, 'fraction_numerical': 0.000187952260125928, 'mean_word_length': 1.7880534451139638, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1739921', 'n_tokens_mistral': 2999, 'n_tokens_neox': 2902, 'n_words': 802}