ubot2/plugins/hearts.py

147 lines
4 KiB
Python
Raw Normal View History

2016-05-18 09:43:43 -04:00
# hearts.py
# Keepin' score is better with <3.
# Eryn Wells <eryn@erynwells.me>
import json
2016-05-19 11:59:33 -04:00
import logging
2016-05-18 09:43:43 -04:00
import os.path
import re
HEARTS_FILE = 'hearts.json'
2016-05-19 11:59:33 -04:00
PLUSES = {'prefix': ['++', '<3', '&lt;3', ':heart:', ':yellow_heart:', ':green_heart:', ':blue_heart:', ':purple_heart:', '❤️', '💛', '💚', '💙', '💜'],
'suffix': ['++', '<3', '&lt;3', ':heart:', ':yellow_heart:', ':green_heart:', ':blue_heart:', ':purple_heart:', '❤️', '💛', '💚', '💙', '💜']}
MINUSES = {'prefix': ['--', '', '', '</3', '&lt;/3', ':broken_heart:', '💔'],
'suffix': ['--', '', '', '</3', '&lt;/3', ':broken_heart:', '💔']}
LOGGER = logging.getLogger('hearts')
2016-05-18 09:43:43 -04:00
outputs = []
def process_message(data):
try:
2016-05-19 11:59:33 -04:00
text = data['text'].strip()
2016-05-18 09:43:43 -04:00
except KeyError:
# TODO: Make this better.
return
if text == '!top5':
scores = top5()
outputs.append([data['channel'], scores])
return
if text.startswith('!erase'):
name = text[len('!erase'):].strip()
success = erase_score(name)
if success:
outputs.append([data['channel'], "Erased score for _{}_.".format(name)])
else:
outputs.append([data['channel'], "No score for _{}_.".format(name)])
return
2016-05-19 11:59:33 -04:00
LOGGER.info('Processing message: %s', text)
score, name = calculate_score_and_find_operators(text)
if score is not None:
LOGGER.info('Adding %s to %s', score, name)
if score:
score = update_item(name, score)
outputs.append([data['channel'], '_{}_ now has a score of {}.'.format(name, score)])
2016-05-18 09:43:43 -04:00
else:
2016-05-19 11:59:33 -04:00
outputs.append([data['channel'], 'No score change for _{}_.'.format(name)])
def calculate_score_and_find_operators(text):
original_text = text
score = 0
2016-05-18 09:43:43 -04:00
2016-05-19 11:59:33 -04:00
times, text = _do_operators(text, PLUSES['prefix'], is_prefix=True)
score += times
2016-05-18 09:43:43 -04:00
2016-05-19 11:59:33 -04:00
times, text = _do_operators(text, PLUSES['suffix'], is_prefix=False)
score += times
2016-05-18 09:43:43 -04:00
2016-05-19 11:59:33 -04:00
times, text = _do_operators(text, MINUSES['prefix'], is_prefix=True)
score -= times
2016-05-18 09:43:43 -04:00
2016-05-19 11:59:33 -04:00
times, text = _do_operators(text, MINUSES['suffix'], is_prefix=False)
score -= times
2016-05-18 09:43:43 -04:00
2016-05-19 11:59:33 -04:00
did_change = original_text != text
if did_change:
return score, text
else:
return None, None
def _do_operators(text, operators, is_prefix):
times = 0
length = 0
check_func = has_prefix if is_prefix else has_suffix
while True:
op = check_func(text, operators)
if not op:
break
LOGGER.info('Found operator: {} (prefix = {})'.format(op, is_prefix))
times += 1
op_len = len(op)
length += op_len
if is_prefix:
text = text[op_len:].lstrip()
else:
text = text[:-op_len].rstrip()
return times, text
2016-05-18 09:43:43 -04:00
def top5():
data = read_data()
items = [(score, name) for name, score in data.items()]
2016-05-18 09:55:39 -04:00
items.sort(key=lambda item: item[0], reverse=True)
2016-05-18 09:43:43 -04:00
out = ''
for idx in range(5):
try:
item = items[idx]
out += '{}. _{}_ : {}\n'.format(idx+1, item[1], item[0])
except IndexError:
break
return out
def update_item(name, increment):
data = read_data()
score = data.get(name)
if not score:
score = 0
2016-05-19 11:59:33 -04:00
score += increment
2016-05-18 09:43:43 -04:00
data[name] = score
write_data(data)
return score
def erase_score(name):
data = read_data()
try:
del data[name]
except KeyError:
return False
else:
write_data(data)
return True
def read_data():
if not os.path.exists(HEARTS_FILE):
return {}
with open(HEARTS_FILE) as f:
return json.load(f)
return None
def write_data(obj):
with open(HEARTS_FILE, 'w') as f:
json.dump(obj, f, sort_keys=True, indent=4)
def has_prefix(text, prefixes):
for p in prefixes:
if text.startswith(p):
return p
return None
def has_suffix(text, suffixes):
for s in suffixes:
if text.endswith(s):
return s
return None