diff options
-rw-r--r-- | README.md | 42 | ||||
-rw-r--r-- | wee_slack.py | 96 |
2 files changed, 99 insertions, 39 deletions
@@ -44,7 +44,7 @@ In Development Dependencies ------------ - * WeeChat 1.3+ http://weechat.org/ + * WeeChat 1.3+ http://weechat.org/ * websocket-client https://pypi.python.org/pypi/websocket-client/ Setup @@ -86,11 +86,13 @@ cp wee_slack.py ~/.weechat/python/autoload weechat ``` +**NOTE:** If weechat is already running, the script can be loaded using ``/python load python/autoload/wee_slack.py`` + ####4. Add your Slack API key(s) ``` /set plugins.var.python.slack_extension.slack_api_token [YOUR_SLACK_TOKEN] ``` -^^ (find this at https://api.slack.com/web) +^^ (find this at https://api.slack.com/web behind the "Generate test tokens" button) If you don't want to store your API token in plaintext you can use the secure features of weechat: @@ -101,7 +103,7 @@ If you don't want to store your API token in plaintext you can use the secure fe ``` ##### Optional: If you would like to connect to multiple groups, use the above command with multiple tokens separated by commas. (NO SPACES) - + ``` /set plugins.var.python.slack_extension.slack_api_token [token1],[token2],[token3] ``` @@ -165,16 +167,6 @@ Add a reaction to the nth last message. The number can be omitted and defaults t 3+:smile: ``` -Turn off colorized nicks: -``` -/set plugins.var.python.slack_extension.colorize_nicks 0 -``` - -Set channel prefix to something other than my-slack-subdomain.slack.com (e.g. when using buffers.pl): -``` -/set plugins.var.python.slack_extension.server_alias.my-slack-subdomain "mysub" -``` - Set all read markers to a specific time: ``` /slack setallreadmarkers (time in epoch) @@ -191,7 +183,27 @@ Debug mode: ``` Optional settings ----------------- +----------------- + +Turn off colorized nicks: +``` +/set plugins.var.python.slack_extension.colorize_nicks 0 +``` + +Turn on colorized messages (messages match nick color): +``` +/set plugins.var.python.slack_extension.colorize_nicks 1 +``` + +Set channel prefix to something other than my-slack-subdomain.slack.com (e.g. when using buffers.pl): +``` +/set plugins.var.python.slack_extension.server_alias.my-slack-subdomain "mysub" +``` + +Show who added each reaction. Makes reactions appear like `[:smile:(@nick1,@nick2)]` instead of `[:smile:2]`. +``` +/set plugins.var.python.slack_extension.show_reaction_nicks on +``` Show typing notification in main bar (slack_typing_notice): ``` @@ -211,4 +223,4 @@ wee-slack is provided without any warranty whatsoever, but you are welcome to as - + diff --git a/wee_slack.py b/wee_slack.py index 68cfbc2..5b0adaf 100644 --- a/wee_slack.py +++ b/wee_slack.py @@ -32,7 +32,7 @@ SCRIPT_DESC = "Extends weechat for typing notification/search/etc on slack.com" BACKLOG_SIZE = 200 SCROLLBACK_SIZE = 500 -CACHE_VERSION = "3" +CACHE_VERSION = "4" SLACK_API_TRANSLATOR = { "channel": { @@ -286,7 +286,7 @@ class SlackServer(object): def create_slack_mappings(self, data): for item in data["users"]: - self.add_user(User(self, item["name"], item["id"], item["presence"], item["deleted"])) + self.add_user(User(self, item["name"], item["id"], item["presence"], item["deleted"], is_bot=item.get('is_bot', False))) for item in data["bots"]: self.add_bot(Bot(self, item["name"], item["id"], item["deleted"])) @@ -642,7 +642,10 @@ class Channel(object): if self.channel_buffer: prefix_same_nick = w.config_string(w.config_get('weechat.look.prefix_same_nick')) if user == self.last_active_user and prefix_same_nick != "": - name = prefix_same_nick + if colorize_nicks and self.server.users.find(user): + name = self.server.users.find(user).color + prefix_same_nick + else: + name = prefix_same_nick else: nick_prefix = w.config_string(w.config_get('weechat.look.nick_prefix')) nick_suffix = w.config_string(w.config_get('weechat.look.nick_suffix')) @@ -660,11 +663,16 @@ class Channel(object): chat_color = w.config_string(w.config_get('weechat.color.chat')) if type(message) is not unicode: message = message.decode('UTF-8', 'replace') + curr_color = w.color(chat_color) + if colorize_nicks and colorize_messages and self.server.users.find(user): + curr_color = self.server.users.find(user).color + message = curr_color + message for user in self.server.users: if user.name in message: message = user.name_regex.sub( - r'\1\2{}\3'.format(user.formatted_name() + w.color(chat_color)), + r'\1\2{}\3'.format(user.formatted_name() + curr_color), message) + message = HTMLParser.HTMLParser().unescape(message) data = u"{}\t{}".format(name, message).encode('utf-8') w.prnt_date_tags(self.channel_buffer, time_int, tags, data) @@ -710,17 +718,17 @@ class Channel(object): self.buffer_redraw() return True - def add_reaction(self, ts, reaction): + def add_reaction(self, ts, reaction, user): if self.has_message(ts): message_index = self.messages.index(ts) - self.messages[message_index].add_reaction(reaction) + self.messages[message_index].add_reaction(reaction, user) self.change_message(ts) return True - def remove_reaction(self, ts, reaction): + def remove_reaction(self, ts, reaction, user): if self.has_message(ts): message_index = self.messages.index(ts) - self.messages[message_index].remove_reaction(reaction) + self.messages[message_index].remove_reaction(reaction, user) self.change_message(ts) return True @@ -803,7 +811,7 @@ class DmChannel(Channel): class User(object): - def __init__(self, server, name, identifier, presence="away", deleted=False): + def __init__(self, server, name, identifier, presence="away", deleted=False, is_bot=False): self.server = server self.name = name self.identifier = identifier @@ -813,6 +821,7 @@ class User(object): self.channel_buffer = w.info_get("irc_buffer", "{}.{}".format(domain, self.name)) self.update_color() self.name_regex = re.compile(r"([\W]|\A)(@{0,1})" + self.name + "('s|[^'\w]|\Z)") + self.is_bot = is_bot if deleted: return @@ -931,23 +940,23 @@ class Message(object): new_text = unicode(new_text, 'utf-8') self.message_json["text"] = new_text - def add_reaction(self, reaction): + def add_reaction(self, reaction, user): if "reactions" in self.message_json: found = False for r in self.message_json["reactions"]: if r["name"] == reaction: - r["count"] += 1 + r["users"].add(user) found = True if not found: - self.message_json["reactions"].append({u"count": 1, u"name": reaction}) + self.message_json["reactions"].append({u"name": reaction, u"users": {user}}) else: - self.message_json["reactions"] = [{u"count": 1, u"name": reaction}] + self.message_json["reactions"] = [{u"name": reaction, u"users": {user}}] - def remove_reaction(self, reaction): + def remove_reaction(self, reaction, user): if "reactions" in self.message_json: for r in self.message_json["reactions"]: if r["name"] == reaction: - r["count"] -= 1 + r["users"].remove(user) else: pass @@ -985,7 +994,11 @@ def me_command_cb(data, current_buffer, args): def join_command_cb(data, current_buffer, args): - if command_talk(current_buffer, args.split()[1]): + args = args.split() + if len(args) < 2: + w.prnt(current_buffer, "Missing channel argument") + return w.WEECHAT_RC_OK_EAT + elif command_talk(current_buffer, args[1]): return w.WEECHAT_RC_OK_EAT else: return w.WEECHAT_RC_OK @@ -1526,6 +1539,25 @@ def process_user_typing(message_json): channel.set_typing(server.users.find(message_json["user"]).name) +def process_bot_enable(message_json): + process_bot_integration(message_json) + + +def process_bot_disable(message_json): + process_bot_integration(message_json) + + +def process_bot_integration(message_json): + server = servers.find(message_json["_server"]) + channel = server.channels.find(message_json["channel"]) + + time = message_json['ts'] + text = "{} {}".format(server.users.find(message_json['user']).formatted_name(), + render_message(message_json)) + bot_name = get_user(message_json, server) + bot_name = bot_name.encode('utf-8') + channel.buffer_prnt(bot_name, text, time) + # todo: does this work? def process_error(message_json): @@ -1534,14 +1566,14 @@ def process_error(message_json): def process_reaction_added(message_json): if message_json["item"].get("type") == "message": channel = channels.find(message_json["item"]["channel"]) - channel.add_reaction(message_json["item"]["ts"], message_json["reaction"]) + channel.add_reaction(message_json["item"]["ts"], message_json["reaction"], message_json["user"]) else: dbg("Reaction to item type not supported: " + str(message_json)) def process_reaction_removed(message_json): if message_json["item"].get("type") == "message": channel = channels.find(message_json["item"]["channel"]) - channel.remove_reaction(message_json["item"]["ts"], message_json["reaction"]) + channel.remove_reaction(message_json["item"]["ts"], message_json["reaction"], message_json["user"]) else: dbg("Reaction to item type not supported: " + str(message_json)) @@ -1552,9 +1584,14 @@ def create_reaction_string(reactions): else: reaction_string = ' [' for r in reactions: - if r["count"] > 0: + if len(r["users"]) > 0: count += 1 - reaction_string += ":{}:{} ".format(r["name"], r["count"]) + if show_reaction_nicks: + nicks = [resolve_ref("@{}".format(user)) for user in r["users"]] + users = "({})".format(",".join(nicks)) + else: + users = len(r["users"]) + reaction_string += ":{}:{} ".format(r["name"], users) reaction_string = reaction_string[:-1] + ']' if count == 0: reaction_string = '' @@ -1624,7 +1661,7 @@ def render_message(message_json, force=False): def process_message(message_json, cache=True): try: # send these subtype messages elsewhere - known_subtypes = ["message_changed", 'message_deleted', 'channel_join', 'channel_leave', 'channel_topic'] + known_subtypes = ["message_changed", 'message_deleted', 'channel_join', 'channel_leave', 'channel_topic', 'bot_enable', 'bot_disable'] if "subtype" in message_json and message_json["subtype"] in known_subtypes: proc[message_json["subtype"]](message_json) @@ -1794,7 +1831,11 @@ def get_user(message_json, server): if 'bot_id' in message_json and message_json['bot_id'] is not None: name = u"{} :]".format(server.bots.find(message_json["bot_id"]).formatted_name()) elif 'user' in message_json: - name = server.users.find(message_json['user']).name + u = server.users.find(message_json['user']) + if u.is_bot: + name = u"{} :]".format(u.formatted_name()) + else: + name = u.name elif 'username' in message_json: name = u"-{}-".format(message_json["username"]) elif 'service_name' in message_json: @@ -2124,7 +2165,7 @@ def create_slack_debug_buffer(): def config_changed_cb(data, option, value): global slack_api_token, distracting_channels, colorize_nicks, colorize_private_chats, slack_debug, debug_mode, \ - unfurl_ignore_alt_text + unfurl_ignore_alt_text, colorize_messages, show_reaction_nicks slack_api_token = w.config_get_plugin("slack_api_token") @@ -2133,10 +2174,12 @@ def config_changed_cb(data, option, value): distracting_channels = [x.strip() for x in w.config_get_plugin("distracting_channels").split(',')] colorize_nicks = w.config_get_plugin('colorize_nicks') == "1" + colorize_messages = w.config_get_plugin("colorize_messages") == "1" debug_mode = w.config_get_plugin("debug_mode").lower() if debug_mode != '' and debug_mode != 'false': create_slack_debug_buffer() colorize_private_chats = w.config_string_to_boolean(w.config_get_plugin("colorize_private_chats")) + show_reaction_nicks = w.config_string_to_boolean(w.config_get_plugin("show_reaction_nicks")) unfurl_ignore_alt_text = False if w.config_get_plugin('unfurl_ignore_alt_text') != "0": @@ -2197,6 +2240,8 @@ if __name__ == "__main__": w.config_set_plugin('debug_mode', "") if not w.config_get_plugin('colorize_nicks'): w.config_set_plugin('colorize_nicks', "1") + if not w.config_get_plugin('colorize_messages'): + w.config_set_plugin('colorize_messages', "0") if not w.config_get_plugin('colorize_private_chats'): w.config_set_plugin('colorize_private_chats', "0") if not w.config_get_plugin('trigger_value'): @@ -2205,8 +2250,11 @@ if __name__ == "__main__": w.config_set_plugin('unfurl_ignore_alt_text', "0") if not w.config_get_plugin('switch_buffer_on_join'): w.config_set_plugin('switch_buffer_on_join', "1") + if not w.config_get_plugin('show_reaction_nicks'): + w.config_set_plugin('show_reaction_nicks', "0") - w.config_option_unset('channels_not_on_current_server_color') + if w.config_get_plugin('channels_not_on_current_server_color'): + w.config_option_unset('channels_not_on_current_server_color') # Global var section slack_debug = None |