-
Notifications
You must be signed in to change notification settings - Fork 1
/
ctftime.py
117 lines (95 loc) · 3.43 KB
/
ctftime.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
'''
legos.ctftime, A plugin for Legobot to interact with CTFtime API
Copyright (C) 2017 Bren Briggs
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Portions of CTFtime API interaction are borrowed from
https://github.com/spiperac/ctftime-ircbot, released under GPLv3
'''
import logging
import requests
from datetime import datetime
from Legobot.Lego import Lego
logger = logging.getLogger(__name__)
API_URL = 'https://ctftime.org/api/v1'
class CTFtime(Lego):
@staticmethod
def listening_for(message):
if message['text'] is not None:
return message['text'].startswith('!ctftime ')
def handle(self, message):
try:
cmd = message['text'].split()[1]
except IndexError as e:
logger.warn('Lego called without arguments')
return False
dispatcher = {
'upcoming': self._get_upcoming,
'top10': self._get_top10
}
if cmd in dispatcher:
logger.debug('Dispatching command {}'.format(cmd))
dispatcher[cmd](message)
return
@staticmethod
def get_name():
return 'ctftime'
@staticmethod
def get_help():
return 'Get info from the CTFtime API.' \
'Usage: !ctftime <upcoming> | <top10>'
# Internal methods (the actual work)
@staticmethod
def _handle_opts(message):
try:
target = message['metadata']['source_channel']
opts = {'target': target}
return opts
except IndexError:
return None
def _get_upcoming(self, message):
r = requests.get('{}/events/'.format(API_URL))
opts = self._handle_opts(message)
if opts is None:
return False
if r.status_code == requests.codes.ok:
for event in r.json():
reply = 'Name: {}, Format: {}, Date {} - {}'.format(
event['title'],
event['format'],
event['start'],
event['finish'])
logger.info('Reply: {}'.format(reply))
self.reply(message, reply, opts)
return True
else:
return False
def _get_top10(self, message):
year = str(datetime.now().year)
r = requests.get('{}/top/{}/'.format(API_URL, year))
opts = self._handle_opts(message)
if opts is None:
return False
if r.status_code == requests.codes.ok:
teams = r.json()[year]
# Column Formatting
longest_name = max(
[team['team_name'] for team in teams],
key=len)
margin_width = len(longest_name)
# Results
self.reply(message, '~~~{} Results~~~'.format(year), opts)
for team in teams:
margin = '-' * (margin_width - len(team['team_name']))
reply = '{}{}|{}'.format(
team['team_name'],
margin,
team['points'])
self.reply(message, reply, opts)
return True
else:
reply = 'Top ten data not found for year {}'.format(year)
self.reply(message, reply, opts)
return False