11#!/usr/bin/env python
22import sys
33import glob
4- import yaml
54import os
65import time
76import logging
87
9- from argparse import ArgumentParser
10-
118from slackclient import SlackClient
129
1310sys .dont_write_bytecode = True
1411
1512
16- def dbg (debug_string ):
17- if debug :
18- logging .info (debug_string )
19-
20-
2113class RtmBot (object ):
22- def __init__ (self , token ):
14+ def __init__ (self , config ):
15+ # set the config object
16+ self .config = config
17+ global site_config
18+ site_config = self .config
19+
20+ # set slack token
21+ self .token = config .get ('SLACK_TOKEN' )
22+
23+ # set working directory for loading plugins or other files
24+ working_directory = os .path .dirname (sys .argv [0 ])
25+ self .directory = self .config .get ('BASE_PATH' , working_directory )
26+ if not self .directory .startswith ('/' ):
27+ path = '{}/{}' .format (os .getcwd (), self .directory )
28+ self .directory = os .path .abspath (path )
29+
30+ # establish logging
31+ log_file = config .get ('LOGFILE' , 'rtmbot.log' )
32+ logging .basicConfig (filename = log_file ,
33+ level = logging .INFO ,
34+ format = '%(asctime)s %(message)s' )
35+ logging .info (self .directory )
36+ if 'DEBUG' in self .config :
37+ self .debug = self .config .get ('DEBUG' )
38+ else :
39+ self .debug = False
40+
41+ # initialize stateful fields
2342 self .last_ping = 0
24- self .token = token
2543 self .bot_plugins = []
2644 self .slack_client = None
2745
46+ def _dbg (self , debug_string ):
47+ if self .debug :
48+ logging .info (debug_string )
49+
2850 def connect (self ):
2951 """Convenience method that creates Server instance"""
3052 self .slack_client = SlackClient (self .token )
3153 self .slack_client .rtm_connect ()
3254
33- def start (self ):
55+ def _start (self ):
3456 self .connect ()
3557 self .load_plugins ()
3658 while True :
@@ -41,6 +63,14 @@ def start(self):
4163 self .autoping ()
4264 time .sleep (.1 )
4365
66+ def start (self ):
67+ if 'DAEMON' in self .config :
68+ if self .config .get ('DAEMON' ):
69+ import daemon
70+ with daemon .DaemonContext ():
71+ self ._start ()
72+ self ._start ()
73+
4474 def autoping (self ):
4575 # hardcode the interval to 3 seconds
4676 now = int (time .time ())
@@ -51,7 +81,7 @@ def autoping(self):
5181 def input (self , data ):
5282 if "type" in data :
5383 function_name = "process_" + data ["type" ]
54- dbg ("got {}" .format (function_name ))
84+ self . _dbg ("got {}" .format (function_name ))
5585 for plugin in self .bot_plugins :
5686 plugin .register_jobs ()
5787 plugin .do (function_name , data )
@@ -74,17 +104,18 @@ def crons(self):
74104 plugin .do_jobs ()
75105
76106 def load_plugins (self ):
77- for plugin in glob .glob (directory + '/plugins/*' ):
107+ for plugin in glob .glob (self . directory + '/plugins/*' ):
78108 sys .path .insert (0 , plugin )
79- sys .path .insert (0 , directory + '/plugins/' )
80- for plugin in glob .glob (directory + '/plugins/*.py' ) + \
81- glob .glob (directory + '/plugins/*/*.py' ):
109+ sys .path .insert (0 , self . directory + '/plugins/' )
110+ for plugin in glob .glob (self . directory + '/plugins/*.py' ) + \
111+ glob .glob (self . directory + '/plugins/*/*.py' ):
82112 logging .info (plugin )
83113 name = plugin .split ('/' )[- 1 ][:- 3 ]
84- # try:
85- self .bot_plugins .append (Plugin (name ))
86- # except:
87- # print "error loading plugin %s" % name
114+ if name in self .config :
115+ logging .info ("config found for: " + name )
116+ plugin_config = self .config .get (name , {})
117+ plugin_config ['DEBUG' ] = self .debug
118+ self .bot_plugins .append (Plugin (name , plugin_config ))
88119
89120
90121class Plugin (object ):
@@ -95,11 +126,10 @@ def __init__(self, name, plugin_config=None):
95126 self .name = name
96127 self .jobs = []
97128 self .module = __import__ (name )
129+ self .module .config = plugin_config
130+ self .debug = self .module .config .get ('DEBUG' )
98131 self .register_jobs ()
99132 self .outputs = []
100- if name in config :
101- logging .info ("config found for: " + name )
102- self .module .config = config [name ]
103133 if 'setup' in dir (self .module ):
104134 self .module .setup ()
105135
@@ -115,18 +145,18 @@ def register_jobs(self):
115145 def do (self , function_name , data ):
116146 if function_name in dir (self .module ):
117147 # this makes the plugin fail with stack trace in debug mode
118- if not debug :
148+ if not self . debug :
119149 try :
120150 eval ("self.module." + function_name )(data )
121151 except :
122- dbg ("problem in module {} {}" .format (function_name , data ))
152+ self . _dbg ("problem in module {} {}" .format (function_name , data ))
123153 else :
124154 eval ("self.module." + function_name )(data )
125155 if "catch_all" in dir (self .module ):
126156 try :
127157 self .module .catch_all (data )
128158 except :
129- dbg ("problem in catch all" )
159+ self . _dbg ("problem in catch all" )
130160
131161 def do_jobs (self ):
132162 for job in self .jobs :
@@ -160,11 +190,11 @@ def __repr__(self):
160190
161191 def check (self ):
162192 if self .lastrun + self .interval < time .time ():
163- if not debug :
193+ if not debug : # TODO: This isn't in scope any more
164194 try :
165195 self .function ()
166196 except :
167- dbg ("problem" )
197+ self . _dbg ("problem" )
168198 else :
169199 self .function ()
170200 self .lastrun = time .time ()
@@ -173,54 +203,3 @@ def check(self):
173203
174204class UnknownChannel (Exception ):
175205 pass
176-
177-
178- def main_loop ():
179- if "LOGFILE" in config :
180- logging .basicConfig (
181- filename = config ["LOGFILE" ],
182- level = logging .INFO ,
183- format = '%(asctime)s %(message)s'
184- )
185- logging .info (directory )
186- try :
187- bot .start ()
188- except KeyboardInterrupt :
189- sys .exit (0 )
190- except :
191- logging .exception ('OOPS' )
192-
193-
194- def parse_args ():
195- parser = ArgumentParser ()
196- parser .add_argument (
197- '-c' ,
198- '--config' ,
199- help = 'Full path to config file.' ,
200- metavar = 'path'
201- )
202- return parser .parse_args ()
203-
204-
205- if __name__ == "__main__" :
206- args = parse_args ()
207- directory = os .path .dirname (sys .argv [0 ])
208- if not directory .startswith ('/' ):
209- directory = os .path .abspath ("{}/{}" .format (os .getcwd (),
210- directory
211- ))
212-
213- config = yaml .load (open (args .config or 'rtmbot.conf' , 'r' ))
214- debug = config ["DEBUG" ]
215- bot = RtmBot (config ["SLACK_TOKEN" ])
216- site_plugins = []
217- files_currently_downloading = []
218- job_hash = {}
219-
220- if 'DAEMON' in config :
221- if config ["DAEMON" ]:
222- import daemon
223-
224- with daemon .DaemonContext ():
225- main_loop ()
226- main_loop ()
0 commit comments