Skip to content
This repository was archived by the owner on Aug 15, 2022. It is now read-only.

Commit 4c7fa8b

Browse files
author
Jeff Ammons
committed
Merge branch 'master' of https://github.com/tzakrajs/python-rtmbot into tzakrajs-master
Also fixes some PEP8 issues and a number of small bugs.
2 parents aa710d2 + bfe7df4 commit 4c7fa8b

File tree

5 files changed

+105
-79
lines changed

5 files changed

+105
-79
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
*.pyc
22
/rtmbot.conf
33
/plugins/**
4+
/build/**
5+
*.log
46
env
57
.tox

rtmbot/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from core import *
2+
3+
site_config = {}
Lines changed: 58 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,58 @@
11
#!/usr/bin/env python
22
import sys
33
import glob
4-
import yaml
54
import os
65
import time
76
import logging
87

9-
from argparse import ArgumentParser
10-
118
from slackclient import SlackClient
129

1310
sys.dont_write_bytecode = True
1411

1512

16-
def dbg(debug_string):
17-
if debug:
18-
logging.info(debug_string)
19-
20-
2113
class 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

90121
class 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

174204
class 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()

setup.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/usr/bin/env python
2+
3+
from distutils.core import setup
4+
5+
setup(
6+
name='rtmbot',
7+
version='0.10',
8+
description='A Slack bot written in python that connects via the RTM API.',
9+
author='Ryan Huber',
10+
author_email='[email protected]',
11+
url='https://github.com/slackhq/python-rtmbot',
12+
packages=['rtmbot'],
13+
)

start_rtmbot.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#!/usr/bin/env python
2+
import sys
3+
import logging
4+
from argparse import ArgumentParser
5+
6+
import yaml
7+
from rtmbot import RtmBot
8+
9+
10+
def parse_args():
11+
parser = ArgumentParser()
12+
parser.add_argument(
13+
'-c',
14+
'--config',
15+
help='Full path to config file.',
16+
metavar='path'
17+
)
18+
return parser.parse_args()
19+
20+
# load args with config path
21+
args = parse_args()
22+
config = yaml.load(file(args.config or 'rtmbot.conf', 'r'))
23+
bot = RtmBot(config)
24+
try:
25+
bot.start()
26+
except KeyboardInterrupt:
27+
sys.exit(0)
28+
except:
29+
logging.exception('OOPS')

0 commit comments

Comments
 (0)