<commit_before># -*- coding: utf-8 -*-
#

from functools import wraps
import time
import json
import os
import pickle
import sha
import re
import urllib
import HTMLParser
import sys
import traceback
import collections
from websocket import create_connection,WebSocketConnectionClosedException

# hack to make tests possible.. better way?
try:
    import weechat as w
except:
    pass

SCRIPT_NAME = "slack_extension"
SCRIPT_AUTHOR = "<NAME> <<EMAIL>>"
SCRIPT_VERSION = "0.99.3"
SCRIPT_LICENSE = "MIT"
SCRIPT_DESC = "Extends weechat for typing notification/search/etc on slack.com"

BACKLOG_SIZE = 200
SCROLLBACK_SIZE = 500

CACHE_VERSION = "3"

SLACK_API_TRANSLATOR = {
    "channel": {
        "history": "channels.history",
        "join": "channels.join",
        "leave": "channels.leave",
        "mark": "channels.mark",
        "info": "channels.info",
    },
    "im": {
        "history": "im.history",
        "join": "im.open",
        "leave": "im.close",
        "mark": "im.mark",
    },
    "group": {
        "history": "groups.history",
        "join": "channels.join",
        "leave": "groups.leave",
        "mark": "groups.mark",
    }

}

NICK_GROUP_HERE = "0|Here"
NICK_GROUP_AWAY = "1|Away"

def dbg(message, fout=False, main_buffer=False):
    """
    send debug output to the slack-debug buffer and optionally write to a file.
    """
    message = "DEBUG: {}".format(message)
    #message = message.encode('utf-8', 'replace')
    if fout:
        file('/tmp/debug.log', 'a+').writelines(message + '\n')
    if main_buffer:
            w.prnt("", message)
    else:
        if slack_debug is not None:
            w.prnt(slack_debug, message)


class SearchList(list):
    """
    A normal python list with some syntactic sugar for searchability
    """
    def __init__(self):
        self.hashtable = {}
        super(SearchList, self).__init__(self)

    def find(self, name):
        if name in self.hashtable.keys():
            return self.hashtable[name]
        #this is a fallback to __eq__ if the item isn't in the hashtable already
        if self.count(name) > 0:
            self.update_hashtable()
            return self[self.index(name)]

    def append(self, item, aliases=[]):
        super(SearchList, self).append(item)
        self.update_hashtable()

    def update_hashtable(self):
        for child in self:
            if hasattr(child, "get_aliases"):
                for alias in child.get_aliases():
                    if alias is not None:
                        self.hashtable[alias] = child

    def find_by_class(self, class_name):
        items = []
        for child in self:
            if child.__class__ == class_name:
                items.append(child)
        return items

    def find_by_class_deep(self, class_name, attribute):
        items = []
        for child in self:
            if child.__class__ == self.__class__:
                items += child.find_by_class_deep(class_name, attribute)
            else:
                items += (eval('child.' + attribute).find_by_class(class_name))
        return items


class SlackServer(object):
    """
    Root object used to represent connection and state of the connection to a slack group.
    """
    def __init__(self, token):
        self.nick = None
        self.name = None
        self.domain = None
        self.server_buffer_name = None
        self.login_data = None
        self.buffer = None
        self.token = token
        self.ws = None
        self.ws_hook = None
        self.users = SearchList()
        self.bots = SearchList()
        self.channels = SearchList()
        self.connecting = False
        self.connected = False
        self.communication_counter = 0
        self.message_buffer = {}
        self.ping_hook = None

        self.identifier = None
        self.connect_to_slack()

    def __eq__(self, compare_str):
        if compare_str == self.identifier or compare_str == self.token or compare_str == self.buffer:
            return True
        else:
            return False

    def __str__(self):
        return "{}".format(self.identifier)

    def __repr__(self):
        return "{}".format(self.identifier)

    def add_user(self, user):
        self.users.append(user, user.get_aliases())
        users.append(user, user.get_aliases())

    def add_bot(self, bot):
        self.bots.append(bot)

    def add_channel(self, channel):
        self.channels.append(channel, channel.get_aliases())
        channels.append(channel, channel.get_aliases())

    def get_aliases(self):
        aliases = [self.identifier, self.token, self.buffer]
        return aliases

    def find(self, name, attribute):
        attribute = eval("self." + attribute)
        return attribute.find(name)

    def get_communication_id(self):
        if self.communication_counter > 999:
            self.communication_counter = 0
        self.communication_counter += 1
        return self.communication_counter

    def send_to_websocket(self, data, expect_reply=True):
        data["id"] = self.get_communication_id()
        message = json.dumps(data)
        try:
            if expect_reply:
                self.message_buffer[data["id"]] = data
            self.ws.send(message)
            dbg("Sent {}...".format(message[:100]))
        except:
            dbg("Unexpected error: {}\nSent: {}".format(sys.exc_info()[0], data))
            self.connected = False

    def ping(self):
        request = {"type": "ping"}
        self.send_to_websocket(request)

    def connect_to_slack(self):
        t = time.time()
        if not self.connecting:
            async_slack_api_request("slack.com", self.token, "rtm.start", {"ts": t})
            self.connecting = True

    def connected_to_slack(self, login_data):
        if login_data["ok"]:
            self.domain = login_data["team"]["domain"] + ".slack.com"
            dbg("connected to {}".format(self.domain))
            self.identifier = self.domain

            alias = w.config_get_plugin("server_alias.{}".format(login_data["team"]["domain"]))
            if alias:
                self.server_buffer_name = alias
            else:
                self.server_buffer_name = self.domain

            self.nick = login_data["self"]["name"]
            self.create_local_buffer()

            if self.create_slack_websocket(login_data):
                if self.ping_hook:
                    w.unhook(self.ping_hook)
                    self.communication_counter = 0
                self.ping_hook = w.hook_timer(1000 * 5, 0, 0, "slack_ping_cb", self.domain)
                if len(self.users) == 0 or len(self.channels) == 0:
                    self.create_slack_mappings(login_data)

                self.connected = True
                self.connecting = False

                self.print_connection_info(login_data)
                if len(self.message_buffer) > 0:
                    for message_id in self.message_buffer.keys():
                        if self.message_buffer[message_id]["type"] != 'ping':
                            resend = self.message_buffer.pop(message_id)
                            dbg("Resent failed message.")
                            self.send_to_websocket(resend)<commit_msg>Make /slack talk and friends work when server_alias is set<commit_after># -*- coding: utf-8 -*-
#

from functools import wraps
import time
import json
import os
import pickle
import sha
import re
import urllib
import HTMLParser
import sys
import traceback
import collections
from websocket import create_connection,WebSocketConnectionClosedException

# hack to make tests possible.. better way?
try:
    import weechat as w
except:
    pass

SCRIPT_NAME = "slack_extension"
SCRIPT_AUTHOR = "<NAME> <<EMAIL>>"
SCRIPT_VERSION = "0.99.3"
SCRIPT_LICENSE = "MIT"
SCRIPT_DESC = "Extends weechat for typing notification/search/etc on slack.com"

BACKLOG_SIZE = 200
SCROLLBACK_SIZE = 500

CACHE_VERSION = "3"

SLACK_API_TRANSLATOR = {
    "channel": {
        "history": "channels.history",
        "join": "channels.join",
        "leave": "channels.leave",
        "mark": "channels.mark",
        "info": "channels.info",
    },
    "im": {
        "history": "im.history",
        "join": "im.open",
        "leave": "im.close",
        "mark": "im.mark",
    },
    "group": {
        "history": "groups.history",
        "join": "channels.join",
        "leave": "groups.leave",
        "mark": "groups.mark",
    }

}

NICK_GROUP_HERE = "0|Here"
NICK_GROUP_AWAY = "1|Away"

def dbg(message, fout=False, main_buffer=False):
    """
    send debug output to the slack-debug buffer and optionally write to a file.
    """
    message = "DEBUG: {}".format(message)
    #message = message.encode('utf-8', 'replace')
    if fout:
        file('/tmp/debug.log', 'a+').writelines(message + '\n')
    if main_buffer:
            w.prnt("", message)
    else:
        if slack_debug is not None:
            w.prnt(slack_debug, message)


class SearchList(list):
    """
    A normal python list with some syntactic sugar for searchability
    """
    def __init__(self):
        self.hashtable = {}
        super(SearchList, self).__init__(self)

    def find(self, name):
        if name in self.hashtable.keys():
            return self.hashtable[name]
        #this is a fallback to __eq__ if the item isn't in the hashtable already
        if self.count(name) > 0:
            self.update_hashtable()
            return self[self.index(name)]

    def append(self, item, aliases=[]):
        super(SearchList, self).append(item)
        self.update_hashtable()

    def update_hashtable(self):
        for child in self:
            if hasattr(child, "get_aliases"):
                for alias in child.get_aliases():
                    if alias is not None:
                        self.hashtable[alias] = child

    def find_by_class(self, class_name):
        items = []
        for child in self:
            if child.__class__ == class_name:
                items.append(child)
        return items

    def find_by_class_deep(self, class_name, attribute):
        items = []
        for child in self:
            if child.__class__ == self.__class__:
                items += child.find_by_class_deep(class_name, attribute)
            else:
                items += (eval('child.' + attribute).find_by_class(class_name))
        return items


class SlackServer(object):
    """
    Root object used to represent connection and state of the connection to a slack group.
    """
    def __init__(self, token):
        self.nick = None
        self.name = None
        self.domain = None
        self.server_buffer_name = None
        self.login_data = None
        self.buffer = None
        self.token = token
        self.ws = None
        self.ws_hook = None
        self.users = SearchList()
        self.bots = SearchList()
        self.channels = SearchList()
        self.connecting = False
        self.connected = False
        self.communication_counter = 0
        self.message_buffer = {}
        self.ping_hook = None
        self.alias = None

        self.identifier = None
        self.connect_to_slack()

    def __eq__(self, compare_str):
        if compare_str == self.identifier or compare_str == self.token or compare_str == self.buffer:
            return True
        else:
            return False

    def __str__(self):
        return "{}".format(self.identifier)

    def __repr__(self):
        return "{}".format(self.identifier)

    def add_user(self, user):
        self.users.append(user, user.get_aliases())
        users.append(user, user.get_aliases())

    def add_bot(self, bot):
        self.bots.append(bot)

    def add_channel(self, channel):
        self.channels.append(channel, channel.get_aliases())
        channels.append(channel, channel.get_aliases())

    def get_aliases(self):
        aliases = filter(None, [self.identifier, self.token, self.buffer, self.alias])
        return aliases

    def find(self, name, attribute):
        attribute = eval("self." + attribute)
        return attribute.find(name)

    def get_communication_id(self):
        if self.communication_counter > 999:
            self.communication_counter = 0
        self.communication_counter += 1
        return self.communication_counter

    def send_to_websocket(self, data, expect_reply=True):
        data["id"] = self.get_communication_id()
        message = json.dumps(data)
        try:
            if expect_reply:
                self.message_buffer[data["id"]] = data
            self.ws.send(message)
            dbg("Sent {}...".format(message[:100]))
        except:
            dbg("Unexpected error: {}\nSent: {}".format(sys.exc_info()[0], data))
            self.connected = False

    def ping(self):
        request = {"type": "ping"}
        self.send_to_websocket(request)

    def connect_to_slack(self):
        t = time.time()
        if not self.connecting:
            async_slack_api_request("slack.com", self.token, "rtm.start", {"ts": t})
            self.connecting = True

    def connected_to_slack(self, login_data):
        if login_data["ok"]:
            self.domain = login_data["team"]["domain"] + ".slack.com"
            dbg("connected to {}".format(self.domain))
            self.identifier = self.domain

            alias = w.config_get_plugin("server_alias.{}".format(login_data["team"]["domain"]))
            if alias:
                self.server_buffer_name = alias
                self.alias = alias
            else:
                self.server_buffer_name = self.domain

            self.nick = login_data["self"]["name"]
            self.create_local_buffer()

            if self.create_slack_websocket(login_data):
                if self.ping_hook:
                    w.unhook(self.ping_hook)
                    self.communication_counter = 0
                self.ping_hook = w.hook_timer(1000 * 5, 0, 0, "slack_ping_cb", self.domain)
                if len(self.users) == 0 or len(self.channels) == 0:
                    self.create_slack_mappings(login_data)

                self.connected = True
                self.connecting = False

                self.print_connection_info(login_data)
                if len(self.message_buffer) > 0:
                    for message_id in self.message_buffer.keys():
                        if self.message_buffer[message_id]["type"] != 'ping':
                            resend = self.message_buffer.pop(message_id)
                            dbg("Resent failed message.")
                            self.send_to_websocket(resend)
{'fraction_non_alphanumeric': 0.11345574129898603, 'fraction_numerical': 0.005069882159495752, 'mean_word_length': 2.1044236495108466, 'pattern_counts': {'":': 36, '<': 9, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, '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': '1143678', 'n_tokens_mistral': 4419, 'n_tokens_neox': 4224, 'n_words': 994}