"""A retarded little bot program written in honor of a retarded little man.
This module implements BrtBot, which scans textual input from strings and
produces random responses from a YAML database file.
"""
__version__ = '1.02'
import os
import random
import re
import yaml
class BrtBot:
"""BrtBot main class."""
def __init__(self, filename='bedrocktruth'):
"""Constructor.
Arguments:
filename: str, identifies the file named 'brt-%s.yaml' containing quote
data in same directory as source file. Defaults to 'bedrocktruth'.
"""
quotes_file = open(os.path.split(__file__)[0] + 'brt-%s.yaml' % filename)
self.quotes = yaml.load(quotes_file)
quotes_file.close()
self.keywords = set()
self.quote_sets = {}
for quote, keywords in self.quotes['specific']:
for keyword in keywords:
# Add all keywords to the master keyword set
self.keywords.add(keyword)
# Generate mapping from keyword to quote
if keyword not in self.quote_sets:
self.quote_sets[keyword] = set()
self.quote_sets[keyword].add(quote)
def _scan(self, input):
"""Scan input for keywords from the quotes file.
Arguments:
input: str, contains search text
Returns:
Tuple of keywords found.
"""
keywords = []
for keyword in self.keywords:
if re.search(keyword, input, re.IGNORECASE):
keywords.append(keyword)
return tuple(keywords)
def _find_quotes(self, keywords):
""" Find quotes related to keywords.
Arguments:
keywords: iterable, gives keywords for which to search
Returns:
Tuple of found quotes.
"""
quotes = set()
# The union of all keyword sets can produce heavily discursive,
# non-sequitur responses.
#
# ...and that's a vital feature for any wingnut emulator
for keyword in keywords:
quotes = quotes.union(self.quote_sets[keyword])
return tuple(quotes)
def blather(self, input):
"""Crank out some good old-fashioned BRT blather.
Arguments:
input: str, contains search text
Returns:
One randomly selected quote relevant to keywords found in input, or one
randomly selected off-hand remark if no keywords match.
"""
keywords = self._scan(input)
# Produce a response relevant to keywords if possible
if keywords:
quotes = self._find_quotes(keywords)
# Use a stock answer if all else fails
else:
quotes = self.quotes['off-hand']
return quotes[random.randint(0, len(quotes) - 1)]