1414
1515from slackclient import SlackClient
1616
17- def dbg (debug_string ):
18- if debug :
19- logging .info (debug_string )
20-
2117class RtmBot (object ):
22- def __init__ (self , token ):
18+ def __init__ (self , config ):
19+ #set the config object
20+ self .config = config
21+ global site_config
22+ site_config = self .config
23+ #set slack token
24+ self .token = config .get ('SLACK_TOKEN' )
25+ #set working directory for loading plugins or other files
26+ working_directory = os .path .dirname (sys .argv [0 ])
27+ self .directory = self .config .get ('BASE_PATH' , working_directory )
28+ if not self .directory .startswith ('/' ):
29+ path = '{}/{}' .format (os .getcwd (), self .directory )
30+ self .directory = os .path .abspath (path )
31+ #establish logging
32+ log_file = config .get ('LOGFILE' , 'rtmbot.log' )
33+ logging .basicConfig (filename = log_file ,
34+ level = logging .INFO ,
35+ format = '%(asctime)s %(message)s' )
36+ logging .info (self .directory )
37+ self .debug = self .config .has_key ('DEBUG' )
38+ #initialize stateful fields
2339 self .last_ping = 0
24- self .token = token
2540 self .bot_plugins = []
2641 self .slack_client = None
42+
43+ def _dbg (self , debug_string ):
44+ if self .debug :
45+ logging .info (debug_string )
46+
2747 def connect (self ):
2848 """Convenience method that creates Server instance"""
2949 self .slack_client = SlackClient (self .token )
3050 self .slack_client .rtm_connect ()
31- def start (self ):
51+
52+ def _start (self ):
3253 self .connect ()
3354 self .load_plugins ()
3455 while True :
@@ -38,19 +59,30 @@ def start(self):
3859 self .output ()
3960 self .autoping ()
4061 time .sleep (.1 )
62+
63+ def start (self ):
64+ if self .config .has_key ('DAEMON' ):
65+ if self .config .get ('DAEMON' ):
66+ import daemon
67+ with daemon .DaemonContext ():
68+ self ._start ()
69+ self ._start ()
70+
4171 def autoping (self ):
4272 #hardcode the interval to 3 seconds
4373 now = int (time .time ())
4474 if now > self .last_ping + 3 :
4575 self .slack_client .server .ping ()
4676 self .last_ping = now
77+
4778 def input (self , data ):
4879 if "type" in data :
4980 function_name = "process_" + data ["type" ]
50- dbg ("got {}" .format (function_name ))
81+ self . _dbg ("got {}" .format (function_name ))
5182 for plugin in self .bot_plugins :
5283 plugin .register_jobs ()
5384 plugin .do (function_name , data )
85+
5486 def output (self ):
5587 for plugin in self .bot_plugins :
5688 limiter = False
@@ -63,18 +95,23 @@ def output(self):
6395 message = output [1 ].encode ('ascii' ,'ignore' )
6496 channel .send_message ("{}" .format (message ))
6597 limiter = True
98+
6699 def crons (self ):
67100 for plugin in self .bot_plugins :
68101 plugin .do_jobs ()
102+
69103 def load_plugins (self ):
70- for plugin in glob .glob (directory + '/plugins/*' ):
104+ for plugin in glob .glob (self . directory + '/plugins/*' ):
71105 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' ):
106+ sys .path .insert (0 , self . directory + '/plugins/' )
107+ for plugin in glob .glob (self . directory + '/plugins/*.py' ) + glob .glob (self . directory + '/plugins/*/*.py' ):
74108 logging .info (plugin )
75109 name = plugin .split ('/' )[- 1 ][:- 3 ]
76110# try:
77- self .bot_plugins .append (Plugin (name ))
111+ if name in self .config :
112+ logging .info ("config found for: " + name )
113+ plugin_config = self .config .get (name )
114+ self .bot_plugins .append (Plugin (name , plugin_config ))
78115# except:
79116# print "error loading plugin %s" % name
80117
@@ -83,13 +120,12 @@ def __init__(self, name, plugin_config={}):
83120 self .name = name
84121 self .jobs = []
85122 self .module = __import__ (name )
123+ self .module .config = plugin_config
86124 self .register_jobs ()
87125 self .outputs = []
88- if name in config :
89- logging .info ("config found for: " + name )
90- self .module .config = config [name ]
91126 if 'setup' in dir (self .module ):
92127 self .module .setup ()
128+
93129 def register_jobs (self ):
94130 if 'crontable' in dir (self .module ):
95131 for interval , function in self .module .crontable :
@@ -98,24 +134,27 @@ def register_jobs(self):
98134 self .module .crontable = []
99135 else :
100136 self .module .crontable = []
137+
101138 def do (self , function_name , data ):
102139 if function_name in dir (self .module ):
103140 #this makes the plugin fail with stack trace in debug mode
104141 if not debug :
105142 try :
106143 eval ("self.module." + function_name )(data )
107144 except :
108- dbg ("problem in module {} {}" .format (function_name , data ))
145+ self . _dbg ("problem in module {} {}" .format (function_name , data ))
109146 else :
110147 eval ("self.module." + function_name )(data )
111148 if "catch_all" in dir (self .module ):
112149 try :
113150 self .module .catch_all (data )
114151 except :
115- dbg ("problem in catch all" )
152+ self ._dbg ("problem in catch all" )
153+
116154 def do_jobs (self ):
117155 for job in self .jobs :
118156 job .check ()
157+
119158 def do_output (self ):
120159 output = []
121160 while True :
@@ -134,68 +173,24 @@ def __init__(self, interval, function):
134173 self .function = function
135174 self .interval = interval
136175 self .lastrun = 0
176+
137177 def __str__ (self ):
138178 return "{} {} {}" .format (self .function , self .interval , self .lastrun )
179+
139180 def __repr__ (self ):
140181 return self .__str__ ()
182+
141183 def check (self ):
142184 if self .lastrun + self .interval < time .time ():
143185 if not debug :
144186 try :
145187 self .function ()
146188 except :
147- dbg ("problem" )
189+ self . _dbg ("problem" )
148190 else :
149191 self .function ()
150192 self .lastrun = time .time ()
151193 pass
152194
153195class UnknownChannel (Exception ):
154196 pass
155-
156-
157- def main_loop ():
158- if "LOGFILE" in config :
159- logging .basicConfig (filename = config ["LOGFILE" ], level = logging .INFO , format = '%(asctime)s %(message)s' )
160- logging .info (directory )
161- try :
162- bot .start ()
163- except KeyboardInterrupt :
164- sys .exit (0 )
165- except :
166- logging .exception ('OOPS' )
167-
168-
169- def parse_args ():
170- parser = ArgumentParser ()
171- parser .add_argument (
172- '-c' ,
173- '--config' ,
174- help = 'Full path to config file.' ,
175- metavar = 'path'
176- )
177- return parser .parse_args ()
178-
179-
180- if __name__ == "__main__" :
181- args = parse_args ()
182- directory = os .path .dirname (sys .argv [0 ])
183- if not directory .startswith ('/' ):
184- directory = os .path .abspath ("{}/{}" .format (os .getcwd (),
185- directory
186- ))
187-
188- config = yaml .load (file (args .config or 'rtmbot.conf' , 'r' ))
189- debug = config ["DEBUG" ]
190- bot = RtmBot (config ["SLACK_TOKEN" ])
191- site_plugins = []
192- files_currently_downloading = []
193- job_hash = {}
194-
195- if config .has_key ("DAEMON" ):
196- if config ["DAEMON" ]:
197- import daemon
198- with daemon .DaemonContext ():
199- main_loop ()
200- main_loop ()
201-
0 commit comments