aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRyan Huber <rhuber@gmail.com>2014-10-24 13:46:15 -0700
committerRyan Huber <rhuber@gmail.com>2014-10-24 13:46:15 -0700
commit585b62e03b00935dc7fbf8347ce6fb8af9ce8858 (patch)
tree317731d9f52e3f7b117e3589ce93fa1af45dc902
parent4af13983ee6bc4733db26c2d124bf28b14b6bc51 (diff)
downloadwee-slack-585b62e03b00935dc7fbf8347ce6fb8af9ce8858.tar.gz
mutli almost done...
-rw-r--r--wee_slack.py333
1 files changed, 196 insertions, 137 deletions
diff --git a/wee_slack.py b/wee_slack.py
index 57b8637..15bc09c 100644
--- a/wee_slack.py
+++ b/wee_slack.py
@@ -45,19 +45,74 @@ SLACK_API_TRANSLATOR = {
}
def dbg(message):
- w.prnt("", str(message))
+ w.prnt("", "DEBUG: " + str(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 += str(each)
+ return string
+ def __repr__(self):
+ self.search_list.get_all(self.attribute)
+ def find(self, name):
+ items = self.search_list.find_deep(name, self.attribute)
+ if len(items) == 1:
+ return items[0]
+ else:
+ raise AmbiguousProblemError
+ def find_by_class(self, class_name):
+ items = []
+ #for each in self.search_list.find_by_class(class_name):
+ items += self.search_list.find_by_class_deep(class_name, self.attribute)
+ return items
class SearchList(list):
- def find(self, item):
- try:
- return self[self.index(item)]
- except ValueError:
- return None
+ 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]
+ else:
+ return items
+ def find_deep(self, name, attribute):
+ items = []
+ for child in self:
+ if child.__class__ == self.__class__:
+ items += child.find_deep(name, attribute)
+ elif dir(child).count('find') == 1:
+ items.append(child.find(name, attribute))
+ 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 item in self:
- if item.__class__ == class_name:
- items.append(item)
+ 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):
@@ -76,7 +131,7 @@ class SlackServer(object):
self.connect_to_slack()
w.hook_timer(6000, 0, 0, "slack_connection_persistence_cb", self.identifier)
def __eq__(self, compare_str):
- if compare_str == self.identifier:
+ if compare_str == self.identifier or compare_str == self.token:
return True
else:
return False
@@ -84,6 +139,9 @@ class SlackServer(object):
return "%s" % (self.identifier)
def __repr__(self):
return "%s" % (self.identifier)
+ def find(self, name, attribute):
+ attribute = eval("self."+attribute)
+ return attribute.find(name)
def connect_to_slack(self):
data = {}
t = time.time()
@@ -102,9 +160,10 @@ class SlackServer(object):
self.create_slack_websocket(login_data)
self.create_slack_mappings(login_data)
- general_buffer_ptr = w.buffer_search("",self.domain+".#general")
- nick_ptr = w.nicklist_search_nick(general_buffer_ptr,'',self.nick)
- name = w.nicklist_nick_get_string(general_buffer_ptr,self.nick,'name')
+ self.buffer = w.buffer_new(self.domain, "input", "", "", "")
+ self.general_buffer_ptr = w.buffer_search("",self.domain+".#general")
+ nick_ptr = w.nicklist_search_nick(self.general_buffer_ptr,'',self.nick)
+ name = w.nicklist_nick_get_string(self.general_buffer_ptr,self.nick,'name')
self.connected = True
return True
@@ -126,47 +185,38 @@ class SlackServer(object):
def create_slack_mappings(self, data):
for item in data["users"]:
- self.users.append(User(item["name"], item["id"], item["presence"]))
+ self.users.append(User(self, item["name"], item["id"], item["presence"]))
for item in data["channels"]:
if not item.has_key("last_read"):
item["last_read"] = 0
- self.channels.append(Channel(self.domain, item["name"], item["id"], item["is_member"], item["last_read"], "#"))
+ self.channels.append(Channel(self, item["name"], item["id"], item["is_member"], item["last_read"], "#"))
for item in data["groups"]:
if not item.has_key("last_read"):
item["last_read"] = 0
- self.channels.append(GroupChannel(self.domain, item["name"], item["id"], item["is_open"], item["last_read"], "#"))
+ self.channels.append(GroupChannel(self, item["name"], item["id"], item["is_open"], item["last_read"], "#"))
for item in data["ims"]:
if not item.has_key("last_read"):
item["last_read"] = 0
name = self.users.find(item["user"]).name
- self.channels.append(DmChannel(self.domain, name, item["id"], item["is_open"], item["last_read"]))
+ self.channels.append(DmChannel(self, name, item["id"], item["is_open"], item["last_read"]))
for item in self.channels:
item.get_history()
-
-
-
class SlackThing(object):
def __init__(self, name, identifier):
self.name = name
self.identifier = identifier
self.channel_buffer = None
- def __eq__(self, compare_str):
- if 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 != None):
- return True
- else:
- return False
def __str__(self):
return "Name: %s Id: %s CB: %s" % (self.name, self.identifier, self.channel_buffer)
def __repr__(self):
return "Name: %s Id: %s CB: %s" % (self.name, self.identifier, self.channel_buffer)
def input(b,c,data):
- for server in servers:
- server.channels.find(b).send_message(data)
- server.channels.find(b).prnt(nick, data)
+ channels.find(b).send_message(data)
+ channels.find(b).prnt(data)
return w.WEECHAT_RC_ERROR
class Channel(SlackThing):
@@ -181,18 +231,23 @@ class Channel(SlackThing):
if active:
self.create_buffer()
self.attach_buffer()
+ 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 != None):
+ return True
+ else:
+ return False
def __str__(self):
return "Name: %s Id: %s CB: %s Active: %s" % (self.name, self.identifier, self.channel_buffer, self.active)
def __repr__(self):
return "Name: %s Id: %s CB: %s Active: %s" % (self.name, self.identifier, self.channel_buffer, self.active)
def create_buffer(self):
- channel_buffer = w.buffer_search("", "%s.%s" % (self.server, self.name))
+ channel_buffer = w.buffer_search("", "%s.%s" % (self.server.domain, self.name))
if channel_buffer:
self.channel_buffer = channel_buffer
else:
- self.channel_buffer = w.buffer_new("%s.%s" % (self.server, self.name), "input", self.name, "", "")
+ self.channel_buffer = w.buffer_new("%s.%s" % (self.server.domain, self.name), "input", self.name, "", "")
def attach_buffer(self):
- channel_buffer = w.buffer_search("", "%s.%s" % (self.server, self.name))
+ channel_buffer = w.buffer_search("", "%s.%s" % (self.server.domain, self.name))
if channel_buffer != main_weechat_buffer:
self.channel_buffer = channel_buffer
else:
@@ -200,6 +255,8 @@ class Channel(SlackThing):
def detach_buffer(self):
self.channel_buffer = None
#self.weechat_buffer = None
+ def fullname(self):
+ return "%s.%s" % (self.server.domain, self.name)
def set_active(self):
self.active = True
def set_inactive(self):
@@ -208,15 +265,15 @@ class Channel(SlackThing):
self.typing[user] = time.time()
def send_message(self, message):
request = {"type":"message","channel":self.identifier, "text": message}
- servers.find(self.server).ws.send(json.dumps(request))
+ self.server.ws.send(json.dumps(request))
def open(self):
t = time.time() + 1
- reply = async_slack_api_request(SLACK_API_TRANSLATOR[self.type]["join"], {"name":self.name.lstrip("#"),"ts":t})
+ async_slack_api_request(self.server.domain, self.server.token, SLACK_API_TRANSLATOR[self.type]["join"], {"name":self.name.lstrip("#"),"ts":t})
self.create_buffer()
self.active = True
def close(self):
t = time.time() + 1
- reply = async_slack_api_request(SLACK_API_TRANSLATOR[self.type]["leave"], {"channel":self.identifier,"ts":t})
+ async_slack_api_request(self.server.domain, self.server.token, SLACK_API_TRANSLATOR[self.type]["leave"], {"channel":self.identifier,"ts":t})
self.active = False
def unset_typing(self, user):
try:
@@ -241,7 +298,7 @@ class Channel(SlackThing):
if self.channel_buffer:
w.buffer_set(self.channel_buffer, "unread", "")
if update_remote:
- async_slack_api_request(SLACK_API_TRANSLATOR[self.type]["mark"], {"channel":self.identifier,"ts":t})
+ async_slack_api_request(self.server.domain, self.server.token, SLACK_API_TRANSLATOR[self.type]["mark"], {"channel":self.identifier,"ts":t})
def rename(self, name=None, fmt=None):
if self.channel_buffer:
if name:
@@ -271,9 +328,9 @@ class Channel(SlackThing):
def get_history(self):
if self.active:
t = time.time()
- async_slack_api_request(SLACK_API_TRANSLATOR[self.type]["history"], {"channel":self.identifier,"ts":t, "oldest":self.last_read})
+ async_slack_api_request(self.server.domain, self.server.token, SLACK_API_TRANSLATOR[self.type]["history"], {"channel":self.identifier,"ts":t, "oldest":self.last_read})
queue.append(self)
- async_slack_api_request(SLACK_API_TRANSLATOR[self.type]["history"], {"channel":self.identifier,"ts":t, "count":BACKLOG_SIZE, "latest":self.last_read})
+ async_slack_api_request(self.server.domain, self.server.token, SLACK_API_TRANSLATOR[self.type]["history"], {"channel":self.identifier,"ts":t, "count":BACKLOG_SIZE, "latest":self.last_read})
class GroupChannel(Channel):
def __init__(self, server, name, identifier, active, last_read=0, prepend_name=""):
@@ -296,10 +353,16 @@ class DmChannel(Channel):
w.buffer_set(self.channel_buffer, "short_name", color + new_name)
class User(SlackThing):
- def __init__(self, name, identifier, presence="away"):
+ def __init__(self, server, name, identifier, presence="away"):
super(User, self).__init__(name, identifier)
self.channel_buffer = w.info_get("irc_buffer", "%s.%s" % (domain, self.name))
self.presence = presence
+ self.server = server
+ def __eq__(self, compare_str):
+ if compare_str == self.name or compare_str == self.identifier:
+ return True
+ else:
+ return False
def set_active(self):
self.presence = "active"
def set_inactive(self):
@@ -310,45 +373,46 @@ class User(SlackThing):
def open(self):
t = time.time() + 1
#reply = async_slack_api_request("im.open", {"channel":self.identifier,"ts":t})
- reply = async_slack_api_request("im.open", {"user":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], a[1]
+ function_name, args = a[0], " ".join(a[1:])
else:
function_name, args = a[0], None
# try:
- cmds[function_name](args)
+ cmds[function_name](current_buffer, args)
# except KeyError:
# w.prnt("", "Command not found or exception: "+function_name)
return w.WEECHAT_RC_OK
-def command_talk(args):
- users.find(args).open()
+def command_talk(current_buffer, args):
+ channels.find(current_buffer).server.users.find(args).open()
-def command_join(args):
- channels.find(args).open()
+def command_join(current_buffer, args):
+ servers.find(current_domain_name()).channels.find(args).open()
-def command_changetoken(args):
+def command_changetoken(current_buffer, args):
w.config_set_plugin('slack_api_token', args)
-def command_test(args):
+def command_test(current_buffer, args):
if slack_buffer:
w.prnt(slack_buffer,"worked!")
-def command_away(args):
+def command_away(current_buffer, args):
async_slack_api_request('presence.set', {"presence":"away"})
-def command_back(args):
+def command_back(current_buffer, args):
async_slack_api_request('presence.set', {"presence":"active"})
-def command_markread(args):
+def command_markread(current_buffer, args):
channel = current_buffer_name(short=True)
- if channels.find(channel):
- channels.find(channel).mark_read()
+ domain = current_domain_name()
+ if servers.find(domain).channels.find(channel):
+ servers.find(domain).channels.find(channel).mark_read()
-def command_neveraway(args):
+def command_neveraway(current_buffer, args):
global never_away
if never_away == True:
never_away = False
@@ -357,20 +421,23 @@ def command_neveraway(args):
never_away = True
w.prnt("", "set as never_away")
-def command_printvar(args):
+def command_printvar(current_buffer, args):
+ w.prnt("", str(eval(args)))
+
+def command_p(current_buffer, args):
w.prnt("", str(eval(args)))
-def command_debug(args):
+def command_debug(current_buffer, args):
create_slack_debug_buffer()
-def command_debugstring(args):
+def command_debugstring(current_buffer, args):
global debug_string
if args == '':
debug_string = None
else:
debug_string = args
-def command_search(args):
+def command_search(current_buffer, args):
if not slack_buffer:
create_slack_buffer()
w.buffer_set(slack_buffer, "display", "1")
@@ -383,14 +450,7 @@ def command_search(args):
formatted_message = "%s / %s:\t%s" % (message["channel"]["name"], message['username'], message['text'])
w.prnt(slack_buffer,str(formatted_message))
-def command_awaybomb(args):
- for i in range(1,10):
- async_slack_api_request('presence.set', {"presence":"away"})
- time.sleep(.2)
- async_slack_api_request('presence.set', {"presence":"active"})
- time.sleep(.2)
-
-def command_nick(args):
+def command_nick(current_buffer, args):
urllib.urlopen("https://%s/account/settings" % (domain))
browser.select_form(nr=0)
browser.form['username'] = args
@@ -403,6 +463,7 @@ def slack_websocket_cb(data, 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
@@ -435,29 +496,23 @@ def write_debug(message_json):
return
w.prnt(slack_debug,output)
-#def modify_buffer_name(name, new_name_fmt="%s"):
-# buffer_name = "%s.%s" % (server, name)
-# buf_ptr = w.buffer_search("",buffer_name)
-# new_buffer_name = new_name_fmt % (name)
-# w.buffer_set(buf_ptr, "short_name", new_buffer_name)
-
def process_presence_change(message_json):
- server = servers.find(message_json["myserver"])
- global nick_ptr
- if message_json["user"] == nick:
- nick_ptr = w.nicklist_search_nick(general_buffer_ptr,'',nick)
- if message_json["presence"] == 'active':
- w.nicklist_nick_set(general_buffer_ptr, nick_ptr, "prefix", "+")
- else:
- w.nicklist_nick_set(general_buffer_ptr, nick_ptr, "prefix", " ")
- else:
+ #server = servers.find(message_json["myserver"])
+# global nick_ptr
+# if message_json["user"] == nick:
+# nick_ptr = w.nicklist_search_nick(general_buffer_ptr,'',nick)
+# if message_json["presence"] == 'active':
+# w.nicklist_nick_set(general_buffer_ptr, nick_ptr, "prefix", "+")
+# else:
+# w.nicklist_nick_set(general_buffer_ptr, nick_ptr, "prefix", " ")
+# else:
#this puts +/- in front of usernames in the buffer list. (req buffers.pl)
buffer_name = "%s.%s" % (domain, message_json["user"])
buf_ptr = w.buffer_search("",buffer_name)
if message_json["presence"] == 'active':
- server.users.find(message_json["user"]).set_active()
+ users.find(message_json["user"]).set_active()
else:
- server.users.find(message_json["user"]).set_inactive()
+ users.find(message_json["user"]).set_inactive()
def process_channel_marked(message_json):
server = servers.find(message_json["myserver"])
@@ -538,8 +593,9 @@ def process_im_open(message_json):
def process_user_typing(message_json):
server = servers.find(message_json["myserver"])
- server.server.channels.find(message_json["channel"]).set_typing(server.users.find(message_json["user"]).name)
+ server.channels.find(message_json["channel"]).set_typing(server.users.find(message_json["user"]).name)
+#todo: does this work?
def process_error(message_json):
connected = False
@@ -601,24 +657,23 @@ def typing_update_cb(data, remaining_calls):
return w.WEECHAT_RC_OK
def buffer_list_update_cb(data, remaining_calls):
- for server in servers:
- for channel in server.channels.find_by_class(Channel):
- if channel.is_someone_typing() == True:
- channel.rename(fmt=">%s")
- else:
- channel.rename()
- for channel in server.channels.find_by_class(GroupChannel):
- if channel.is_someone_typing() == True:
- channel.rename(fmt=">%s")
- else:
- channel.rename()
- for channel in server.channels.find_by_class(DmChannel):
-# if server.users.find(channel.name).presence == "active":
-# channel.rename(fmt="+%s")
-# else:
-# channel.rename(fmt=" %s")
- pass
- return w.WEECHAT_RC_OK
+ for channel in channels.find_by_class(Channel):
+ if channel.is_someone_typing() == True:
+ channel.rename(fmt=">%s")
+ else:
+ channel.rename()
+ for channel in channels.find_by_class(GroupChannel):
+ if channel.is_someone_typing() == True:
+ channel.rename(fmt=">%s")
+ else:
+ channel.rename()
+ for channel in channels.find_by_class(DmChannel):
+ if users.find(channel.name).presence == "active":
+ channel.rename(fmt="+%s")
+ else:
+ channel.rename(fmt=" %s")
+ pass
+ return w.WEECHAT_RC_OK
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)
@@ -628,26 +683,20 @@ def hotlist_cache_update_cb(data, remaining_calls):
w.infolist_free(prev_hotlist)
return w.WEECHAT_RC_OK
-def incoming_irc_message_cb(data, modifier, modifier_data, line):
-# currently blocks incoming irc messages. lets do this on websockets!
-# irc_privmsg
-# w.prnt("", str(data))
-# w.prnt("", str(modifier))
-# w.prnt("", str(modifier_data))
- if modifier_data.count('irc_privmsg') > 0:
- return ""
- else:
- return line
-
def buffer_opened_cb(signal, sig_type, data):
name = w.buffer_get_string(data, "name")
- if name.startswith(domain):
- name = name.split(".")[-1]
- if users.find(name):
- users.find(name).open()
- if channels.find(name):
- channels.find(name).attach_buffer()
- channels.find(name).get_history()
+ channel = channels.find(name)
+ channel.set_active()
+# domain = ".".join(name.split('.')[:-1])
+# if domain in servers:
+ channel.attach_buffer()
+ channel.get_history()
+# name = name.split(".")[-1]
+# if server.find(domain).users.find(name):
+# server.find(domain).users.find(name).open()
+# if server.find(domain).channels.find(name):
+# server.find(domain).channels.find(name).attach_buffer()
+# server.find(domain).channels.find(name).get_history()
return w.WEECHAT_RC_OK
def buffer_closing_cb(signal, sig_type, data):
@@ -659,12 +708,11 @@ def buffer_closing_cb(signal, sig_type, data):
def buffer_switch_cb(signal, sig_type, data):
#NOTE: we flush both the next and previous buffer so that all read pointer id up to date
global previous_buffer, hotlist
- for server in servers:
- if server.channels.find(previous_buffer):
- server.channels.find(previous_buffer).mark_read()
+ if channels.find(previous_buffer):
+ channels.find(previous_buffer).mark_read()
channel_name = current_buffer_name()
- previous_buffer = channel_name
+ previous_buffer = data
# if current_buffer_name().startswith(domain):
# channel_name = current_buffer_name(short=True)
@@ -732,14 +780,14 @@ def slack_mark_channel_read(channel_id):
channel.find(channel_id).mark_read()
#NOTE: switched to async/curl because sync slowed down the UI
-def async_slack_api_request(request, data):
- t = time.time() + random.random()
- request += "?t=%s" % t
- data["token"] = slack_api_token
- data = urllib.urlencode(data)
- post = {"maxconnects": "1", "post": "1", "postfields": data}
- url = 'https://%s/api/%s' % (domain, request)
- queue.append(['url:%s' % (url), post, 20000, 'url_processor_cb', str(data)])
+def async_slack_api_request(domain, token, request, data):
+ t = time.time()
+ request += "?t=%s" % t
+ data["token"] = token
+ data = urllib.urlencode(data)
+ post = {"post": "1", "postfields": data}
+ url = 'https://%s/api/%s' % (domain, request)
+ queue.append(['url:%s' % (url), post, 20000, 'url_processor_cb', str(data)])
queue = []
@@ -757,7 +805,7 @@ def async_queue_cb(data, remaining_calls):
query = urlparse.parse_qs(item[-1])
if query.has_key("channel") and item[0].find('history') > -1:
channel = query["channel"][0]
- dbg("downloading channel history for %s" % (channels.find(channel).name))
+ dbg("downloading channel history for %s" % (channel))
except:
pass
if item.__class__ == list:
@@ -770,6 +818,7 @@ def async_queue_cb(data, remaining_calls):
return w.WEECHAT_RC_OK
def url_processor_cb(data, command, return_code, out, err):
+ url_processor_lock=False
global url_processor_lock, big_data
if return_code == 0:
url_processor_lock=False
@@ -785,12 +834,15 @@ def url_processor_cb(data, command, return_code, out, err):
query = urlparse.parse_qs(data)
if query.has_key("channel"):
channel = query["channel"][0]
+ if query.has_key("token"):
+ token = query["token"][0]
message_json = json.loads(big_data[identifier])
del big_data[identifier]
if message_json.has_key("messages"):
messages = message_json["messages"].reverse()
for message in message_json["messages"]:
- message["channel"] = channels.find(channel)
+ message["myserver"] = servers.find(token).domain
+ message["channel"] = servers.find(token).channels.find(channel)
process_message(message)
return w.WEECHAT_RC_OK
@@ -811,6 +863,13 @@ def mark_silly_channels_read(channel):
### Utility Methods
+def current_domain_name():
+ buffer = w.current_buffer()
+ #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")
@@ -880,7 +939,7 @@ if __name__ == "__main__":
### Global var section
slack_api_token = w.config_get_plugin("slack_api_token")
- server = w.config_get_plugin("server")
+ #server = w.config_get_plugin("server")
timeout = w.config_get_plugin("timeout")
channels_always_marked_read = [x.strip() for x in w.config_get_plugin("channels_always_marked_read").split(',')]
@@ -896,7 +955,6 @@ if __name__ == "__main__":
login_data = None
nick = None
nick_ptr = None
- general_buffer_ptr = None
name = None
connected = False
never_away = False
@@ -905,10 +963,11 @@ if __name__ == "__main__":
### End global var section
- channels = SearchList()
- users = SearchList()
+ #channels = SearchList()
servers = SearchList()
servers.append(SlackServer(slack_api_token))
+ channels = Meta('channels', servers)
+ users = Meta('users', servers)
# w.hook_timer(60000, 0, 0, "slack_connection_persistence_cb", "")