diff options
author | Johannes Löthberg <johannes@kyriasis.com> | 2017-06-08 00:41:34 +0200 |
---|---|---|
committer | Johannes Löthberg <johannes@kyriasis.com> | 2017-06-08 00:41:34 +0200 |
commit | 9c7030c38c3a5086b63709088ef259a5cf42399e (patch) | |
tree | 029005e45466b868d1ad76829542f93f87d13959 | |
parent | 37dc8851acabe40502a3329cfb5f77fd981a3f98 (diff) | |
download | dotfiles-9c7030c38c3a5086b63709088ef259a5cf42399e.tar.xz |
weechat: Delete autojoin_on_invite and wee_slack
Signed-off-by: Johannes Löthberg <johannes@kyriasis.com>
-rw-r--r-- | weechat/python/autojoin_on_invite.py | 119 | ||||
-rw-r--r-- | weechat/python/wee_slack.py | 1690 |
2 files changed, 0 insertions, 1809 deletions
diff --git a/weechat/python/autojoin_on_invite.py b/weechat/python/autojoin_on_invite.py deleted file mode 100644 index 45adab5..0000000 --- a/weechat/python/autojoin_on_invite.py +++ /dev/null @@ -1,119 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (c) 2009 by xt <xt@bash.no> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# - -# -# (this script requires WeeChat 0.3.0 or newer) -# -# History: -# 2015-10-11, Simmo Saan <simmo.saan@gmail.com> -# version 0.6: allow joining channels with keys in autojoin -# 2013-12-21, Sebastien Helleu <flashcode@flashtux.org> -# version 0.5: fix parsing of INVITE message -# 2013-11-28, sakkemo <scajanus@gmail.com> -# version 0.4: add whitelist for nicks/channels -# 2009-11-09, xt <xt@bash.no> -# version 0.3: add ignore option for channels -# 2009-10-29, xt <xt@bash.no> -# version 0.2: add ignore option -# 2009-10-28, xt <xt@bash.no> -# version 0.1: initial release - -import weechat as w -import re - -SCRIPT_NAME = "autojoin_on_invite" -SCRIPT_AUTHOR = "xt <xt@bash.no>" -SCRIPT_VERSION = "0.6" -SCRIPT_LICENSE = "GPL3" -SCRIPT_DESC = "Auto joins channels when invited" - -# script options -settings = { - 'whitelist_nicks': '', # comma separated list of nicks, - # overrides ignore_nicks - 'whitelist_channels': '', # comma separated list of channels, - # overrides ignore_channels - 'ignore_nicks': '', # comma separated list of nicks - #that we will not accept auto invite from - 'ignore_channels': '', # comma separated list of channels to not join - 'autojoin_key': 'on', # use channel keys from server's autojoin list -} - -if w.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE, - SCRIPT_DESC, "", ""): - for option, default_value in settings.iteritems(): - if not w.config_is_set_plugin(option): - w.config_set_plugin(option, default_value) - - w.hook_signal('*,irc_in2_invite', 'invite_cb', '') - -def join(server, channel): - key = None - - if w.config_string_to_boolean(w.config_get_plugin('autojoin_key')): - autojoin = w.config_string(w.config_get('irc.server.%s.autojoin' % server)).split(' ', 1) - - if len(autojoin) > 1: # any keys specified - autojoin_keys = dict(zip(autojoin[0].split(','), autojoin[1].split(','))) - key = autojoin_keys.get(channel) # defaults to None when not set - - if key: - w.command('', '/quote -server %s JOIN %s %s' % (server, channel, key)) - else: - w.command('', '/quote -server %s JOIN %s' % (server, channel)) - -def invite_cb(data, signal, signal_data): - server = signal.split(',')[0] # EFNet,irc_in_INVITE - channel = signal_data.split()[-1].lstrip(':') # :nick!ident@host.name INVITE yournick :#channel - from_nick = re.match(':(?P<nick>.+)!', signal_data).groups()[0] - - if len(w.config_get_plugin('whitelist_nicks')) > 0 and len(w.config_get_plugin('whitelist_channels')) > 0: # if there's two whitelists, accept both - if from_nick in w.config_get_plugin('whitelist_nicks').split(',') or channel in w.config_get_plugin('whitelist_channels').split(','): - w.prnt('', 'Automatically joining %s on server %s, invitation from %s (whitelist).' \ - %(channel, server, from_nick)) - join(server, channel) - else: - w.prnt('', 'Ignoring invite from %s to channel %s. Neither inviter nor channel in whitelist.' %(from_nick, channel)) - - elif len(w.config_get_plugin('whitelist_nicks')) > 0: # if there's a whitelist, accept nicks in it - if from_nick in w.config_get_plugin('whitelist_nicks').split(','): - w.prnt('', 'Automatically joining %s on server %s, invitation from %s (whitelist).' \ - %(channel, server, from_nick)) - join(server, channel) - else: - w.prnt('', 'Ignoring invite from %s to channel %s. Inviter not in whitelist.' %(from_nick, channel)) - - elif len(w.config_get_plugin('whitelist_channels')) > 0: # if there's a whitelist, accept channels in it - if channel in w.config_get_plugin('whitelist_channels').split(','): - w.prnt('', 'Automatically joining %s on server %s, invitation from %s (whitelist).' \ - %(channel, server, from_nick)) - join(server, channel) - else: - w.prnt('', 'Ignoring invite from %s to channel %s. Channel not in whitelist.' %(from_nick, channel)) - - else: # use the ignore lists to make the decision - if from_nick in w.config_get_plugin('ignore_nicks').split(','): - w.prnt('', 'Ignoring invite from %s to channel %s. Invite from ignored inviter.' %(from_nick, channel)) - elif channel in w.config_get_plugin('ignore_channels').split(','): - w.prnt('', 'Ignoring invite from %s to channel %s. Invite to ignored channel.' %(from_nick, channel)) - else: - w.prnt('', 'Automatically joining %s on server %s, invitation from %s.' \ - %(channel, server, from_nick)) - join(server, channel) - - return w.WEECHAT_RC_OK diff --git a/weechat/python/wee_slack.py b/weechat/python/wee_slack.py deleted file mode 100644 index c2e8cb3..0000000 --- a/weechat/python/wee_slack.py +++ /dev/null @@ -1,1690 +0,0 @@ -# -*- coding: utf-8 -*- -# -from functools import wraps -import time -import json -import pickle -import sha -import re -import urllib -import urlparse -import HTMLParser -from websocket import create_connection - -# hack to make tests possible.. better way? -try: - import weechat as w -except: - pass - -SCRIPT_NAME = "slack_extension" -SCRIPT_AUTHOR = "Ryan Huber <rhuber@gmail.com>" -SCRIPT_VERSION = "0.97.22" -SCRIPT_LICENSE = "MIT" -SCRIPT_DESC = "Extends weechat for typing notification/search/etc on slack.com" - -BACKLOG_SIZE = 200 - -SLACK_API_TRANSLATOR = { - "channel": { - "history": "channels.history", - "join": "channels.join", - "leave": "channels.leave", - "mark": "channels.mark", - "info": "channels.info", - }, - "im": { - "history": "im.history", - "leave": "im.close", - "mark": "im.mark", - }, - "group": { - "history": "groups.history", - "join": "channels.join", - "leave": "groups.leave", - "mark": "groups.mark", - } - -} - -def dbg(message, fout=False, main_buffer=False): - 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) - -# hilarious, i know - - -class Meta(list): - - def __init__(self, attribute, search_list): - self.attribute = attribute - self.search_list = search_list - - def __str__(self): - string = '' - for each in self.search_list.get_all(self.attribute): - string += "{} ".format(each) - return string - - def __repr__(self): - self.search_list.get_all(self.attribute) - - def __getitem__(self, index): - things = self.get_all() - return things[index] - - def __iter__(self): - things = self.get_all() - for channel in things: - yield channel - - def get_all(self): - items = [] - items += self.search_list.get_all(self.attribute) - return items - - def find(self, name): - items = self.search_list.find_deep(name, self.attribute) - items = [x for x in items if x is not None] - if len(items) == 1: - return items[0] - elif len(items) == 0: - pass - else: - dbg("probably something bad happened with meta items: {}".format(items)) - return items - #raise AmbiguousProblemError - - def find_first(self, name): - items = self.find(name) - if items.__class__ == list: - return items[0] - else: - return False - - def find_by_class(self, class_name): - items = self.search_list.find_by_class_deep(class_name, self.attribute) - return items - - -class SearchList(list): - - def find(self, name): - items = [] - for child in self: - if child.__class__ == self.__class__: - items += child.find(name) - else: - if child == name: - items.append(child) - if len(items) == 1: - return items[0] - elif items != []: - return items - - def find_deep(self, name, attribute): - items = [] - for child in self: - if child.__class__ == self.__class__: - if items is not None: - items += child.find_deep(name, attribute) - elif dir(child).count('find') == 1: - if items is not None: - items.append(child.find(name, attribute)) - if items != []: - return items - - def get_all(self, attribute): - items = [] - for child in self: - if child.__class__ == self.__class__: - items += child.get_all(attribute) - else: - items += (eval("child." + attribute)) - return items - - 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): - - def __init__(self, token): - self.nick = None - self.name = None - self.domain = None - self.login_data = None - self.buffer = None - self.token = token - self.ws = None - self.ws_hook = None - self.users = SearchList() - self.channels = SearchList() - self.connecting = False - self.connected = False - self.communication_counter = 0 - self.message_buffer = {} - self.ping_hook = None - self.failed_message = 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 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): - data["id"] = self.get_communication_id() - message = json.dumps(data) - try: - self.message_buffer[data["id"]] = data - self.ws.send(message) - dbg("Sent {}...".format(message[:100])) - except: - self.failed_message = 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 - 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) and 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 self.failed_message: - dbg("Resent failed message.") - self.send_to_websocket(self.failed_message) - self.failed_message = None - return True - else: - w.prnt("", "\n!! slack.com login error: " + login_data["error"] + "\n Please check your API token with\n \"/set plugins.var.python.slack_extension.slack_api_token (token)\"\n\n ") - self.connected = False - - def print_connection_info(self, login_data): - self.buffer_prnt('Connected to Slack', backlog=True) - self.buffer_prnt('{:<20} {}'.format("Websocket URL", login_data["url"]), backlog=True) - self.buffer_prnt('{:<20} {}'.format("User name", login_data["self"]["name"]), backlog=True) - self.buffer_prnt('{:<20} {}'.format("User ID", login_data["self"]["id"]), backlog=True) - self.buffer_prnt('{:<20} {}'.format("Team name", login_data["team"]["name"]), backlog=True) - self.buffer_prnt('{:<20} {}'.format("Team domain", login_data["team"]["domain"]), backlog=True) - self.buffer_prnt('{:<20} {}'.format("Team id", login_data["team"]["id"]), backlog=True) - - def create_local_buffer(self): - if not w.buffer_search("", self.domain): - self.buffer = w.buffer_new(self.domain, "buffer_input_cb", "", "", "") - w.buffer_set(self.buffer, "nicklist", "1") - - def create_slack_websocket(self, data): - web_socket_url = data['url'] - try: - self.ws = create_connection(web_socket_url) - self.ws_hook = w.hook_fd(self.ws.sock._sock.fileno(), 1, 0, 0, "slack_websocket_cb", self.identifier) - self.ws.sock.setblocking(0) - return True - except: - return False - - def create_slack_mappings(self, data): - - for item in data["users"]: - self.users.append(User(self, item["name"], item["id"], item["presence"])) - - for item in data["channels"]: - if "last_read" not in item: - item["last_read"] = 0 - if "members" not in item: - item["members"] = [] - if "topic" not in item: - item["topic"] = {} - item["topic"]["value"] = "" - if not item["is_archived"]: - self.channels.append(Channel(self, item["name"], item["id"], item["is_member"], item["last_read"], "#", item["members"], item["topic"]["value"])) - for item in data["groups"]: - if "last_read" not in item: - item["last_read"] = 0 - if not item["is_archived"]: - self.channels.append(GroupChannel(self, item["name"], item["id"], item["is_open"], item["last_read"], "#", item["members"], item["topic"]["value"])) - for item in data["ims"]: - if "last_read" not in item: - item["last_read"] = 0 - name = self.users.find(item["user"]).name - self.channels.append(DmChannel(self, name, item["id"], item["is_open"], item["last_read"])) - - for item in self.channels: - item.get_history() - - def buffer_prnt(self, message='no message', user="SYSTEM", backlog=False): - message = message.encode('ascii', 'ignore') - if backlog: - tags = "no_highlight,notify_none,logger_backlog_end" - else: - tags = "" - if self.buffer: - w.prnt_date_tags(self.buffer, 0, tags, "{}\t{}".format(user, message)) - else: - pass - #w.prnt("", "%s\t%s" % (user, message)) - - -class SlackThing(object): - - def __init__(self, name, identifier): - self.name = name - self.identifier = identifier - self.channel_buffer = None - - def __str__(self): - return self.name - - def __repr__(self): - return self.name - - -def buffer_input_cb(b, buffer, data): - if not data.startswith('s/'): - channel = channels.find(buffer) - channel.send_message(data) - channel.buffer_prnt(channel.server.nick, data) - elif data.count('/') == 3: - old, new = data.split('/')[1:3] - channel = channels.find(buffer) - channel.change_previous_message(old, new) - channel.mark_read(True) - return w.WEECHAT_RC_ERROR - - -class Channel(SlackThing): - - def __init__(self, server, name, identifier, active, last_read=0, prepend_name="", members=[], topic=""): - super(Channel, self).__init__(name, identifier) - self.type = "channel" - self.server = server - self.name = prepend_name + self.name - self.typing = {} - self.active = active - self.opening = False - self.members = set(members) - self.topic = topic - self.last_read = float(last_read) - self.last_received = None - if active: - self.create_buffer() - self.attach_buffer() - self.update_nicklist() - self.set_topic(self.topic) - buffer_list_update_next() - - def __eq__(self, compare_str): - if compare_str == self.fullname() or compare_str == self.name or compare_str == self.identifier or compare_str == self.name[1:] or (compare_str == self.channel_buffer and self.channel_buffer is not None): - return True - else: - return False - - def create_buffer(self): - channel_buffer = w.buffer_search("", "{}.{}".format(self.server.domain, self.name)) - if channel_buffer: - self.channel_buffer = channel_buffer - else: - self.channel_buffer = w.buffer_new("{}.{}".format(self.server.domain, self.name), "buffer_input_cb", self.name, "", "") - if self.type == "im": - w.buffer_set(self.channel_buffer, "localvar_set_type", 'private') - else: - w.buffer_set(self.channel_buffer, "localvar_set_type", 'channel') - w.buffer_set(self.channel_buffer, "short_name", 'loading..') - - def attach_buffer(self): - channel_buffer = w.buffer_search("", "{}.{}".format(self.server.domain, self.name)) - if channel_buffer != main_weechat_buffer: - self.channel_buffer = channel_buffer -# w.buffer_set(self.channel_buffer, "highlight_words", self.server.nick) - else: - self.channel_buffer = None - - def detach_buffer(self): - if self.channel_buffer is not None: - w.buffer_close(self.channel_buffer) - self.channel_buffer = None - - def update_nicklist(self): - if self.channel_buffer: - w.buffer_set(self.channel_buffer, "nicklist", "1") - w.nicklist_remove_all(self.channel_buffer) - try: - for user in self.members: - user = self.server.users.find(user) - if user.presence == 'away': - w.nicklist_add_nick(self.channel_buffer, "", user.name, user.color_name, " ", "", 1) - else: - w.nicklist_add_nick(self.channel_buffer, "", user.name, user.color_name, "+", "", 1) - except: - print "DEBUG: {} {}".format(self.identifier,self.name) - - def fullname(self): - return "{}.{}".format(self.server.domain, self.name) - - def has_user(self, name): - return name in self.members - - def user_join(self, name): - self.members.add(name) - self.update_nicklist() - - def user_leave(self, name): - if name in self.members: - self.members.remove(name) - self.update_nicklist() - - def set_active(self): - self.active = True - - def set_inactive(self): - self.active = False - - def set_typing(self, user): - self.typing[user] = time.time() - buffer_list_update_next() - - def unset_typing(self, user): - try: - del self.typing[user] - buffer_list_update_next() - except: - pass - - def send_message(self, message): - message = self.linkify_text(message) - dbg(message) - request = {"type": "message", "channel": self.identifier, "text": message, "myserver": self.server.domain} - self.server.send_to_websocket(request) - - def linkify_text(self, message): - message = message.split(' ') - for item in enumerate(message): - if item[1].startswith('@'): - named = re.match('.*[@#](\w+)(\W*)', item[1]).groups() - if named[0] in ["group", "channel"]: - message[item[0]] = "<!{}>".format(named[0]) - if self.server.users.find(named[0]): - message[item[0]] = "<@{}>{}".format(self.server.users.find(named[0]).identifier, named[1]) - if item[1].startswith('#') and self.server.channels.find(item[1]): - named = re.match('.*[@#](\w+)(\W*)', item[1]).groups() - if self.server.channels.find(named[0]): - message[item[0]] = "<#{}>{}".format(self.server.channels.find(named[0]).identifier, named[1]) - dbg(message) - return " ".join(message) - - def set_topic(self, topic): - topic = topic.encode('ascii', 'ignore') - w.buffer_set(self.channel_buffer, "title", topic) - - def open(self, update_remote=True): - self.opening = True - self.create_buffer() - self.active = True - self.get_history() - if "info" in SLACK_API_TRANSLATOR[self.type]: - async_slack_api_request(self.server.domain, self.server.token, SLACK_API_TRANSLATOR[self.type]["info"], {"name": self.name.lstrip("#")}) - if update_remote: - if "join" in SLACK_API_TRANSLATOR[self.type]: - async_slack_api_request(self.server.domain, self.server.token, SLACK_API_TRANSLATOR[self.type]["join"], {"name": self.name.lstrip("#")}) - self.opening = False - - def close(self, update_remote=True): - #remove from cache so messages don't reappear when reconnecting - if self.active: - self.active = False - self.detach_buffer() - if update_remote: - t = time.time() - async_slack_api_request(self.server.domain, self.server.token, SLACK_API_TRANSLATOR[self.type]["leave"], {"channel": self.identifier}) - - def closed(self): - message_cache.pop(self.identifier) - self.channel_buffer = None - self.last_received = None - self.close() - - def is_someone_typing(self): - for user in self.typing.keys(): - if self.typing[user] + 4 > time.time(): - return True - if len(self.typing) > 0: - self.typing = {} - buffer_list_update_next() - return False - - def get_typing_list(self): - typing = [] - for user in self.typing.keys(): - if self.typing[user] + 4 > time.time(): - typing.append(user) - return typing - - def mark_read(self, update_remote=True): - t = time.time() - - if self.channel_buffer: - w.buffer_set(self.channel_buffer, "unread", "") - if update_remote: - self.last_read = time.time() - self.update_read_marker(self.last_read) - - def update_read_marker(self, time): - async_slack_api_request(self.server.domain, self.server.token, SLACK_API_TRANSLATOR[self.type]["mark"], {"channel": self.identifier, "ts": time}) - - def rename(self): - if current_domain_name() != self.server.domain and channels_not_on_current_server_color: - color = w.color(channels_not_on_current_server_color) - else: - color = "" - if self.is_someone_typing(): - new_name = ">{}".format(self.name[1:]) - else: - new_name = self.name - if self.channel_buffer: - if w.buffer_get_string(self.channel_buffer, "short_name") != (color + new_name): - w.buffer_set(self.channel_buffer, "short_name", color + new_name) - - def buffer_prnt_changed(self, user, text, time, append=""): - if user: - if self.server.users.find(user): - name = self.server.users.find(user).formatted_name() - else: - name = user - name = name.decode('utf-8') - modify_buffer_line(self.channel_buffer, name, text, time, append) - else: - modify_buffer_line(self.channel_buffer, None, text, time, append) - return False - - def buffer_prnt(self, user='unknown user', message='no message', time=0): - set_read_marker = False - time_float = float(time) - if time_float != 0 and self.last_read >= time_float: - tags = "no_highlight,notify_none,logger_backlog_end" - set_read_marker = True - elif message.find(self.server.nick.encode('utf-8')) > -1: - tags = "notify_highlight" - elif user != self.server.nick and self.name in self.server.users: - tags = "notify_private,notify_message" - else: - tags = "notify_message" - time_int = int(time_float) - if self.channel_buffer: - if self.server.users.find(user): - name = self.server.users.find(user).formatted_name() - else: - name = user - name = name.decode('utf-8') - #colorize nicks in each line - chat_color = w.config_string(w.config_get('weechat.color.chat')) - message = message.decode('UTF-8', 'replace') - 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)), - 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) - - if set_read_marker: - self.mark_read(False) - else: - self.open(False) - self.last_received = time - self.unset_typing(user) - - def change_previous_message(self, old, new): - message = self.my_last_message() - if new == "" and old == "": - async_slack_api_request(self.server.domain, self.server.token, 'chat.delete', {"channel": self.identifier, "ts": message['ts']}) - else: - new_message = message["text"].replace(old, new) - async_slack_api_request(self.server.domain, self.server.token, 'chat.update', {"channel": self.identifier, "ts": message['ts'], "text": new_message}) - - def my_last_message(self): - for message in reversed(message_cache[self.identifier]): - if "user" in message and "text" in message and message["user"] == self.server.users.find(self.server.nick).identifier: - return message - - def get_history(self): - if self.active: - if self.identifier in message_cache.keys(): - for message in message_cache[self.identifier]: - process_message(message) - if self.last_received != None: - async_slack_api_request(self.server.domain, self.server.token, SLACK_API_TRANSLATOR[self.type]["history"], {"channel": self.identifier, "oldest": self.last_received, "count": BACKLOG_SIZE}) - else: - async_slack_api_request(self.server.domain, self.server.token, SLACK_API_TRANSLATOR[self.type]["history"], {"channel": self.identifier, "count": BACKLOG_SIZE}) - - -class GroupChannel(Channel): - - def __init__(self, server, name, identifier, active, last_read=0, prepend_name="", members=[], topic=""): - super(GroupChannel, self).__init__(server, name, identifier, active, last_read, prepend_name, members, topic) - self.type = "group" - - -class DmChannel(Channel): - - def __init__(self, server, name, identifier, active, last_read=0, prepend_name=""): - super(DmChannel, self).__init__(server, name, identifier, active, last_read, prepend_name) - self.type = "im" - - def rename(self): - if current_domain_name() != self.server.domain and channels_not_on_current_server_color: - force_color = w.color(channels_not_on_current_server_color) - else: - force_color = None - - if self.server.users.find(self.name).presence == "active": - new_name = self.server.users.find(self.name).formatted_name('+', force_color) - else: - new_name = self.server.users.find(self.name).formatted_name(' ', force_color) - - if self.channel_buffer: - w.buffer_set(self.channel_buffer, "short_name", new_name) - - -class User(SlackThing): - - def __init__(self, server, name, identifier, presence="away"): - super(User, self).__init__(name, identifier) - self.channel_buffer = w.info_get("irc_buffer", "{}.{}".format(domain, self.name)) - self.presence = presence - self.server = server - self.update_color() - self.name_regex = re.compile(r"([\W]|\A)(@{0,1})" + self.name + "('s|[^'\w]|\Z)") - if self.presence == 'away': - self.nicklist_pointer = w.nicklist_add_nick(server.buffer, "", self.name, self.color_name, " ", "", 0) - else: - self.nicklist_pointer = w.nicklist_add_nick(server.buffer, "", self.name, self.color_name, "+", "", 1) -# w.nicklist_add_nick(server.buffer, "", self.formatted_name(), "", "", "", 1) - - def __eq__(self, compare_str): - if compare_str == self.name or compare_str == "@" + self.name or compare_str == self.identifier: - return True - else: - return False - - def set_active(self): - self.presence = "active" - for channel in self.server.channels: - if channel.has_user(self.identifier): - channel.update_nicklist() - w.nicklist_nick_set(self.server.buffer, self.nicklist_pointer, "prefix", "+") - w.nicklist_nick_set(self.server.buffer, self.nicklist_pointer, "visible", "1") - buffer_list_update_next() - - def set_inactive(self): - self.presence = "away" - for channel in self.server.channels: - if channel.has_user(self.identifier): - channel.update_nicklist() - w.nicklist_nick_set(self.server.buffer, self.nicklist_pointer, "prefix", " ") - w.nicklist_nick_set(self.server.buffer, self.nicklist_pointer, "visible", "0") - buffer_list_update_next() - - def update_color(self): - if colorize_nicks: - self.color = w.info_get('irc_nick_color', self.name) - self.color_name = w.info_get('irc_nick_color_name', self.name) - else: - self.color = "" - self.color_name = "" - - def formatted_name(self, prepend="", force_color=None): - if colorize_nicks: - if self.name == self.server.nick: - return prepend + self.name - elif not force_color: - print_color = self.color - else: - print_color = force_color - return print_color + prepend + self.name - else: - return prepend + self.name - - def open(self): - t = time.time() + 1 - #reply = async_slack_api_request("im.open", {"channel":self.identifier,"ts":t}) - async_slack_api_request(self.server.domain, self.server.token, "im.open", {"user": self.identifier, "ts": t}) - - -def slack_command_cb(data, current_buffer, args): - a = args.split(' ', 1) - if len(a) > 1: - function_name, args = a[0], " ".join(a[1:]) - else: - function_name, args = a[0], None - - try: - command = cmds[function_name](current_buffer, args) - except KeyError: - w.prnt("", "Command not found: " + function_name) - - return w.WEECHAT_RC_OK - - -def me_command_cb(data, current_buffer, args): - if channels.find(current_buffer): - channel = channels.find(current_buffer) - nick = channel.server.nick - message = "_{}_".format(args) - message = message.encode('utf-8') - buffer_input_cb("", current_buffer, message) - return w.WEECHAT_RC_OK - - -def join_command_cb(data, current_buffer, args): - if channels.find(current_buffer) or servers.find(current_buffer): - channel = args.split()[1] - servers.find(current_domain_name()).channels.find(channel).open() - return w.WEECHAT_RC_OK_EAT - else: - return w.WEECHAT_RC_OK - - -def part_command_cb(data, current_buffer, args): - if channels.find(current_buffer) or servers.find(current_buffer): - args = args.split() - if len(args) > 1: - channel = args[1:] - servers.find(current_domain_name()).channels.find(channel).close(True) - else: - channels.find(current_buffer).close(True) - return w.WEECHAT_RC_OK_EAT - else: - return w.WEECHAT_RC_OK - - -# Wrap command_ functions that require they be performed in a slack buffer -def slack_buffer_required(f): - @wraps(f) - def wrapper(current_buffer, *args, **kwargs): - server = servers.find(current_domain_name()) - if not server: - w.prnt(current_buffer, "This command must be used in a slack buffer") - return - return f(current_buffer, *args, **kwargs) - return wrapper - - -@slack_buffer_required -def command_talk(current_buffer, args): - """ - Open a chat with the specified user - /slack talk [user] - """ - servers.find(current_domain_name()).users.find(args).open() - - -def command_join(current_buffer, args): - """ - Join the specified channel - /slack join [channel] - """ - domain = current_domain_name() - if domain == "": - if len(servers) == 1: - domain = servers[0] - else: - w.prnt(current_buffer, "You are connected to multiple Slack instances, please execute /join from a server buffer. i.e. (domain).slack.com") - return - channel = servers.find(domain).channels.find(args) - if channel != None: - servers.find(domain).channels.find(args).open() - else: - w.prnt(current_buffer, "Channel not found.") - - -@slack_buffer_required -def command_channels(current_buffer, args): - """ - List all the channels for the slack instance (name, id, active) - /slack channels - """ - server = servers.find(current_domain_name()) - for channel in server.channels: - line = "{:<25} {} {}".format(channel.name, channel.identifier, channel.active) - server.buffer_prnt(line) - - -def command_nodistractions(current_buffer, args): - global hide_distractions - hide_distractions = not hide_distractions - if distracting_channels[0] != "": - for channel in distracting_channels: - try: - w.buffer_set(channels.find(channel).channel_buffer, "hidden", str(int(hide_distractions))) - except: - dbg("Can't hide channel {}".format(channel), main_buffer=True) - - -@slack_buffer_required -def command_users(current_buffer, args): - """ - List all the users for the slack instance (name, id, away) - /slack users - """ - server = servers.find(current_domain_name()) - for user in server.users: - line = "{:<40} {} {}".format(user.formatted_name(), user.identifier, user.presence) - server.buffer_prnt(line) - - -def command_setallreadmarkers(current_buffer, args): - """ - Sets the read marker for all channels - /slack setallreadmarkers - """ - for channel in channels: - channel.mark_read() - - -def command_changetoken(current_buffer, args): - w.config_set_plugin('slack_api_token', args) - - -def command_test(current_buffer, args): - w.prnt(current_buffer, "worked!") - - -@slack_buffer_required -def command_away(current_buffer, args): - """ - Sets your status as 'away' - /slack away - """ - server = servers.find(current_domain_name()) - async_slack_api_request(server.domain, server.token, 'presence.set', {"presence": "away"}) - - -@slack_buffer_required -def command_back(current_buffer, args): - """ - Sets your status as 'back' - /slack back - """ - server = servers.find(current_domain_name()) - async_slack_api_request(server.domain, server.token, 'presence.set', {"presence": "active"}) - - -@slack_buffer_required -def command_markread(current_buffer, args): - """ - Marks current channel as read - /slack markread - """ - # refactor this - one liner i think - channel = current_buffer_name(short=True) - domain = current_domain_name() - if servers.find(domain).channels.find(channel): - servers.find(domain).channels.find(channel).mark_read() - -def command_cacheinfo(current_buffer, args): - for channel in message_cache.keys(): - c = channels.find(channel) - w.prnt("", "{} {}".format(channels.find(channel), len(message_cache[channel]))) -# server.buffer_prnt("{} {}".format(channels.find(channel), len(message_cache[channel]))) - -def command_flushcache(current_buffer, args): - global message_cache - message_cache = {} - cache_write_cb("","") - -def command_uncache(current_buffer, args): - identifier = channels.find(current_buffer).identifier - message_cache.pop(identifier) - cache_write_cb("","") - -def command_cachenow(current_buffer, args): - cache_write_cb("","") - -def command_neveraway(current_buffer, args): - global never_away - if never_away: - never_away = False - dbg("unset never_away", main_buffer=True) - else: - never_away = True - dbg("set never_away", main_buffer=True) - - -def command_printvar(current_buffer, args): - w.prnt("", "{}".format(eval(args))) - - -def command_p(current_buffer, args): - w.prnt("", "{}".format(eval(args))) - - -def command_debug(current_buffer, args): - create_slack_debug_buffer() - - -def command_debugstring(current_buffer, args): - global debug_string - if args == '': - debug_string = None - else: - debug_string = args - - -def command_search(current_buffer, args): - pass -# if not slack_buffer: -# create_slack_buffer() -# w.buffer_set(slack_buffer, "display", "1") -# query = args -# w.prnt(slack_buffer,"\nSearched for: %s\n\n" % (query)) -# reply = slack_api_request('search.messages', {"query":query}).read() -# data = json.loads(reply) -# for message in data['messages']['matches']: -# message["text"] = message["text"].encode('ascii', 'ignore') -# formatted_message = "%s / %s:\t%s" % (message["channel"]["name"], message['username'], message['text']) -# w.prnt(slack_buffer,str(formatted_message)) - - -def command_nick(current_buffer, args): - pass -# urllib.urlopen("https://%s/account/settings" % (domain)) -# browser.select_form(nr=0) -# browser.form['username'] = args -# reply = browser.submit() - - -def command_help(current_buffer, args): - help_cmds = { k[8:]: v.__doc__ for k, v in globals().items() if k.startswith("command_") } - - if args: - try: - help_cmds = {args: help_cmds[args]} - except KeyError: - w.prnt("", "Command not found: " + args) - return - - for cmd, helptext in help_cmds.items(): - w.prnt('', w.color("bold") + cmd) - w.prnt('', (helptext or 'No help text').strip()) - w.prnt('', '') - -# Websocket handling methods - -def command_openweb(current_buffer, args): - trigger = w.config_get_plugin('trigger_value') - if trigger != "0": - if args is None: - channel = channels.find(current_buffer) - url = "{}/messages/{}".format(channel.server.domain, channel.name) - topic = w.buffer_get_string(channel.channel_buffer, "title") - w.buffer_set(channel.channel_buffer, "title", "{}:{}".format(trigger, url)) - w.hook_timer(1000, 0, 1, "command_openweb", json.dumps({"topic": topic, "buffer": current_buffer})) - else: - #TODO: fix this dirty hack because i don't know the right way to send multiple args. - args = current_buffer - data = json.loads(args) - channel_buffer = channels.find(data["buffer"]).channel_buffer - w.buffer_set(channel_buffer, "title", data["topic"]) - return w.WEECHAT_RC_OK - -def slack_websocket_cb(server, fd): - try: - data = servers.find(server).ws.recv() - message_json = json.loads(data) - # this magic attaches json that helps find the right dest - message_json['myserver'] = server - except: - return w.WEECHAT_RC_OK - # dispatch here - if "reply_to" in message_json: - function_name = "reply" - elif "type" in message_json: - function_name = message_json["type"] - else: - function_name = "unknown" - try: - proc[function_name](message_json) - # dbg(function_name) - except KeyError: - if function_name: - dbg("Function not implemented: {}\n{}".format(function_name, message_json)) - else: - dbg("Function not implemented\n{}".format(message_json)) - w.bar_item_update("slack_typing_notice") - return w.WEECHAT_RC_OK - -def process_reply(message_json): - server = servers.find(message_json["myserver"]) - identifier = message_json["reply_to"] - item = server.message_buffer.pop(identifier) - if "type" in item: - if item["type"] == "message": - item["ts"] = message_json["ts"] - cache_message(item, from_me=True) - dbg("REPLY {}".format(item)) - -def process_pong(message_json): - pass - - -def process_team_join(message_json): - server = servers.find(message_json["myserver"]) - item = message_json["user"] - server.users.append(User(server, item["name"], item["id"], item["presence"])) - server.buffer_prnt(server.buffer, "New user joined: {}".format(item["name"])) - - -def process_presence_change(message_json): - buffer_name = "{}.{}".format(domain, message_json["user"]) - buf_ptr = w.buffer_search("", buffer_name) - if message_json["presence"] == 'active': - users.find(message_json["user"]).set_active() - else: - users.find(message_json["user"]).set_inactive() - - -def process_channel_marked(message_json): - channel = channels.find(message_json["channel"]) - channel.mark_read(False) - if not legacy_mode: - w.buffer_set(channel.channel_buffer, "hotlist", "-1") - - -def process_group_marked(message_json): - channel = channels.find(message_json["channel"]) - channel.mark_read(False) - if not legacy_mode: - w.buffer_set(channel.channel_buffer, "hotlist", "-1") - - -def process_channel_created(message_json): - server = servers.find(message_json["myserver"]) - item = message_json["channel"] - if server.channels.find(message_json["channel"]["name"]): - server.channels.find(message_json["channel"]["name"]).open(False) - else: - item = message_json["channel"] - server.channels.append(Channel(server, item["name"], item["id"], item["is_open"], item["last_read"], "#", item["members"], item["topic"])) - server.buffer_prnt("New channel created: {}".format(item["name"])) - - -def process_channel_left(message_json): - server = servers.find(message_json["myserver"]) - server.channels.find(message_json["channel"]).close(False) - - -def process_channel_join(message_json): - server = servers.find(message_json["myserver"]) - channel = server.channels.find(message_json["channel"]) - channel.user_join(message_json["user"]) - - -def process_channel_topic(message_json): - server = servers.find(message_json["myserver"]) - channel = server.channels.find(message_json["channel"]) - channel.set_topic(message_json["topic"]) - - -def process_channel_joined(message_json): - server = servers.find(message_json["myserver"]) - if server.channels.find(message_json["channel"]["name"]): - server.channels.find(message_json["channel"]["name"]).open(False) - else: - item = message_json["channel"] - server.channels.append(Channel(server, item["name"], item["id"], item["is_open"], item["last_read"], "#", item["members"], item["topic"])) - - -def process_channel_leave(message_json): - server = servers.find(message_json["myserver"]) - channel = server.channels.find(message_json["channel"]) - channel.user_leave(message_json["user"]) - - -def process_group_left(message_json): - server = servers.find(message_json["myserver"]) - server.channels.find(message_json["channel"]).close(False) - - -def process_group_joined(message_json): - server = servers.find(message_json["myserver"]) - if server.channels.find(message_json["channel"]["name"]): - server.channels.find(message_json["channel"]["name"]).open(False) - else: - item = message_json["channel"] - server.channels.append(GroupChannel(server, item["name"], item["id"], item["is_open"], item["last_read"], "#", item["members"], item["topic"])) - - -def process_im_close(message_json): - server = servers.find(message_json["myserver"]) - server.channels.find(message_json["channel"]).close(False) - - -def process_im_open(message_json): - server = servers.find(message_json["myserver"]) - server.channels.find(message_json["channel"]).open(False) - - -def process_im_marked(message_json): - channel = channels.find(message_json["channel"]) - channel.mark_read(False) - if not legacy_mode: - w.buffer_set(channel.channel_buffer, "hotlist", "-1") - - -def process_im_created(message_json): - server = servers.find(message_json["myserver"]) - item = message_json["channel"] - channel_name = server.users.find(item["user"]).name - if server.channels.find(channel_name): - server.channels.find(channel_name).open(False) - else: - item = message_json["channel"] - server.channels.append(DmChannel(server, channel_name, item["id"], item["is_open"], item["last_read"])) - server.buffer_prnt("New channel created: {}".format(item["name"])) - - -def process_user_typing(message_json): - server = servers.find(message_json["myserver"]) - server.channels.find(message_json["channel"]).set_typing(server.users.find(message_json["user"]).name) - -# todo: does this work? - - -def process_error(message_json): - pass - #connected = False - -# def process_message_changed(message_json): -# process_message(message_json) - -def cache_message(message_json, from_me=False): - global message_cache - if from_me: - server = channels.find(message_json["channel"]).server - message_json["user"] = server.users.find(server.nick).identifier - channel = message_json["channel"] - if channel not in message_cache: - message_cache[channel] = [] - if message_json not in message_cache[channel]: - message_cache[channel].append(message_json) - if len(message_cache[channel]) > BACKLOG_SIZE: - message_cache[channel] = message_cache[channel][-BACKLOG_SIZE:] - - -def modify_buffer_line(buffer, user, new_message, time, append): - time = int(float(time)) - own_lines = w.hdata_pointer(w.hdata_get('buffer'), buffer, 'own_lines') - if own_lines: - line = w.hdata_pointer(w.hdata_get('lines'), own_lines, 'last_line') - hdata_line = w.hdata_get('line') - hdata_line_data = w.hdata_get('line_data') - - while line: - data = w.hdata_pointer(hdata_line, line, 'data') - if data: - date = w.hdata_time(hdata_line_data, data, 'date') - prefix = w.hdata_string(hdata_line_data, data, 'prefix') - if user and (int(date) == int(time) and user == prefix): -# w.prnt("", "found matching time date is {}, time is {} ".format(date, time)) - w.hdata_update(hdata_line_data, data, {"message": "{}{}".format(new_message, append)}) - break - elif not user and (int(date) == int(time)): - w.hdata_update(hdata_line_data, data, {"message": "{}{}".format(new_message, append)}) - else: - pass - line = w.hdata_move(hdata_line, line, -1) - return w.WEECHAT_RC_OK - - -def process_message(message_json): - try: - # send these messages elsewhere - known_subtypes = ['channel_join', 'channel_leave', 'channel_topic'] - if "subtype" in message_json and message_json["subtype"] in known_subtypes: - proc[message_json["subtype"]](message_json) - - # move message properties down to root of json object - message_json = unwrap_message(message_json) - - server = servers.find(message_json["myserver"]) - channel = channels.find(message_json["channel"]) - - #do not process messages in unexpected channels - if not channel.active: - channel.open(False) - dbg("message came for closed channel {}".format(channel.name)) - return - - cache_message(message_json) - - time = message_json['ts'] - if "fallback" in message_json: - text = message_json["fallback"] - elif "text" in message_json: - text = message_json["text"] - else: - text = "" - - text = unfurl_refs(text) - if "attachments" in message_json: - text += u" --- {}".format(unwrap_attachments(message_json)) - text = text.lstrip() - text = text.replace("\t", " ") - name = get_user(message_json, server) - - text = text.encode('utf-8') - name = name.encode('utf-8') - - if "subtype" in message_json and message_json["subtype"] == "message_changed": - if "edited" in message_json["message"]: - append = " (edited)" - else: - append = '' - channel.buffer_prnt_changed(message_json["message"]["user"], text, message_json["message"]["ts"], append) - elif "subtype" in message_json and message_json["subtype"] == "message_deleted": - append = "(deleted)" - text = "" - channel.buffer_prnt_changed(None, text, message_json["deleted_ts"], append) - else: - channel.buffer_prnt(name, text, time) - except: - dbg("cannot process message {}".format(message_json)) - - -def unwrap_message(message_json): - if "message" in message_json: - if "attachments" in message_json["message"]: - message_json["attachments"] = message_json["message"]["attachments"] - if "text" in message_json["message"]: - if "text" in message_json: - message_json["text"] += message_json["message"]["text"] - dbg("added text!") - else: - message_json["text"] = message_json["message"]["text"] - if "fallback" in message_json["message"]: - if "fallback" in message_json: - message_json["fallback"] += message_json["message"]["fallback"] - else: - message_json["fallback"] = message_json["message"]["fallback"] - return message_json - - -def unwrap_attachments(message_json): - attachment_text = '' - for attachment in message_json["attachments"]: - if "fallback" in attachment: - attachment_text += attachment["fallback"] -# attachment_text = attachment_text.encode('ascii', 'ignore') - return attachment_text - - -def unfurl_refs(text): - if text.find('<') > -1: - newtext = [] - text = text.split(" ") - for item in text: - # dbg(item) - start = item.find('<') - end = item.find('>') - if start > -1 and end > -1: - item = item[start + 1:end] - if item.find('|') > -1: - item = item.split('|')[0] - if item.startswith('@U'): - if users.find(item[1:]): - try: - item = "@{}".format(users.find(item[1:]).name) - except: - dbg("NAME: {}".format(item)) - if item.startswith('#C'): - if channels.find(item[1:]): - item = "{}".format(channels.find(item[1:]).name) - newtext.append(item) - text = " ".join(newtext) - return text - else: - return text - - -def get_user(message_json, server): - if 'user' in message_json: - name = server.users.find(message_json['user']).name - elif 'username' in message_json: - name = u"-{}-".format(message_json["username"]) - elif 'service_name' in message_json: - name = u"-{}-".format(message_json["service_name"]) - elif 'bot_id' in message_json: - name = u"-{}-".format(message_json["bot_id"]) - else: - name = u"" - return name - -# END Websocket handling methods - - -def typing_bar_item_cb(data, buffer, args): - typers = [x for x in channels.get_all() if x.is_someone_typing()] - if len(typers) > 0: - direct_typers = [] - channel_typers = [] - for dm in channels.find_by_class(DmChannel): - direct_typers.extend(dm.get_typing_list()) - direct_typers = ["D/" + x for x in direct_typers] - current_channel = w.current_buffer() - channel = channels.find(current_channel) - try: - if channel and channel.__class__ != DmChannel: - channel_typers = channels.find(current_channel).get_typing_list() - except: - w.prnt("", "Bug on {}".format(channel)) - typing_here = ", ".join(channel_typers + direct_typers) - if len(typing_here) > 0: - color = w.color('yellow') - return color + "typing: " + typing_here - return "" - - -def typing_update_cb(data, remaining_calls): - w.bar_item_update("slack_typing_notice") - return w.WEECHAT_RC_OK - - -def buffer_list_update_cb(data, remaining_calls): - global buffer_list_update - - now = time.time() - if buffer_list_update and previous_buffer_list_update + 1 < now: - gray_check = False - if len(servers) > 1: - gray_check = True - # for channel in channels.find_by_class(Channel) + channels.find_by_class(GroupChannel): - for channel in channels: - channel.rename() - buffer_list_update = False - return w.WEECHAT_RC_OK - -def buffer_list_update_next(): - global buffer_list_update - buffer_list_update = True - -def hotlist_cache_update_cb(data, remaining_calls): - # this keeps the hotlist dupe up to date for the buffer switch, but is prob technically a race condition. (meh) - global hotlist - prev_hotlist = hotlist - hotlist = w.infolist_get("hotlist", "", "") - w.infolist_free(prev_hotlist) - return w.WEECHAT_RC_OK - - -def buffer_closing_cb(signal, sig_type, data): - if channels.find(data): - channels.find(data).closed() - return w.WEECHAT_RC_OK - - -def buffer_switch_cb(signal, sig_type, data): - global previous_buffer, hotlist - # this is to see if we need to gray out things in the buffer list - buffer_list_update_next() - if channels.find(previous_buffer): - channels.find(previous_buffer).mark_read() - - channel_name = current_buffer_name() - previous_buffer = data - return w.WEECHAT_RC_OK - - -def typing_notification_cb(signal, sig_type, data): - if len(w.buffer_get_string(data, "input")) > 8: - global typing_timer - now = time.time() - if typing_timer + 4 < now: - channel = channels.find(current_buffer_name()) - if channel: - identifier = channel.identifier - request = {"type": "typing", "channel": identifier} - channel.server.send_to_websocket(request) - typing_timer = now - return w.WEECHAT_RC_OK - -# NOTE: figured i'd do this because they do - - -def slack_ping_cb(data, remaining): - servers.find(data).ping() - return w.WEECHAT_RC_OK - - -def slack_connection_persistence_cb(data, remaining_calls): - for server in servers: - if not server.connected: - server.buffer_prnt("Disconnected from slack, trying to reconnect..") - if server.ws_hook is not None: - w.unhook(server.ws_hook) - server.connect_to_slack() - return w.WEECHAT_RC_OK - - -def slack_never_away_cb(data, remaining): - global never_away - if never_away: - for server in servers: - identifier = server.channels.find("slackbot").identifier - request = {"type": "typing", "channel": identifier} - #request = {"type":"typing","channel":"slackbot"} - server.send_to_websocket(request) - return w.WEECHAT_RC_OK - -# Slack specific requests - -# NOTE: switched to async/curl because sync slowed down the UI - - -def async_slack_api_request(domain, token, request, post_data, priority=False): - if not STOP_TALKING_TO_SLACK: - post_data["token"] = token - url = 'https://{}/api/{}'.format(domain, request) - command = 'curl -A "wee_slack {}" -s --data "{}" {}'.format(SCRIPT_VERSION, urllib.urlencode(post_data), url) - context = pickle.dumps({"request": request, "token": token, "post_data": post_data}) - w.hook_process(command, 20000, "url_processor_cb", context) - -# funny, right? -big_data = {} - -def url_processor_cb(data, command, return_code, out, err): - global big_data, message_cache - data = pickle.loads(data) - identifier = sha.sha("{}{}".format(data, command)).hexdigest() - if identifier not in big_data: - big_data[identifier] = '' - big_data[identifier] += out - if return_code == 0: - try: - my_json = json.loads(big_data[identifier]) - except: - dbg("curl failed, doing again...") - dbg("curl length: {} identifier {}\n{}".format(len(big_data[identifier]), identifier, data)) - my_json = False - - big_data.pop(identifier, None) - - if my_json: - if data["request"] == 'rtm.start': - servers.find(data["token"]).connected_to_slack(my_json) - - else: - if "channel" in data["post_data"]: - channel = data["post_data"]["channel"] - token = data["token"] - if "messages" in my_json: - messages = my_json["messages"].reverse() - for message in my_json["messages"]: - message["myserver"] = servers.find(token).domain - message["channel"] = servers.find(token).channels.find(channel).identifier - process_message(message) - if "channel" in my_json: - if "members" in my_json["channel"]: - channels.find(my_json["channel"]["id"]).members = set(my_json["channel"]["members"]) - elif return_code != -1: - big_data.pop(identifier, None) - dbg("return code: {}".format(return_code)) - - return w.WEECHAT_RC_OK - -def cache_write_cb(data, remaining): - open("{}/{}".format(WEECHAT_HOME, CACHE_NAME), 'w').write(json.dumps(message_cache)) - return w.WEECHAT_RC_OK - - - -# END Slack specific requests - -# Utility Methods - - -def current_domain_name(): - buffer = w.current_buffer() - if servers.find(buffer): - return servers.find(buffer).domain - else: - #number = w.buffer_get_integer(buffer, "number") - name = w.buffer_get_string(buffer, "name") - name = ".".join(name.split(".")[:-1]) - return name - - -def current_buffer_name(short=False): - buffer = w.current_buffer() - #number = w.buffer_get_integer(buffer, "number") - name = w.buffer_get_string(buffer, "name") - if short: - try: - name = name.split('.')[-1] - except: - pass - return name - - -def closed_slack_buffer_cb(data, buffer): - global slack_buffer - slack_buffer = None - return w.WEECHAT_RC_OK - - -def create_slack_buffer(): - global slack_buffer - slack_buffer = w.buffer_new("slack", "", "", "closed_slack_buffer_cb", "") - w.buffer_set(slack_buffer, "notify", "0") - #w.buffer_set(slack_buffer, "display", "1") - return w.WEECHAT_RC_OK - - -def closed_slack_debug_buffer_cb(data, buffer): - global slack_debug - slack_debug = None - return w.WEECHAT_RC_OK - - -def create_slack_debug_buffer(): - global slack_debug, debug_string - if slack_debug is not None: - w.buffer_set(slack_debug, "display", "1") - else: - debug_string = None - slack_debug = w.buffer_new("slack-debug", "", "", "closed_slack_debug_buffer_cb", "") - w.buffer_set(slack_debug, "notify", "0") - - -def config_changed_cb(data, option, value): - global slack_api_token, distracting_channels, channels_not_on_current_server_color, colorize_nicks, slack_debug, debug_mode - slack_api_token = w.config_get_plugin("slack_api_token") - - if slack_api_token.startswith('${sec.data'): - slack_api_token = w.string_eval_expression(slack_api_token, {}, {}, {}) - - distracting_channels = [x.strip() for x in w.config_get_plugin("distracting_channels").split(',')] - channels_not_on_current_server_color = w.config_get_plugin("channels_not_on_current_server_color") - if channels_not_on_current_server_color == "0": - channels_not_on_current_server_color = False - colorize_nicks = w.config_get_plugin('colorize_nicks') == "1" - debug_mode = w.config_get_plugin("debug_mode").lower() - if debug_mode != '' and debug_mode != 'false': - create_slack_debug_buffer() - return w.WEECHAT_RC_OK - -def quit_notification_cb(signal, sig_type, data): - global STOP_TALKING_TO_SLACK - STOP_TALKING_TO_SLACK = True - cache_write_cb("", "") - return w.WEECHAT_RC_OK - -def script_unloaded(): - global STOP_TALKING_TO_SLACK - STOP_TALKING_TO_SLACK = True - cache_write_cb("", "") - return w.WEECHAT_RC_OK - -# END Utility Methods - -# Main -if __name__ == "__main__": - if w.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE, - SCRIPT_DESC, "script_unloaded", ""): - - WEECHAT_HOME = w.info_get("weechat_dir", "") - CACHE_NAME = "slack.cache" - STOP_TALKING_TO_SLACK = False - - if not w.config_get_plugin('slack_api_token'): - w.config_set_plugin('slack_api_token', "INSERT VALID KEY HERE!") - if not w.config_get_plugin('distracting_channels'): - w.config_set_plugin('distracting_channels', "") - if not w.config_get_plugin('channels_not_on_current_server_color'): - w.config_set_plugin('channels_not_on_current_server_color', "0") - if not w.config_get_plugin('debug_mode'): - 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('trigger_value'): - w.config_set_plugin('trigger_value', "0") - - version = w.info_get("version_number", "") or 0 - if int(version) >= 0x00040400: - legacy_mode = False - else: - legacy_mode = True - - # Global var section - slack_debug = None - config_changed_cb("", "", "") - - cmds = {k[8:]: v for k, v in globals().items() if k.startswith("command_")} - proc = {k[8:]: v for k, v in globals().items() if k.startswith("process_")} - - typing_timer = time.time() - domain = None - previous_buffer = None - slack_buffer = None - - buffer_list_update = False - previous_buffer_list_update = 0 - - #name = None - never_away = False - hide_distractions = False - hotlist = w.infolist_get("hotlist", "", "") - main_weechat_buffer = w.info_get("irc_buffer", "{}.{}".format(domain, "DOESNOTEXIST!@#$")) - - try: - cache_file = open("{}/{}".format(WEECHAT_HOME, CACHE_NAME), 'r') - message_cache = json.loads(cache_file.read()) - except (IOError, ValueError): - message_cache = {} - # End global var section - - #channels = SearchList() - servers = SearchList() - for token in slack_api_token.split(','): - servers.append(SlackServer(token)) - channels = Meta('channels', servers) - users = Meta('users', servers) - - w.hook_config("plugins.var.python." + SCRIPT_NAME + ".*", "config_changed_cb", "") - w.hook_timer(3000, 0, 0, "slack_connection_persistence_cb", "") - - # attach to the weechat hooks we need - w.hook_timer(1000, 0, 0, "typing_update_cb", "") - w.hook_timer(1000, 0, 0, "buffer_list_update_cb", "") - w.hook_timer(1000, 0, 0, "hotlist_cache_update_cb", "") - w.hook_timer(1000 * 60 * 29, 0, 0, "slack_never_away_cb", "") - w.hook_timer(1000 * 60 * 5, 0, 0, "cache_write_cb", "") - w.hook_signal('buffer_closing', "buffer_closing_cb", "") - w.hook_signal('buffer_switch', "buffer_switch_cb", "") - w.hook_signal('window_switch', "buffer_switch_cb", "") - w.hook_signal('input_text_changed', "typing_notification_cb", "") - w.hook_signal('quit', "quit_notification_cb", "") - w.hook_command( - # Command name and description - 'slack', 'Plugin to allow typing notification and sync of read markers for slack.com', - # Usage - '[command] [command options]', - # Description of arguments - 'Commands:\n' + - '\n'.join(cmds.keys()) + - '\nUse /slack help [command] to find out more\n', - # Completions - '|'.join(cmds.keys()), - # Function name - 'slack_command_cb', '') -# w.hook_command('me', 'me_command_cb', '') - w.hook_command('me', '', 'stuff', 'stuff2', '', 'me_command_cb', '') - w.hook_command_run('/query', 'join_command_cb', '') - w.hook_command_run('/join', 'join_command_cb', '') - w.hook_command_run('/part', 'part_command_cb', '') - w.hook_command_run('/leave', 'part_command_cb', '') - w.bar_item_new('slack_typing_notice', 'typing_bar_item_cb', '') - # END attach to the weechat hooks we need |