diff --git a/contrib_bots/lib/DefineBot/correct_word.png b/contrib_bots/lib/DefineBot/correct_word.png new file mode 100644 index 0000000..2b5ae1f Binary files /dev/null and b/contrib_bots/lib/DefineBot/correct_word.png differ diff --git a/contrib_bots/lib/DefineBot/docs.md b/contrib_bots/lib/DefineBot/docs.md new file mode 100644 index 0000000..c84e973 --- /dev/null +++ b/contrib_bots/lib/DefineBot/docs.md @@ -0,0 +1,21 @@ +# DefineBot + +* This is a bot that defines a word that the user inputs. Whenever the user +inputs a message starting with '@define', the bot defines the word +that follows. + +* The definitions are brought to the website using an API. The bot posts the +definition of the word to the stream from which the user inputs the message. +If the user inputs a word that does not exist or a word that is incorrect or +is not in the dictionary, the definition is not displayed. + +* For example, if the user says "@define crash", all the meanings of crash +appear, each in a separate line. + +![Correct Word](correct_word.png) + +* If the user enters a wrong word, like "@define cresh" or "@define crish", +then an error message saying no definition is available is displayed. + +![Wrong Word](wrong_word.png) + diff --git a/contrib_bots/lib/DefineBot/wrong_word.png b/contrib_bots/lib/DefineBot/wrong_word.png new file mode 100644 index 0000000..eca3301 Binary files /dev/null and b/contrib_bots/lib/DefineBot/wrong_word.png differ diff --git a/contrib_bots/lib/define_bot.py b/contrib_bots/lib/define_bot.py new file mode 100644 index 0000000..10bd3ee --- /dev/null +++ b/contrib_bots/lib/define_bot.py @@ -0,0 +1,85 @@ +# See readme.md for instructions on running this code. +import logging +import json +import requests +import html2text + +class DefineHandler(object): + ''' + This plugin define a word that the user inputs. It + looks for messages starting with '@define'. + ''' + + DEFINITION_API_URL = 'https://owlbot.info/api/v1/dictionary/{}?format=json' + REQUEST_ERROR_MESSAGE = 'Definition not available.' + EMPTY_WORD_REQUEST_ERROR_MESSAGE = 'Please enter a word to define.' + PHRASE_ERROR_MESSAGE = 'Definitions for phrases are not available.' + + def usage(DefineHandler): + return ''' + This plugin will allow users to define a word. Users should preface + messages with "@define". + ''' + + def triage_message(DefineHandler, message): + # return True if we want to (possibly) response to this message + original_content = message['content'] + # This next line of code is defensive, as we + # never want to get into an infinite loop of posting follow + # ups for own follow ups! + is_define = original_content.startswith('@define') + + return is_define + + def _handle_definition(DefineHandler, original_content): + # Remove '@define' from the message and extract the rest of the message, the + # word to define. + split_content = original_content.split(' ') + + # If there are more than one word (a phrase) + if len(split_content) > 2: + return DefineHandler.PHRASE_ERROR_MESSAGE + + to_define = split_content[1].strip() + to_define_lower = to_define.lower() + + # No word was entered. + if not to_define_lower: + return DefineHandler.EMPTY_WORD_REQUEST_ERROR_MESSAGE + else: + response = '**{}**:\n'.format(to_define) + + try: + # Use OwlBot API to fetch definition. + api_result = requests.get(DefineHandler.DEFINITION_API_URL.format(to_define_lower)) + # Convert API result from string to JSON format. + definitions = api_result.json() + + # Could not fetch definitions for the given word. + if not definitions: + response += DefineHandler.REQUEST_ERROR_MESSAGE + else: # Definitions available. + # Show definitions line by line. + for d in definitions: + example = d['example'] if d['example'] else '*No example available.*' + response += '\n' + '* (**{}**) {}\n  {}'.format(d['type'], d['defenition'], html2text.html2text(example)) + + except Exception as e: + response += DefineHandler.REQUEST_ERROR_MESSAGE + logging.exception(e) + + return response + + def handle_message(DefineHandler, message, client, state_handler): + original_content = message['content'] + + response = DefineHandler._handle_definition(original_content) + + client.send_message(dict( + type='stream', + to=message['display_recipient'], + subject=message['sender_email'], + content=response + )) + +handler_class = DefineHandler