11#!/usr/bin/env python
2-
32import sys
4- sys .dont_write_bytecode = True
5-
63import glob
74import yaml
8- import json
95import os
10- import sys
116import time
127import logging
8+
139from argparse import ArgumentParser
1410
1511from slackclient import SlackClient
1612
13+ sys .dont_write_bytecode = True
14+
15+
1716def dbg (debug_string ):
1817 if debug :
1918 logging .info (debug_string )
2019
20+
2121class RtmBot (object ):
2222 def __init__ (self , token ):
2323 self .last_ping = 0
2424 self .token = token
2525 self .bot_plugins = []
2626 self .slack_client = None
27+
2728 def connect (self ):
2829 """Convenience method that creates Server instance"""
2930 self .slack_client = SlackClient (self .token )
3031 self .slack_client .rtm_connect ()
32+
3133 def start (self ):
3234 self .connect ()
3335 self .load_plugins ()
@@ -38,48 +40,58 @@ def start(self):
3840 self .output ()
3941 self .autoping ()
4042 time .sleep (.1 )
43+
4144 def autoping (self ):
42- #hardcode the interval to 3 seconds
45+ # hardcode the interval to 3 seconds
4346 now = int (time .time ())
4447 if now > self .last_ping + 3 :
4548 self .slack_client .server .ping ()
4649 self .last_ping = now
50+
4751 def input (self , data ):
4852 if "type" in data :
4953 function_name = "process_" + data ["type" ]
5054 dbg ("got {}" .format (function_name ))
5155 for plugin in self .bot_plugins :
5256 plugin .register_jobs ()
5357 plugin .do (function_name , data )
58+
5459 def output (self ):
5560 for plugin in self .bot_plugins :
5661 limiter = False
5762 for output in plugin .do_output ():
5863 channel = self .slack_client .server .channels .find (output [0 ])
59- if channel != None and output [1 ] != None :
60- if limiter == True :
64+ if channel is not None and output [1 ] is not None :
65+ if limiter :
6166 time .sleep (.1 )
6267 limiter = False
63- message = output [1 ].encode ('ascii' ,'ignore' )
68+ message = output [1 ].encode ('ascii' , 'ignore' )
6469 channel .send_message ("{}" .format (message ))
6570 limiter = True
71+
6672 def crons (self ):
6773 for plugin in self .bot_plugins :
6874 plugin .do_jobs ()
75+
6976 def load_plugins (self ):
70- for plugin in glob .glob (directory + '/plugins/*' ):
77+ for plugin in glob .glob (directory + '/plugins/*' ):
7178 sys .path .insert (0 , plugin )
72- sys .path .insert (0 , directory + '/plugins/' )
73- for plugin in glob .glob (directory + '/plugins/*.py' ) + glob .glob (directory + '/plugins/*/*.py' ):
79+ sys .path .insert (0 , directory + '/plugins/' )
80+ for plugin in glob .glob (directory + '/plugins/*.py' ) + \
81+ glob .glob (directory + '/plugins/*/*.py' ):
7482 logging .info (plugin )
7583 name = plugin .split ('/' )[- 1 ][:- 3 ]
76- # try:
84+ # try:
7785 self .bot_plugins .append (Plugin (name ))
78- # except:
79- # print "error loading plugin %s" % name
86+ # except:
87+ # print "error loading plugin %s" % name
88+
8089
8190class Plugin (object ):
82- def __init__ (self , name , plugin_config = {}):
91+
92+ def __init__ (self , name , plugin_config = None ):
93+ if plugin_config is None :
94+ plugin_config = {} # TODO: is this variable necessary?
8395 self .name = name
8496 self .jobs = []
8597 self .module = __import__ (name )
@@ -90,32 +102,36 @@ def __init__(self, name, plugin_config={}):
90102 self .module .config = config [name ]
91103 if 'setup' in dir (self .module ):
92104 self .module .setup ()
105+
93106 def register_jobs (self ):
94107 if 'crontable' in dir (self .module ):
95108 for interval , function in self .module .crontable :
96- self .jobs .append (Job (interval , eval ("self.module." + function )))
109+ self .jobs .append (Job (interval , eval ("self.module." + function )))
97110 logging .info (self .module .crontable )
98111 self .module .crontable = []
99112 else :
100113 self .module .crontable = []
114+
101115 def do (self , function_name , data ):
102116 if function_name in dir (self .module ):
103- #this makes the plugin fail with stack trace in debug mode
117+ # this makes the plugin fail with stack trace in debug mode
104118 if not debug :
105119 try :
106- eval ("self.module." + function_name )(data )
120+ eval ("self.module." + function_name )(data )
107121 except :
108122 dbg ("problem in module {} {}" .format (function_name , data ))
109123 else :
110- eval ("self.module." + function_name )(data )
124+ eval ("self.module." + function_name )(data )
111125 if "catch_all" in dir (self .module ):
112126 try :
113127 self .module .catch_all (data )
114128 except :
115129 dbg ("problem in catch all" )
130+
116131 def do_jobs (self ):
117132 for job in self .jobs :
118133 job .check ()
134+
119135 def do_output (self ):
120136 output = []
121137 while True :
@@ -129,15 +145,19 @@ def do_output(self):
129145 self .module .outputs = []
130146 return output
131147
148+
132149class Job (object ):
133150 def __init__ (self , interval , function ):
134151 self .function = function
135152 self .interval = interval
136153 self .lastrun = 0
154+
137155 def __str__ (self ):
138156 return "{} {} {}" .format (self .function , self .interval , self .lastrun )
157+
139158 def __repr__ (self ):
140159 return self .__str__ ()
160+
141161 def check (self ):
142162 if self .lastrun + self .interval < time .time ():
143163 if not debug :
@@ -150,13 +170,18 @@ def check(self):
150170 self .lastrun = time .time ()
151171 pass
152172
173+
153174class UnknownChannel (Exception ):
154175 pass
155176
156177
157178def main_loop ():
158179 if "LOGFILE" in config :
159- logging .basicConfig (filename = config ["LOGFILE" ], level = logging .INFO , format = '%(asctime)s %(message)s' )
180+ logging .basicConfig (
181+ filename = config ["LOGFILE" ],
182+ level = logging .INFO ,
183+ format = '%(asctime)s %(message)s'
184+ )
160185 logging .info (directory )
161186 try :
162187 bot .start ()
@@ -182,20 +207,20 @@ def parse_args():
182207 directory = os .path .dirname (sys .argv [0 ])
183208 if not directory .startswith ('/' ):
184209 directory = os .path .abspath ("{}/{}" .format (os .getcwd (),
185- directory
186- ))
210+ directory
211+ ))
187212
188- config = yaml .load (file (args .config or 'rtmbot.conf' , 'r' ))
213+ config = yaml .load (open (args .config or 'rtmbot.conf' , 'r' ))
189214 debug = config ["DEBUG" ]
190215 bot = RtmBot (config ["SLACK_TOKEN" ])
191216 site_plugins = []
192217 files_currently_downloading = []
193218 job_hash = {}
194219
195- if config . has_key ( " DAEMON" ) :
220+ if ' DAEMON' in config :
196221 if config ["DAEMON" ]:
197222 import daemon
223+
198224 with daemon .DaemonContext ():
199225 main_loop ()
200226 main_loop ()
201-
0 commit comments