Skip to content

Instantly share code, notes, and snippets.

@epequeno
Created October 20, 2016 06:01
Show Gist options
  • Save epequeno/09da2983f6313e098b4612c4777fe849 to your computer and use it in GitHub Desktop.
Save epequeno/09da2983f6313e098b4612c4777fe849 to your computer and use it in GitHub Desktop.
slackbot to monitor urls for 200 status code
# stdlib
import multiprocessing as mp
from time import sleep
from subprocess import call
from urllib.parse import quote
# 3rd party
import requests
from slackbot.bot import Bot, respond_to
import validators
# local
from slackbot_settings import API_TOKEN
# globals
JOBS = []
WORKERS = []
JOB_COUNTER = 0
def send(message, room):
cmd = 'curl https://slack.com/api/chat.postMessage?token={}&channel={}&text={}&as_user=true&pretty=1'
cmd = cmd.format(API_TOKEN, quote(room), quote(message))
call(cmd.split())
@respond_to('mon (.*)')
@respond_to('mon (.*) (.*)')
def monitor(message, action=None, job_num=None):
# job_num can be an int or str, cast to int if needed.
if job_num and job_num != 'all':
job_num = int(job_num)
def worker(j):
while True:
res = None
try:
res = requests.get(j['url'])
except Exception as e:
m = '{}) {} - {}'.format(j['job_num'], j['url'], e)
send(m, message.body['channel'])
sleep(600)
if res is None:
continue
elif res.status_code != 200:
m = '{}) {} - {}'.format(j['job_num'], res.status_code, j['url'])
send(m, message.body['channel'])
sleep(600)
sleep(60)
def ls():
global JOBS
if len(JOBS) == 0:
message.send('no current jobs')
return
m = '```{}```'
body = ''
for j in sorted(JOBS, key=lambda x: x['job_num']):
if j['active']:
line = '{}) {}\n'.format(j['job_num'], j['url'])
else:
line = '{}) {} (paused)\n'.format(j['job_num'], j['url'])
body += line
body.rstrip()
message.send(m.format(body))
def pause(job):
global JOBS
global WORKERS
if job == 'all':
pass
elif job not in [x['job_num'] for x in JOBS]:
message.send('job {} not found'.format(job))
return
m = 'pausing job: {}'.format(job)
message.send(m)
if job == 'all':
for w in WORKERS:
w.terminate()
for j in JOBS:
j['active'] = False
else:
for j in JOBS:
if j['job_num'] == job:
j['active'] = False
for w in WORKERS:
if w.pid == j['worker']:
w.terminate()
def rm(job):
global JOB_COUNTER
global JOBS
global WORKERS
m = 'removing job: {}'.format(job)
message.send(m)
if job == 'all':
JOBS = []
JOB_COUNTER = 0
for w in WORKERS:
w.terminate()
WORKERS = []
return
elif not isinstance(job, int):
message.send("I didn't understand that")
return
JOB_COUNTER -= 1
for j in JOBS:
if j['job_num'] == job:
for w in WORKERS:
if w.pid == j['worker']:
w.terminate()
JOBS = [x for x in JOBS if x['job_num'] != job]
def resume(job):
global JOBS
global WORKERS
if job == 'all':
pass
elif job not in [x['job_num'] for x in JOBS]:
message.send('job {} not found'.format(job))
return
m = 'resuming job: {}'.format(job)
message.send(m)
if job == 'all':
for j in JOBS:
if not j['active']:
w = mp.Process(target=worker, args=[j])
w.start()
WORKERS.append(w)
j['active'] = True
j['worker'] = w.pid
return
for j in JOBS:
if j['job_num'] == job:
w = mp.Process(target=worker, args=[j])
w.start()
WORKERS.append(w)
j['active'] = True
j['worker'] = w.pid
def mon_help():
with open('mon_help', 'r') as fd:
message.send(fd.read())
actions = {'ls': ls,
'pause': pause,
'rm': rm,
'resume': resume,
'help': mon_help}
url = action.lstrip('<').rstrip('>')
valid_url = validators.url(url)
if valid_url:
global JOB_COUNTER
global WORKERS
if JOB_COUNTER == 5:
message.send('too many jobs, please remove one.')
return
JOB_COUNTER += 1
full = set(range(1, 6))
current = set(j['job_num'] for j in JOBS)
j = {'job_num': min(full - current) if current != full else JOB_COUNTER,
'url': url,
'active': True}
p = mp.Process(target=worker, args=[j])
p.start()
j['worker'] = p.pid
JOBS.append(j)
WORKERS.append(p)
msg = 'added job {}) {}'.format(j['job_num'], j['url'])
message.send(msg)
elif action in actions:
if job_num:
try:
actions[action](job_num)
except TypeError:
message.send('`job_num` not needed for {}'.format(action))
actions[action]()
else:
if len(action.split()) == 2:
return
try:
actions[action]()
except TypeError:
message.send("missing argument `job_num` to: {}".format(action))
elif not len(url.split()) > 1:
msg = 'invalid url: {}'.format(url)
message.send(msg)
def main():
bot = Bot()
bot.run()
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment