aboutsummaryrefslogtreecommitdiffstats
path: root/weechat
diff options
context:
space:
mode:
Diffstat (limited to 'weechat')
-rw-r--r--weechat/python/autojoin_on_invite.py119
-rw-r--r--weechat/python/wee_slack.py1690
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