Compare commits
No commits in common. "master" and "catalyst" have entirely different histories.
16 changed files with 345 additions and 26317 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -2,4 +2,3 @@
|
||||||
*.log
|
*.log
|
||||||
/*.db
|
/*.db
|
||||||
/*.conf
|
/*.conf
|
||||||
/env
|
|
||||||
|
|
|
||||||
31
README.md
31
README.md
|
|
@ -1,31 +0,0 @@
|
||||||
LolBot
|
|
||||||
======
|
|
||||||
|
|
||||||
A naff IRC bot I rattled off in a hurry once, for folks stuck behind censor
|
|
||||||
walls at work. Logs a channel and collects up all the URLs for later.
|
|
||||||
It was refactored for Twisted in 2011, then again to use pypi irc in 2015.
|
|
||||||
Has recently grown a quiz feature based on MoxQuizz, which might actually turn
|
|
||||||
into something useful one day.
|
|
||||||
|
|
||||||
Installation
|
|
||||||
------------
|
|
||||||
|
|
||||||
To get started, set up a Python virtual environment, and install the stuff in
|
|
||||||
`requirements.txt`.
|
|
||||||
|
|
||||||
apt-get install python-virtualenv
|
|
||||||
|
|
||||||
Clone this git repository, and in the directory:
|
|
||||||
|
|
||||||
virtualenv env
|
|
||||||
env/bin/pip install -r requirements.txt
|
|
||||||
|
|
||||||
Then you can run the bot like so:
|
|
||||||
|
|
||||||
env/bin/python lolbot.py --help
|
|
||||||
|
|
||||||
Development
|
|
||||||
-----------
|
|
||||||
|
|
||||||
Patches welcome! Development currently happens on the New Zealand Open Source
|
|
||||||
Society [GitLab](https://git.nzoss.org.nz/moxquizz-fans/lolbot).
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
irc.server = irc.freenode.net
|
irc.server = irc.wgtn.cat-it.co.nz
|
||||||
irc.channel = #lolbottest
|
irc.channel = #lolbottest
|
||||||
|
|
||||||
|
# defaults:
|
||||||
|
# irc.port = 6667
|
||||||
|
# irc.nickname = lolbot
|
||||||
|
|
||||||
# sqlite database filename
|
# sqlite database filename
|
||||||
db.file = lolbot.db
|
db.file = lolbot.db
|
||||||
|
|
||||||
|
|
|
||||||
694
lolbot.py
Normal file → Executable file
694
lolbot.py
Normal file → Executable file
|
|
@ -1,339 +1,253 @@
|
||||||
#! /usr/bin/env python
|
#!/usr/bin/env python
|
||||||
"""
|
#
|
||||||
LOLBOT 2
|
# LolBot
|
||||||
|
#
|
||||||
|
# New version based on Twisted IRC.
|
||||||
|
|
||||||
- die: Let the bot cease to exist.
|
"""
|
||||||
- ask: Ask a MoxQuizz question.
|
Useful bot for folks stuck behind censor walls at work
|
||||||
- list: list some URLs
|
Logs a channel and collects URLs for later.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import print_function, unicode_literals
|
try:
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import string
|
||||||
|
import re
|
||||||
|
import random
|
||||||
|
import time
|
||||||
|
import getopt
|
||||||
|
import sqlite3
|
||||||
|
from twisted.words.protocols import irc
|
||||||
|
from twisted.internet import protocol
|
||||||
|
from twisted.internet import reactor
|
||||||
|
from datetime import datetime
|
||||||
|
from mechanize import Browser
|
||||||
|
from sqlalchemy import MetaData, Table, Column, String, Text, Integer, DateTime, create_engine
|
||||||
|
from sqlalchemy.orm import sessionmaker
|
||||||
|
from sqlalchemy.ext.declarative import declarative_base
|
||||||
|
except ImportError:
|
||||||
|
print "Some modules missing: Lolbot relies on Twisted IRC, Mechanize and SQLAlchemy.\n"
|
||||||
|
sys.exit
|
||||||
|
|
||||||
import sys
|
SqlBase = declarative_base()
|
||||||
import os
|
|
||||||
import sqlite3
|
|
||||||
import random
|
|
||||||
import time
|
|
||||||
import getopt
|
|
||||||
import irc.strings
|
|
||||||
from irc.bot import SingleServerIRCBot
|
|
||||||
from sqlalchemy import create_engine
|
|
||||||
from sqlalchemy.orm import sessionmaker
|
|
||||||
from models import Log, Url, Model
|
|
||||||
from pymoxquizz import QuestionBank, Question
|
|
||||||
from os import listdir, path
|
|
||||||
|
|
||||||
|
class Log(SqlBase):
|
||||||
DEBUG = True
|
|
||||||
|
|
||||||
|
|
||||||
def debug(msg):
|
|
||||||
if DEBUG:
|
|
||||||
print(msg)
|
|
||||||
|
|
||||||
|
|
||||||
class LolBot(SingleServerIRCBot):
|
|
||||||
"""
|
"""
|
||||||
An IRC bot to entertain the troops with MoxQuizz questions, log URLs, and
|
This class represents an event in the log table and inherits from a SQLAlchemy
|
||||||
other shenanigans.
|
convenience ORM class.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
qb = list()
|
__tablename__ = "log"
|
||||||
|
|
||||||
def __init__(self, config=None):
|
id = Column(Integer, primary_key=True)
|
||||||
|
timestamp = Column(DateTime)
|
||||||
|
nickname = Column(String(20))
|
||||||
|
text = Column(Text)
|
||||||
|
|
||||||
|
def __init__(self, nickname, text, timestamp=None):
|
||||||
"""
|
"""
|
||||||
Constructor. Instantiates a lolbot with a configuration dictionary,
|
Creates an event log for the IRC logger.
|
||||||
or from command-line options if none is specified.
|
"""
|
||||||
|
if timestamp is None:
|
||||||
|
timestamp = datetime.now()
|
||||||
|
self.timestamp = timestamp
|
||||||
|
self.nickname = nickname
|
||||||
|
self.text = text
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "(%s) %s: %s" % (self.timestamp.strftime("%Y-%m-%d %H:%M:%S"), self.nickname, self.text)
|
||||||
|
|
||||||
|
class Url(SqlBase):
|
||||||
|
"""
|
||||||
|
This class represents a saved URL and inherits from a SQLAlchemy convenience
|
||||||
|
ORM class.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not config:
|
__tablename__ = "url"
|
||||||
config = LolBot.get_options()
|
|
||||||
|
|
||||||
if not self.validate_config(config):
|
id = Column(Integer, primary_key=True)
|
||||||
sys.exit(1)
|
timestamp = Column(DateTime)
|
||||||
|
nickname = Column(String(20))
|
||||||
|
url = Column(String(200), unique=True)
|
||||||
|
title = Column(Text)
|
||||||
|
|
||||||
self.config = config
|
def __init__(self, nickname, url, title=None, timestamp=None):
|
||||||
(server, port, channel, nickname, database) = (
|
if timestamp is None:
|
||||||
config['irc.server'],
|
timestamp = datetime.now()
|
||||||
config['irc.port'],
|
self.timestamp = timestamp
|
||||||
config['irc.channel'],
|
self.nickname = nickname
|
||||||
config['irc.nickname'],
|
self.url = url
|
||||||
config['db.file'])
|
self.title = title
|
||||||
|
|
||||||
debug("Instantiating SingleServerIRCBot")
|
# populate the title from the URL if not given.
|
||||||
irc.client.ServerConnection.buffer_class = irc.buffer.LenientDecodingLineBuffer
|
if title is None:
|
||||||
SingleServerIRCBot.__init__(self, [(server, port)], nickname, nickname)
|
try:
|
||||||
self.channel = channel
|
br = Browser()
|
||||||
|
br.open(self.url)
|
||||||
|
self.title = br.title()
|
||||||
|
except Exception as ex:
|
||||||
|
self.title = ''
|
||||||
|
|
||||||
# load some MoxQuizz questions
|
def __repr__(self):
|
||||||
qfiles = [f for f in listdir('questions') if path.isfile(path.join('questions', f))]
|
if not self.title:
|
||||||
debug("Loading MoxQuizz questions")
|
return "%s: %s" % (self.nickname, self.url)
|
||||||
for f in qfiles:
|
else:
|
||||||
qfile = path.abspath(path.join('questions', f))
|
return "%s: %s - %s" % (self.nickname, self.url, self.title)
|
||||||
debug(" - from MoxQuizz bank '%s'" % qfile)
|
|
||||||
self.qb += QuestionBank(qfile).questions
|
|
||||||
random.shuffle(self.qb)
|
|
||||||
self.quiz = 0
|
|
||||||
self.question = None
|
|
||||||
|
|
||||||
# connect to the database
|
class LolBot(irc.IRCClient):
|
||||||
debug("Connecting to SQLite database '%s'" % database)
|
"""
|
||||||
self.dbfile = database
|
The Lolbot itself.
|
||||||
self.dbengine = create_engine('sqlite+pysqlite://', creator=self._get_connection)
|
"""
|
||||||
Model.metadata.bind = self.dbengine
|
|
||||||
Model.metadata.create_all()
|
|
||||||
self.get_db = sessionmaker(bind=self.dbengine)
|
|
||||||
|
|
||||||
self.helptext = "Keeps a list of URLs. Commands: list [n|x-y] - prints the last 10 URLs (or n URLs, or x through y); <url> - adds the URL to the list; help - this message."
|
|
||||||
debug("Exiting lolbot constructor")
|
|
||||||
|
|
||||||
def _get_connection(self):
|
def _get_connection(self):
|
||||||
"""Creator function for SQLAlchemy."""
|
connection = sqlite3.Connection(self.config['db.file'])
|
||||||
connection = sqlite3.Connection(self.dbfile)
|
|
||||||
connection.text_factory = str
|
connection.text_factory = str
|
||||||
debug("Creating SQLAlchemy connection")
|
|
||||||
return connection
|
return connection
|
||||||
|
|
||||||
@property
|
def created(self, when):
|
||||||
def nickname(self):
|
# connect to the database
|
||||||
return self.connection.get_nickname()
|
self.dbengine = create_engine('sqlite+pysqlite://', creator=self._get_connection)
|
||||||
|
SqlBase.metadata.bind = self.dbengine
|
||||||
|
SqlBase.metadata.create_all()
|
||||||
|
self.get_session = sessionmaker(bind=self.dbengine)
|
||||||
|
|
||||||
def say_public(self, text):
|
self.helptext = "Keeps a list of URLs. Commands: list [n|x-y] - prints the last 10 URLs (or n URLs, or x through y); clear - clears the list; <url> - adds the URL to the list; help - this message."
|
||||||
"""
|
|
||||||
Say text in the public channel for all to see.
|
|
||||||
"""
|
|
||||||
self.connection.privmsg(self.channel, text)
|
|
||||||
self.log_event(self.nickname, text)
|
|
||||||
|
|
||||||
def say_private(self, nick, text):
|
def now(self):
|
||||||
"""
|
return datetime.today().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
Say text in a private message to nick.
|
|
||||||
"""
|
|
||||||
self.connection.privmsg(nick, text)
|
|
||||||
|
|
||||||
def reply(self, text, to_private=None):
|
|
||||||
"""
|
|
||||||
Say text in either public channel or a private message (if to_private
|
|
||||||
supplied).
|
|
||||||
"""
|
|
||||||
if to_private is not None:
|
|
||||||
self.say_private(to_private, text)
|
|
||||||
else:
|
|
||||||
self.say_public(text)
|
|
||||||
|
|
||||||
def on_nicknameinuse(self, connection, event):
|
|
||||||
debug("Nick '%s' in use, trying '%s_'" % (self.nickname, self.nickname))
|
|
||||||
connection.nick(self.nickname + "_")
|
|
||||||
|
|
||||||
def on_welcome(self, connection, event):
|
|
||||||
debug("Joining channel '%s' as %s" % (self.channel, self.nickname))
|
|
||||||
connection.join(self.channel)
|
|
||||||
|
|
||||||
def on_privmsg(self, connection, event):
|
|
||||||
"""
|
|
||||||
Handle a /msg from a user.
|
|
||||||
Handle commands addressed to the bot.
|
|
||||||
"""
|
|
||||||
message = event.arguments[0]
|
|
||||||
self.do_command(event, message)
|
|
||||||
|
|
||||||
def on_pubmsg(self, connection, event):
|
|
||||||
"""
|
|
||||||
Handle an event on the channel.
|
|
||||||
Handle commands addressed to the bot.
|
|
||||||
If there's a question, see if it's been answered.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Handle bot commands if addressed by nick or using ! shortcut.
|
|
||||||
try:
|
|
||||||
(nick, message) = event.arguments[0].split(": ", 1)
|
|
||||||
if irc.strings.lower(nick) == irc.strings.lower(self.connection.get_nickname()):
|
|
||||||
self.do_command(event, message.strip())
|
|
||||||
except ValueError:
|
|
||||||
message = event.arguments[0]
|
|
||||||
nick = event.source.nick
|
|
||||||
if message.startswith('!'):
|
|
||||||
self.do_command(event, message.lstrip('!'))
|
|
||||||
|
|
||||||
# Log it.
|
|
||||||
self.log_event(nick, message)
|
|
||||||
|
|
||||||
# Deal with MoxQuizz question.
|
|
||||||
if self.quiz:
|
|
||||||
self.handle_quiz(nick, message)
|
|
||||||
|
|
||||||
# Record URLs.
|
|
||||||
words = message.split(" ")
|
|
||||||
for w in words:
|
|
||||||
if w.startswith('http://') or w.startswith('https://'):
|
|
||||||
title = self.save_url(nick, w)
|
|
||||||
if title is False:
|
|
||||||
self.say_public("Failed to record URL, or no title found.")
|
|
||||||
else:
|
|
||||||
self.say_public("URL added. %s" % title)
|
|
||||||
|
|
||||||
def save_url(self, nickname, url):
|
def save_url(self, nickname, url):
|
||||||
title = False
|
title = False
|
||||||
try:
|
try:
|
||||||
db = self.get_db()
|
db = self.get_session()
|
||||||
if not db.query(Url).filter(Url.url == url).count():
|
if not db.query(Url).filter(Url.url == url).count():
|
||||||
theurl = Url(nickname, url)
|
theurl = Url(nickname, url)
|
||||||
db.add(theurl)
|
db.add(theurl)
|
||||||
db.commit()
|
db.commit()
|
||||||
else:
|
else:
|
||||||
theurl = db.query(Url).filter(Url.url == url).one()
|
theurl = db.query(Url).filter(Url.url == url).one()
|
||||||
print(theurl)
|
print theurl
|
||||||
title = theurl.title
|
title = theurl.title
|
||||||
except Exception as ex:
|
except Exception, ex:
|
||||||
print("Exception caught saving URL: %s" % ex)
|
print "Exception caught saving URL: %s" % ex
|
||||||
return title
|
return title
|
||||||
|
|
||||||
def log_event(self, nick, text):
|
def log_event(self, nick, text):
|
||||||
try:
|
try:
|
||||||
entry = Log(nick, text)
|
entry = Log(nick, text)
|
||||||
db = self.get_db()
|
db = self.get_session()
|
||||||
db.add(entry)
|
db.add(entry)
|
||||||
db.commit()
|
db.commit()
|
||||||
print(entry)
|
print entry
|
||||||
except Exception as ex:
|
except Exception, ex:
|
||||||
print("Exception caught logging event: %s" % ex)
|
print "Exception caught logging event: %s" % ex
|
||||||
|
|
||||||
def start_quiz(self, nick):
|
def _get_nickname(self):
|
||||||
self.quiz = 0
|
return self.factory.nickname
|
||||||
self.quiz_scores = dict()
|
nickname = property(_get_nickname)
|
||||||
self.connection.notice(self.channel, 'Quiz begun by %s.' % nick)
|
|
||||||
self.quiz_get_next()
|
|
||||||
|
|
||||||
def stop_quiz(self):
|
def _get_channel(self):
|
||||||
self.quiz = 0
|
return self.factory.channel
|
||||||
self.quiz_scores = None
|
channel = property(_get_channel)
|
||||||
self.question = None
|
|
||||||
|
|
||||||
def quiz_get_next(self):
|
def _get_config(self):
|
||||||
self.quiz += 1
|
return self.factory.config
|
||||||
self.tip = 0
|
config = property(_get_config)
|
||||||
self.question = random.choice(self.qb)
|
|
||||||
print(self.question.question)
|
|
||||||
self.connection.notice(self.channel, "Question %s: %s" % (self.quiz, self.question.question))
|
|
||||||
|
|
||||||
def quiz_tip(self):
|
def signedOn(self):
|
||||||
if len(self.question.tip) > self.tip:
|
self.join(self.channel)
|
||||||
self.connection.notice(self.channel, "Tip: %s" % self.question.tip[self.tip])
|
print "Signed on as %s." % (self.nickname,)
|
||||||
self.tip += 1
|
|
||||||
|
def joined(self, channel):
|
||||||
|
print "Joined %s." % (channel,)
|
||||||
|
|
||||||
|
def privmsg(self, user, channel, msg):
|
||||||
|
user = user.split('!')[0]
|
||||||
|
if channel == self.nickname:
|
||||||
|
# Private /msg from a user
|
||||||
|
self.do_command(msg, user)
|
||||||
else:
|
else:
|
||||||
self.connection.notice(self.channel, "No more tips.")
|
# log it
|
||||||
|
self.log_event(user, msg)
|
||||||
|
|
||||||
def quiz_award_points(self, nick):
|
args = string.split(msg, ":", 1)
|
||||||
if nick not in self.quiz_scores.keys():
|
if len(args) > 1 and args[0] == self.nickname:
|
||||||
self.quiz_scores[nick] = 0
|
self.do_command(string.strip(args[1]))
|
||||||
self.quiz_scores[nick] += self.question.score
|
else:
|
||||||
|
# parse it for links, add URLs to the list
|
||||||
|
words = msg.split(" ")
|
||||||
|
for w in words:
|
||||||
|
|
||||||
score = "%s point" % self.quiz_scores[nick]
|
# URL
|
||||||
if self.quiz_scores[nick] != 1:
|
if w.startswith('http://') or w.startswith('https://'):
|
||||||
score += "s"
|
title = self.save_url(user, w)
|
||||||
|
if title != False:
|
||||||
|
self.say_public("URL added. %s" % title)
|
||||||
|
|
||||||
self.connection.notice(self.channel, 'Correct! The answer was %s.' % self.question.answer)
|
# Moodle tracker bugs
|
||||||
time.sleep(1)
|
elif w.startswith('MDL-'):
|
||||||
self.connection.notice(self.channel, '%s is on %s.' % (nick, score))
|
m = re.search('^MDL-([0-9]+)$', w)
|
||||||
|
if m:
|
||||||
|
trackerurl = 'https://tracker.moodle.org/browse/%s' % w
|
||||||
|
title = self.save_url(user, trackerurl)
|
||||||
|
if title != False:
|
||||||
|
self.say_public("%s - %s" % (trackerurl, title))
|
||||||
|
|
||||||
def quiz_check_win(self, nick):
|
# Work requests
|
||||||
if self.quiz_scores[nick] == 10:
|
elif w.startswith('WR'):
|
||||||
self.connection.notice(self.channel, '%s wins with 10 points!' % nick)
|
m = re.search('^WR#?([0-9]+)$', w)
|
||||||
self.quiz_scoreboard()
|
if m:
|
||||||
self.stop_quiz()
|
wrmsurl = 'https://wrms.catalyst.net.nz/%s' % m.groups()[0]
|
||||||
|
title = self.save_url(user, wrmsurl)
|
||||||
|
if title != False:
|
||||||
|
self.say_public("%s - %s" % (wrmsurl, title))
|
||||||
|
|
||||||
def quiz_scoreboard(self):
|
# Bugzilla
|
||||||
if not self.quiz:
|
elif w.startswith('BUG'):
|
||||||
self.connection.notice(self.channel, 'Quiz not running.')
|
m = re.search('^BUG#?([0-9]+)$', w)
|
||||||
return
|
if m:
|
||||||
|
wrmsurl = 'http://bugzilla.catalyst.net.nz/show_bug.cgi?id=%s' % m.groups()[0]
|
||||||
|
title = self.save_url(user, wrmsurl)
|
||||||
|
if title != False:
|
||||||
|
self.say_public("%s - %s" % (wrmsurl, title))
|
||||||
|
|
||||||
self.connection.notice(self.channel, 'Scoreboard:')
|
def say_public(self, text):
|
||||||
for nick in self.quiz_scores.keys():
|
"Print TEXT into public channel, for all to see."
|
||||||
score = "%s point" % self.quiz_scores[nick]
|
self.notice(self.channel, text)
|
||||||
if self.quiz_scores[nick] != 1:
|
self.log_event(self.nickname, text)
|
||||||
score += "s"
|
|
||||||
self.connection.notice(self.channel, '%s has %s.' % (nick, score))
|
|
||||||
if not len(self.quiz_scores):
|
|
||||||
self.connection.notice(self.channel, 'So far, nobody has got anything right.')
|
|
||||||
|
|
||||||
def handle_quiz(self, nick, message):
|
def say_private(self, nick, text):
|
||||||
# bail if there's no quiz or unanswered question.
|
"Send private message of TEXT to NICK."
|
||||||
if not self.quiz or not isinstance(self.question, Question):
|
self.notice(nick, text)
|
||||||
return
|
|
||||||
|
|
||||||
# see if anyone answered correctly.
|
def reply(self, text, to_private=None):
|
||||||
if self.question.attempt(message):
|
"Send TEXT to either public channel or TO_PRIVATE nick (if defined)."
|
||||||
self.quiz_award_points(nick)
|
if to_private is not None:
|
||||||
time.sleep(1)
|
self.say_private(to_private, text)
|
||||||
self.quiz_check_win(nick)
|
else:
|
||||||
|
self.say_public(text)
|
||||||
|
|
||||||
# if nobody has won, carry on
|
def do_command(self, cmd, target=None):
|
||||||
if self.quiz:
|
|
||||||
|
|
||||||
# scores every 10 questions.
|
|
||||||
if self.quiz % 10 == 0:
|
|
||||||
self.quiz_scoreboard()
|
|
||||||
|
|
||||||
time.sleep(1)
|
|
||||||
self.quiz_get_next()
|
|
||||||
|
|
||||||
def do_command(self, e, cmd):
|
|
||||||
"""
|
"""
|
||||||
Handle bot commands.
|
This is the function called whenever someone sends a public or
|
||||||
|
private message addressed to the bot. (e.g. "bot: blah").
|
||||||
"""
|
"""
|
||||||
nick = e.source.nick
|
|
||||||
c = self.connection
|
|
||||||
|
|
||||||
if cmd == "die":
|
|
||||||
self.die()
|
|
||||||
|
|
||||||
elif cmd == 'help':
|
|
||||||
c.notice(nick, self.helptext)
|
|
||||||
|
|
||||||
elif cmd == 'status':
|
|
||||||
c.notice(self.channel, "I know %s questions." % len(self.qb))
|
|
||||||
if self.quiz:
|
|
||||||
c.notice(self.channel, "I am currently running a quiz.")
|
|
||||||
self.quiz_scoreboard()
|
|
||||||
|
|
||||||
elif cmd == 'halt' or cmd == 'quit':
|
|
||||||
if self.quiz:
|
|
||||||
self.quiz_scoreboard()
|
|
||||||
self.stop_quiz()
|
|
||||||
c.notice(self.channel, "Quiz halted by %s. Use ask to start a new one." % nick)
|
|
||||||
else:
|
|
||||||
c.notice(self.channel, "No quiz running.")
|
|
||||||
|
|
||||||
elif cmd == 'scores':
|
|
||||||
if self.quiz:
|
|
||||||
self.quiz_scoreboard()
|
|
||||||
|
|
||||||
elif cmd == 'tip' or cmd == 'hint':
|
|
||||||
if self.quiz:
|
|
||||||
self.quiz_tip()
|
|
||||||
|
|
||||||
elif cmd == 'ask':
|
|
||||||
if self.quiz:
|
|
||||||
c.notice(self.channel, "Quiz is running. Use halt or quit to stop.")
|
|
||||||
c.notice(self.channel, self.question.question)
|
|
||||||
elif isinstance(self.question, Question):
|
|
||||||
c.notice(self.channel, "There is an unanswered question.")
|
|
||||||
c.notice(self.channel, self.question.question)
|
|
||||||
else:
|
|
||||||
self.start_quiz(nick)
|
|
||||||
|
|
||||||
elif cmd == 'revolt':
|
|
||||||
if isinstance(self.question, Question):
|
|
||||||
c.notice(self.channel, "Fine, the answer is: %s" % self.question.answer)
|
|
||||||
self.quiz_get_next()
|
|
||||||
|
|
||||||
elif cmd.startswith('urls') or cmd.startswith('list'):
|
|
||||||
db = self.get_db()
|
|
||||||
try:
|
try:
|
||||||
(listcmd, n) = cmd.split(" ", 1)
|
if cmd == 'help':
|
||||||
except ValueError:
|
self.reply(self.helptext, target)
|
||||||
n = '5'
|
|
||||||
|
|
||||||
|
elif cmd == 'urls' or cmd == 'list':
|
||||||
|
db = self.get_session()
|
||||||
|
for url in db.query(Url).order_by(Url.timestamp.desc())[:10]:
|
||||||
|
line = "%s %s" % (url.url, url.title)
|
||||||
|
self.reply(line, target)
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
elif cmd.startswith('urls ') or cmd.startswith('list '):
|
||||||
|
db = self.get_session()
|
||||||
|
(listcmd, n) = cmd.split(" ", 1)
|
||||||
n = n.strip()
|
n = n.strip()
|
||||||
if n == "all":
|
if n == "all":
|
||||||
rows = db.query(Url).order_by(Url.timestamp.desc())
|
rows = db.query(Url).order_by(Url.timestamp.desc())
|
||||||
|
|
@ -344,118 +258,91 @@ class LolBot(SingleServerIRCBot):
|
||||||
y = abs(int(y))
|
y = abs(int(y))
|
||||||
if y < x:
|
if y < x:
|
||||||
x, y = y, x
|
x, y = y, x
|
||||||
except ValueError as ex:
|
except ValueError, ex:
|
||||||
c.notice(nick, "Give me a number or a range of numbers, e.g. list 5 or list 11-20")
|
self.reply("Give me a number or a range of numbers, e.g. list 5 or list 11-20", target)
|
||||||
raise ex
|
raise ex
|
||||||
rows = db.query(Url).order_by(Url.timestamp.desc())[x - 1: y]
|
rows = db.query(Url).order_by(Url.timestamp.desc())[x-1:y]
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
n = abs(int(n))
|
n = abs(int(n))
|
||||||
except ValueError as ex:
|
except ValueError, ex:
|
||||||
c.notice(nick, "Give me a number or a range of numbers, e.g. list 5 or list 11-20")
|
self.reply("Give me a number or a range of numbers, e.g. list 5 or list 11-20", target)
|
||||||
raise ex
|
raise ex
|
||||||
rows = db.query(Url).order_by(Url.timestamp.desc())[:n]
|
rows = db.query(Url).order_by(Url.timestamp.desc())[:n]
|
||||||
|
|
||||||
for url in rows:
|
for url in rows:
|
||||||
line = "%s %s" % (url.url, url.title)
|
line = "%s %s" % (url.url, url.title)
|
||||||
c.notice(nick, line)
|
self.reply(line, target)
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
|
elif cmd.startswith('http:') or cmd.startswith('https:'):
|
||||||
|
title = self.save_url(from_private, cmd)
|
||||||
|
if title == False:
|
||||||
|
self.say_public("Sorry, I'm useless at UTF-8.")
|
||||||
else:
|
else:
|
||||||
c.notice(nick, "Not understood: " + cmd)
|
self.reply('URL added. %s' % title, target)
|
||||||
|
|
||||||
def validate_config(self, config):
|
else:
|
||||||
"""
|
self.reply("I'm a bot of little brain. Try help for more information.", target)
|
||||||
Basic checks for configuration parameters. Returns a Boolean indicating
|
|
||||||
success or failure.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# validate IRC host
|
except Exception, ex:
|
||||||
if 'irc.server' not in config.keys():
|
print "Exception caught processing command: %s" % ex
|
||||||
print("Error: the IRC server was not specified. Use --help for more information.")
|
print " command was '%s' from %s" % (cmd, target)
|
||||||
return False
|
self.reply("Sorry, I didn't understand: %s" % cmd, target)
|
||||||
|
self.reply(self.helptext, target)
|
||||||
|
|
||||||
# validate IRC port
|
class LolBotFactory(protocol.ClientFactory):
|
||||||
if 'irc.port' not in config.keys():
|
protocol = LolBot
|
||||||
config['irc.port'] = '6667'
|
|
||||||
|
def __init__(self, config_path):
|
||||||
|
self.config = get_config(config_path)
|
||||||
|
self.server = self.config['irc.server']
|
||||||
|
self.port = self.config['irc.port']
|
||||||
|
self.nickname = self.config['irc.nickname']
|
||||||
|
self.channel = self.config['irc.channel']
|
||||||
|
|
||||||
|
def clientConnectionLost(self, connector, reason):
|
||||||
|
print "Lost connection (%s), reconnecting." % (reason,)
|
||||||
|
connector.connect()
|
||||||
|
|
||||||
|
def clientConnectionFailed(self, connector, reason):
|
||||||
|
print "Could not connect: %s" % (reason,)
|
||||||
|
|
||||||
|
def get_options():
|
||||||
try:
|
try:
|
||||||
config['irc.port'] = int(config['irc.port'])
|
(options, args) = getopt.getopt(sys.argv[1:], "hc:", ["help", "config=", ])
|
||||||
except ValueError:
|
except getopt.GetoptError, err:
|
||||||
print("Error: the IRC port must be an integer. If not specified, lolbot will use the default IRC port value 6667. Use --help for more information.")
|
print str(err)
|
||||||
return False
|
usage()
|
||||||
|
|
||||||
# validate IRC channel
|
|
||||||
if 'irc.channel' not in config.keys() or not config['irc.channel'].startswith('#'):
|
|
||||||
print("Error: the IRC channel is not specified or incorrect. It must begin with a # - e.g. #mychatchannel. Use --help for more information.")
|
|
||||||
return False
|
|
||||||
|
|
||||||
# validate bot nickname
|
|
||||||
if 'irc.nickname' not in config.keys():
|
|
||||||
config['irc.nickname'] = 'lolbot'
|
|
||||||
|
|
||||||
# validate bot nickname
|
|
||||||
if 'db.file' not in config.keys():
|
|
||||||
config['db.file'] = 'lolbot.db'
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_options():
|
|
||||||
"""
|
|
||||||
Set up configuration from the script arguments.
|
|
||||||
"""
|
|
||||||
|
|
||||||
try:
|
|
||||||
(options, args) = getopt.getopt(sys.argv[1:], 'hc:s:p:j:n:d:', ['help', 'config=', 'server=', 'port=', 'join=', 'nick=', 'database=', ])
|
|
||||||
except getopt.GetoptError as err:
|
|
||||||
print(err)
|
|
||||||
LolBot.usage()
|
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
|
|
||||||
config = {}
|
config_path = ""
|
||||||
for option, value in options:
|
for option,value in options:
|
||||||
# Display help text.
|
if option in ("-h", "--help"):
|
||||||
if option in ('-h', '--help'):
|
usage()
|
||||||
LolBot.usage()
|
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
|
if option in ("-c", "--config"):
|
||||||
|
config_path = value
|
||||||
|
return { 'config_path': config_path }
|
||||||
|
|
||||||
# Get configuration from a file.
|
def get_config(config_path):
|
||||||
if option in ('-c', '--config'):
|
|
||||||
config = LolBot.load_config(value)
|
|
||||||
break
|
|
||||||
|
|
||||||
# Individually specified settings.
|
|
||||||
if option in ('-s', '--server'):
|
|
||||||
config['irc.server'] = value
|
|
||||||
if option in ('-p', '--port'):
|
|
||||||
config['irc.port'] = value
|
|
||||||
if option in ('-j', '--join', '--channel', '--join-channel'):
|
|
||||||
config['irc.channel'] = value
|
|
||||||
if option in ('-n', '--nickname'):
|
|
||||||
config['irc.nickname'] = value
|
|
||||||
if option in ('-d', '--database'):
|
|
||||||
config['db.file'] = value
|
|
||||||
|
|
||||||
return config
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def load_config(config_path=''):
|
|
||||||
"""
|
"""
|
||||||
This method loads configuration options from a lolbot.conf file. The file
|
This method loads configuration options from a lolbot.conf file. The file
|
||||||
should look something like this::
|
should look like this:
|
||||||
|
|
||||||
irc.server = irc.yourdomain.com
|
irc.server = irc.freenode.net
|
||||||
irc.port = 6667
|
irc.port = 6667
|
||||||
irc.channel = #lolbottest
|
irc.channel = #lolbottest
|
||||||
irc.nickname = lolbot
|
irc.nickname = lolbot
|
||||||
db.file = lolbot.db
|
db.url = sqlite:///lolbot.db
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if config_path == '':
|
if not config_path:
|
||||||
config_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'lolbot.conf')
|
config_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "lolbot.conf")
|
||||||
if not os.path.exists(config_path):
|
if not os.path.exists(config_path):
|
||||||
print("Error: configuration file not found. By default lolbot will look for a lolbot.conf file in the same directory as the lolbot script, but you can override this by specifying a path on the command line with the --config option.")
|
print "Error: configuration file not found. By default lolbot will look for a lolbot.conf file in the same directory as the lolbot script, but you can override this by specifying a path on the command line with the --config option."
|
||||||
LolBot.usage()
|
usage()
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# open the configuration file and grab all param=value declarations.
|
# open the configuration file and grab all param=value declarations.
|
||||||
|
|
@ -463,64 +350,79 @@ class LolBot(SingleServerIRCBot):
|
||||||
with open(config_path) as f:
|
with open(config_path) as f:
|
||||||
for line in f:
|
for line in f:
|
||||||
# skip comments
|
# skip comments
|
||||||
if line.strip().startswith('#') or line.strip() == '':
|
if line.strip().startswith("#") or line.strip() == "":
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# collect up param = value
|
# collect up param = value
|
||||||
try:
|
try:
|
||||||
(param, value) = line.strip().split('=', 1)
|
(param, value) = line.strip().split("=", 1)
|
||||||
if param.strip() != '':
|
if param.strip() != "":
|
||||||
config[param.strip()] = value.strip()
|
config[param.strip()] = value.strip()
|
||||||
except ValueError:
|
except ValueError:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# validate IRC host
|
||||||
|
if "irc.server" not in config.keys():
|
||||||
|
print "Error: the IRC server was not specified. Use --help for more information."
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# validate IRC port
|
||||||
|
if "irc.port" not in config.keys():
|
||||||
|
config["irc.port"] = "6667"
|
||||||
|
try:
|
||||||
|
config["irc.port"] = int(config["irc.port"])
|
||||||
|
except ValueError:
|
||||||
|
print "Error: the IRC port must be an integer. If not specified, lolbot will use the default IRC port value 6667. Use --help for more information."
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# validate IRC channel
|
||||||
|
if "irc.channel" not in config.keys() or not config["irc.channel"].startswith("#"):
|
||||||
|
print "Error: the IRC channel is not specified or incorrect. It must begin with a # - e.g. #mychatchannel. Use --help for more information."
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# validate bot nickname
|
||||||
|
if "irc.nickname" not in config.keys():
|
||||||
|
config["irc.nickname"] = "lolbot"
|
||||||
|
|
||||||
return config
|
return config
|
||||||
|
|
||||||
@staticmethod
|
def usage():
|
||||||
def usage():
|
print """Run a lolbot.
|
||||||
"""
|
|
||||||
Spits out CLI help.
|
|
||||||
"""
|
|
||||||
|
|
||||||
print("""Run a lolbot.
|
|
||||||
|
|
||||||
-h, --help
|
-h, --help
|
||||||
This message.
|
This message.
|
||||||
|
|
||||||
-s, --server=<hostname>
|
-c, --config=<filename>
|
||||||
The IRC server, e.g. irc.freenode.net
|
Specify a configuration file. Defaults to lolbot.conf in the same
|
||||||
|
|
||||||
-p, --port=<port>
|
|
||||||
The IRC server port. Default: 6667
|
|
||||||
|
|
||||||
-j, --join=<channel>
|
|
||||||
The chat channel to join, e.g. #trainspotting
|
|
||||||
|
|
||||||
-n, --nickname=<nickname>
|
|
||||||
The nickname for your lolbot. Default: "lolbot"
|
|
||||||
|
|
||||||
-d, --database=<path>
|
|
||||||
The path to a SQLite lolbot database. If not specified, lolbot will
|
|
||||||
attempt to use a SQLite database called lolbot.db in the same
|
|
||||||
directory as the script.
|
directory as the script.
|
||||||
|
|
||||||
Configuration file:
|
Configuration:
|
||||||
|
|
||||||
-c, --config=<filename>
|
|
||||||
Specify a configuration file. Ignores any options specified from the
|
|
||||||
command-line. Defaults to lolbot.conf in the same directory as the
|
|
||||||
script. File layout:
|
|
||||||
|
|
||||||
irc.server = <host>
|
irc.server = <host>
|
||||||
irc.port = <port>
|
The IRC server, e.g. irc.freenode.net
|
||||||
irc.channel = <channel>
|
|
||||||
irc.nickname = <nickname>
|
|
||||||
db.file = <path>
|
|
||||||
""".strip())
|
|
||||||
|
|
||||||
|
irc.port = <port>
|
||||||
|
The IRC server port. Default: 6667
|
||||||
|
|
||||||
|
irc.channel = <channel>
|
||||||
|
The chat channel to join, e.g. #trainspotting
|
||||||
|
|
||||||
|
irc.nickname = <nickname>
|
||||||
|
The nickname for your lolbot. Default: "lolbot"
|
||||||
|
|
||||||
|
db.url = <url>
|
||||||
|
The URL to your lolbot database. This can be any valid URL accepted
|
||||||
|
by SQL Alchemy. If not specified, lolbot will attempt to use a
|
||||||
|
SQLite database called lolbot.db in the same directory as the
|
||||||
|
script.
|
||||||
|
"""
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
args = get_options()
|
||||||
|
config = get_config(args['config_path'])
|
||||||
try:
|
try:
|
||||||
LolBot().start()
|
reactor.connectTCP(config['irc.server'], config['irc.port'], LolBotFactory(args['config_path']))
|
||||||
|
reactor.run()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
pass
|
print "Shutting down."
|
||||||
|
|
||||||
|
|
|
||||||
83
models.py
83
models.py
|
|
@ -1,83 +0,0 @@
|
||||||
#! /usr/bin/env python
|
|
||||||
"""
|
|
||||||
Database models for lolbot.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import print_function, unicode_literals
|
|
||||||
|
|
||||||
import requests
|
|
||||||
from datetime import datetime
|
|
||||||
from bs4 import BeautifulSoup
|
|
||||||
from sqlalchemy import (Column, String, Text, Integer, DateTime)
|
|
||||||
from sqlalchemy.ext.declarative import (declarative_base)
|
|
||||||
|
|
||||||
|
|
||||||
Model = declarative_base()
|
|
||||||
|
|
||||||
|
|
||||||
class Log(Model):
|
|
||||||
"""
|
|
||||||
This class represents an event in the log table and inherits from a SQLAlchemy
|
|
||||||
convenience ORM class.
|
|
||||||
"""
|
|
||||||
|
|
||||||
__tablename__ = "log"
|
|
||||||
|
|
||||||
id = Column(Integer, primary_key=True)
|
|
||||||
timestamp = Column(DateTime)
|
|
||||||
nickname = Column(String(20))
|
|
||||||
text = Column(Text)
|
|
||||||
|
|
||||||
def __init__(self, nickname, text, timestamp=None):
|
|
||||||
"""
|
|
||||||
Creates an event log for the IRC logger.
|
|
||||||
"""
|
|
||||||
if timestamp is None:
|
|
||||||
timestamp = datetime.now()
|
|
||||||
self.timestamp = timestamp
|
|
||||||
self.nickname = nickname
|
|
||||||
self.text = text
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return "(%s) %s: %s" % (self.timestamp.strftime("%Y-%m-%d %H:%M:%S"), self.nickname, self.text)
|
|
||||||
|
|
||||||
|
|
||||||
class Url(Model):
|
|
||||||
"""
|
|
||||||
This class represents a saved URL and inherits from a SQLAlchemy convenience
|
|
||||||
ORM class.
|
|
||||||
"""
|
|
||||||
|
|
||||||
__tablename__ = "url"
|
|
||||||
|
|
||||||
id = Column(Integer, primary_key=True)
|
|
||||||
timestamp = Column(DateTime)
|
|
||||||
nickname = Column(String(20))
|
|
||||||
url = Column(String(200), unique=True)
|
|
||||||
title = Column(Text)
|
|
||||||
|
|
||||||
def __init__(self, nickname, url, title=None, timestamp=None):
|
|
||||||
if timestamp is None:
|
|
||||||
timestamp = datetime.now()
|
|
||||||
self.timestamp = timestamp
|
|
||||||
self.nickname = nickname
|
|
||||||
self.url = url
|
|
||||||
self.title = title
|
|
||||||
|
|
||||||
# populate the title from the URL if not given.
|
|
||||||
if title is None:
|
|
||||||
r = requests.get(url)
|
|
||||||
if r.status_code == 200:
|
|
||||||
if 'text/html' in r.headers['content-type']:
|
|
||||||
dom = BeautifulSoup(r.content, 'html.parser')
|
|
||||||
self.title = dom.title.string
|
|
||||||
else:
|
|
||||||
self.title = r.headers['content-type']
|
|
||||||
else:
|
|
||||||
self.title = "Error: HTTP %s" % r.status_code
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
if not self.title:
|
|
||||||
return "%s: %s" % (self.nickname, self.url)
|
|
||||||
else:
|
|
||||||
return "%s: %s - %s" % (self.nickname, self.url, self.title)
|
|
||||||
300
pymoxquizz.py
300
pymoxquizz.py
|
|
@ -1,300 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
## -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
A MozQuizz question library for Python.
|
|
||||||
See http://moxquizz.de/ for the original implementation in TCL.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import unicode_literals, print_function
|
|
||||||
from io import open
|
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
|
|
||||||
|
|
||||||
class Question:
|
|
||||||
"""
|
|
||||||
Represents one MoxQuizz question.
|
|
||||||
"""
|
|
||||||
|
|
||||||
category = None
|
|
||||||
"""
|
|
||||||
The question category. Arbitrary text; optional.
|
|
||||||
"""
|
|
||||||
|
|
||||||
question = None
|
|
||||||
"""
|
|
||||||
The question. Arbitrary text; required.
|
|
||||||
"""
|
|
||||||
|
|
||||||
answer = None
|
|
||||||
"""
|
|
||||||
The answer. Arbitrary text; required. Correct answers can also be covered
|
|
||||||
by the :attr:`regexp` property.
|
|
||||||
"""
|
|
||||||
|
|
||||||
regexp = None
|
|
||||||
"""
|
|
||||||
A regular expression that will generate correct answers. Optional. See
|
|
||||||
also the :attr:`answer` property.
|
|
||||||
"""
|
|
||||||
|
|
||||||
author = None
|
|
||||||
"""
|
|
||||||
The question author. Arbitrary text; optional.
|
|
||||||
"""
|
|
||||||
|
|
||||||
level = None # Default: NORMAL (constructor)
|
|
||||||
"""
|
|
||||||
The difficulty level. Value must be from the :attr:`LEVELS` tuple.
|
|
||||||
The default value is :attr:`NORMAL`.
|
|
||||||
"""
|
|
||||||
|
|
||||||
comment = None
|
|
||||||
"""
|
|
||||||
A comment. Arbitrary text; optional.
|
|
||||||
"""
|
|
||||||
|
|
||||||
score = 1
|
|
||||||
"""
|
|
||||||
The points scored for the correct answer. Integer value; default is 1.
|
|
||||||
"""
|
|
||||||
tip = list()
|
|
||||||
"""
|
|
||||||
An ordered list of tips (hints) to display to users. Optional.
|
|
||||||
"""
|
|
||||||
|
|
||||||
tipcycle = 0
|
|
||||||
"""
|
|
||||||
Indicates which tip is to be displayed next, if any.
|
|
||||||
"""
|
|
||||||
|
|
||||||
TRIVIAL = 1
|
|
||||||
"""
|
|
||||||
A value for :attr:`level` that indicates a question of trivial difficulty.
|
|
||||||
"""
|
|
||||||
|
|
||||||
EASY = 2
|
|
||||||
"""
|
|
||||||
A value for :attr:`level` that indicates a question of easy difficulty.
|
|
||||||
"""
|
|
||||||
|
|
||||||
NORMAL = 3
|
|
||||||
"""
|
|
||||||
A value for :attr:`level` that indicates a question of average or normal
|
|
||||||
difficulty.
|
|
||||||
"""
|
|
||||||
|
|
||||||
HARD = 4
|
|
||||||
"""
|
|
||||||
A value for :attr:`level` that indicates a question of hard difficulty.
|
|
||||||
"""
|
|
||||||
|
|
||||||
EXTREME = 5
|
|
||||||
"""
|
|
||||||
A value for :attr:`level` that indicates a question of extreme difficulty
|
|
||||||
or obscurity.
|
|
||||||
"""
|
|
||||||
|
|
||||||
LEVELS = (TRIVIAL, EASY, NORMAL, HARD, EXTREME)
|
|
||||||
"""
|
|
||||||
The available :attr:`level` difficulty values, :attr:`TRIVIAL`, :attr:`EASY`,
|
|
||||||
:attr:`NORMAL`, :attr:`HARD` and :attr:`EXTREME`.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, attributes_dict):
|
|
||||||
"""
|
|
||||||
Constructor that takes a dictionary of MoxQuizz key-value pairs. Usually
|
|
||||||
called from a :class:`QuestionBank`.
|
|
||||||
"""
|
|
||||||
# Set defaults first.
|
|
||||||
self.level = self.NORMAL
|
|
||||||
self.parse(attributes_dict)
|
|
||||||
|
|
||||||
def parse(self, attributes_dict):
|
|
||||||
"""
|
|
||||||
Populate fields from a dictionary of attributes, usually provided by a
|
|
||||||
:class:`QuestionBank` :attr:`~QuestionBank.parse` call.
|
|
||||||
"""
|
|
||||||
|
|
||||||
## Valid keys:
|
|
||||||
# ----------
|
|
||||||
# Category? (should always be on top!)
|
|
||||||
# Question (should always stand after Category)
|
|
||||||
# Answer (will be matched if no regexp is provided)
|
|
||||||
# Regexp? (use UNIX-style expressions)
|
|
||||||
# Author? (the brain behind this question)
|
|
||||||
# Level? [baby|easy|normal|hard|extreme] (difficulty)
|
|
||||||
# Comment? (comment line)
|
|
||||||
# Score? [#] (credits for answering this question)
|
|
||||||
# Tip* (provide one or more hints)
|
|
||||||
# TipCycle? [#] (Specify number of generated tips)
|
|
||||||
|
|
||||||
if 'Question' in attributes_dict.keys():
|
|
||||||
self.question = attributes_dict['Question']
|
|
||||||
else:
|
|
||||||
raise Exception("Cannot instantiate Question: 'Question' attribute required.")
|
|
||||||
|
|
||||||
if 'Category' in attributes_dict.keys():
|
|
||||||
self.category = attributes_dict['Category']
|
|
||||||
|
|
||||||
if 'Answer' in attributes_dict.keys():
|
|
||||||
self.answer = attributes_dict['Answer']
|
|
||||||
else:
|
|
||||||
raise Exception("Cannot instantiate Question: 'Answer' attribute required.")
|
|
||||||
|
|
||||||
if 'Regexp' in attributes_dict.keys():
|
|
||||||
self.regexp = attributes_dict['Regexp']
|
|
||||||
|
|
||||||
if 'Author' in attributes_dict.keys():
|
|
||||||
self.category = attributes_dict['Author']
|
|
||||||
|
|
||||||
if 'Level' in attributes_dict.keys() and attributes_dict['Level'] in self.LEVELS:
|
|
||||||
self.level = attributes_dict['Level']
|
|
||||||
elif 'Level' in attributes_dict.keys() and attributes_dict['Level'] in QuestionBank.LEVEL_VALUES.keys():
|
|
||||||
self.level = QuestionBank.LEVEL_VALUES[attributes_dict['Level']]
|
|
||||||
|
|
||||||
if 'Comment' in attributes_dict.keys():
|
|
||||||
self.comment = attributes_dict['Comment']
|
|
||||||
|
|
||||||
if 'Score' in attributes_dict.keys():
|
|
||||||
self.score = attributes_dict['Score']
|
|
||||||
|
|
||||||
if 'Tip' in attributes_dict.keys():
|
|
||||||
self.tip = attributes_dict['Tip']
|
|
||||||
|
|
||||||
if 'Tipcycle' in attributes_dict.keys():
|
|
||||||
self.tipcycle = attributes_dict['Tipcycle']
|
|
||||||
|
|
||||||
def attempt(self, answer):
|
|
||||||
return (self.answer is not None and self.answer.lower() == answer.lower()) or (
|
|
||||||
self.regexp is not None and re.search(self.regexp, answer, re.IGNORECASE) is not None)
|
|
||||||
|
|
||||||
class QuestionBank:
|
|
||||||
"""
|
|
||||||
Represents a MoxQuizz question bank.
|
|
||||||
"""
|
|
||||||
|
|
||||||
filename = ''
|
|
||||||
"""
|
|
||||||
The path or filename of the question bank file.
|
|
||||||
"""
|
|
||||||
|
|
||||||
questions = list()
|
|
||||||
"""
|
|
||||||
A list of :class:`Question` objects, constituting the questions in the
|
|
||||||
question bank.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Case sensitive, to remain backwards-compatible with MoxQuizz.
|
|
||||||
KEYS = ('Answer',
|
|
||||||
'Author',
|
|
||||||
'Category',
|
|
||||||
'Comment',
|
|
||||||
'Level',
|
|
||||||
'Question',
|
|
||||||
'Regexp',
|
|
||||||
'Score',
|
|
||||||
'Tip',
|
|
||||||
'Tipcycle',
|
|
||||||
)
|
|
||||||
"""
|
|
||||||
The valid attributes available in a MoxQuizz question bank file.
|
|
||||||
"""
|
|
||||||
|
|
||||||
LEVEL_VALUES = {
|
|
||||||
'trivial': Question.TRIVIAL,
|
|
||||||
'baby': Question.TRIVIAL,
|
|
||||||
'easy': Question.EASY,
|
|
||||||
'normal': Question.NORMAL,
|
|
||||||
'hard': Question.HARD,
|
|
||||||
'difficult': Question.HARD,
|
|
||||||
'extreme': Question.EXTREME
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
Text labels for the :attr:`Question.level` difficulty values.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, filename):
|
|
||||||
"""
|
|
||||||
Constructor, takes a MozQuizz-formatted question bank filename.
|
|
||||||
"""
|
|
||||||
self.filename = filename
|
|
||||||
self.questions = self.parse(filename)
|
|
||||||
|
|
||||||
def parse(self, filename):
|
|
||||||
"""
|
|
||||||
Read a MoxQuizz-formatted question bank file. Returns a ``list`` of
|
|
||||||
:class:`Question` objects found in the file.
|
|
||||||
"""
|
|
||||||
questions = list()
|
|
||||||
|
|
||||||
with open(filename) as f:
|
|
||||||
key = ''
|
|
||||||
i = 0
|
|
||||||
|
|
||||||
# new question
|
|
||||||
q = dict()
|
|
||||||
q['Tip'] = list()
|
|
||||||
|
|
||||||
for line in f:
|
|
||||||
line = line.strip()
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
# Ignore comments.
|
|
||||||
if line.startswith('#'):
|
|
||||||
continue
|
|
||||||
|
|
||||||
# A blank line starts a new question.
|
|
||||||
if line == '':
|
|
||||||
# Store the previous question, if valid.
|
|
||||||
if 'Question' in q.keys() and 'Answer' in q.keys():
|
|
||||||
question = Question(q)
|
|
||||||
questions.append(question)
|
|
||||||
|
|
||||||
# Start a new question.
|
|
||||||
q = dict()
|
|
||||||
q['Tip'] = list()
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Fetch the next parameter.
|
|
||||||
try:
|
|
||||||
(key, value) = line.split(':', 1)
|
|
||||||
key = key.strip()
|
|
||||||
value = value.strip()
|
|
||||||
except ValueError:
|
|
||||||
print("Unexpected weirdness in MoxQuizz questionbank '%s', line %s." % (self.filename, i))
|
|
||||||
continue
|
|
||||||
# break # TODO: is it appropriate to bail on broken bank files?
|
|
||||||
|
|
||||||
# Ignore bad parameters.
|
|
||||||
if key not in self.KEYS:
|
|
||||||
print("Unexpected key '%s' in MoxQuizz questionbank '%s', line %s." % (key, self.filename, i))
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Enumerate the Tips.
|
|
||||||
if key == 'Tip':
|
|
||||||
q['Tip'].append(value.strip())
|
|
||||||
elif key == 'Level':
|
|
||||||
if value not in self.LEVEL_VALUES:
|
|
||||||
print("Unexpected Level value '%s' in MoxQuizz questionbank '%s', line '%s'." % (value, self.filename, i))
|
|
||||||
else:
|
|
||||||
q['Level'] = self.LEVEL_VALUES[value]
|
|
||||||
else:
|
|
||||||
q[key] = value.strip()
|
|
||||||
|
|
||||||
return questions
|
|
||||||
|
|
||||||
|
|
||||||
# A crappy test.
|
|
||||||
if __name__ == '__main__':
|
|
||||||
qb = QuestionBank('questions/questions.doctorlard.en')
|
|
||||||
for q in qb.questions:
|
|
||||||
print(q.question)
|
|
||||||
if sys.version.startswith('2'):
|
|
||||||
a = unicode(raw_input('A: '), 'utf8')
|
|
||||||
else:
|
|
||||||
a = input('A: ')
|
|
||||||
if q.attempt(a):
|
|
||||||
print("Correct!")
|
|
||||||
else:
|
|
||||||
print("Incorrect - the answer is '%s'" % q.answer)
|
|
||||||
|
|
@ -1,175 +0,0 @@
|
||||||
########################################################
|
|
||||||
# DoctorLard's collection of random Moxquizz questions
|
|
||||||
########################################################
|
|
||||||
|
|
||||||
## Demo-Entry:
|
|
||||||
# ----------
|
|
||||||
# Category: History
|
|
||||||
# Question: Chinese philosopher (um 500 v. Chr.) ?
|
|
||||||
# Answer: Konfuzius
|
|
||||||
# Regexp: [ck]onfu(ts|z)ius
|
|
||||||
# Author: anonymous
|
|
||||||
# Level: hard
|
|
||||||
# Comment: demo-entry, ÄÖÜäöüß ^° !"§$%&/()=? `Ž
|
|
||||||
# Score: 5
|
|
||||||
# Tip: Kon......
|
|
||||||
# Tip: ...fuz...
|
|
||||||
# Tip: ......ius
|
|
||||||
|
|
||||||
## valid keys:
|
|
||||||
# ----------
|
|
||||||
# Category? (should always be on top!)
|
|
||||||
# Question (should always stand after Category)
|
|
||||||
# Answer (will be matched if no regexp is provided)
|
|
||||||
# Regexp? (use UNIX-style expressions)
|
|
||||||
# Author? (the brain behind this question)
|
|
||||||
# Level? [baby|easy|normal|hard|extreme] (difficulty)
|
|
||||||
# Comment? (comment line)
|
|
||||||
# Score? [#] (credits for answering this question)
|
|
||||||
# Tip* (provide one or more hints)
|
|
||||||
# TipCycle? [#] (Specify number of generated tips)
|
|
||||||
|
|
||||||
## WARNING:
|
|
||||||
# -------
|
|
||||||
# DO NOT ADD COMMENTS BEYOND THIS LINE, since they might get lost.
|
|
||||||
# you may add as much comments as you want into the part above
|
|
||||||
|
|
||||||
Category: Units
|
|
||||||
Question: What does the SI unit weber (Wb) measure?
|
|
||||||
Tip: m....... f...
|
|
||||||
Answer: magnetic flux
|
|
||||||
Author: DoctorLard
|
|
||||||
|
|
||||||
Category: Units
|
|
||||||
Question: Four gills in a ....?
|
|
||||||
Tip: It's an Imperial unit.
|
|
||||||
Tip: You might ask for one at the pub.
|
|
||||||
Tip: p...
|
|
||||||
Answer: pint
|
|
||||||
Author: DoctorLard
|
|
||||||
|
|
||||||
Category: Units
|
|
||||||
Question: Ten chains in a ....?
|
|
||||||
Tip: It's an Imperial unit of length.
|
|
||||||
Tip: f......
|
|
||||||
Answer: furlong
|
|
||||||
Author: DoctorLard
|
|
||||||
|
|
||||||
Category: Units
|
|
||||||
Question: Four .... in a chain?
|
|
||||||
Tip: An obscure Imperial unit of length.
|
|
||||||
Tip: Equal to 5½ yards.
|
|
||||||
Tip: r..
|
|
||||||
RegExp: (rod|pole|perch)
|
|
||||||
Answer: Rod (or Pole, or Perch)
|
|
||||||
Author: DoctorLard
|
|
||||||
|
|
||||||
Category: Units
|
|
||||||
Question: Eight .... in a mile?
|
|
||||||
Tip: An Imperial unit of length.
|
|
||||||
Tip: Equal to 220 yards.
|
|
||||||
Tip: f......
|
|
||||||
Answer: Furlong
|
|
||||||
Author: DoctorLard
|
|
||||||
|
|
||||||
Category: Units
|
|
||||||
Question: A perch is unit of area equivalent to a square pole. A pole is another name for a rod, and there are ten chains to a furlong and four rods to a chain. A rood is a quarter acre, and there are 160 perches to an acre. If a property area is one rood and half a furlong on one side, how long is the other side, in rods?
|
|
||||||
Tip: Less than you might think.
|
|
||||||
Tip: Whatever. Google won't help you either.
|
|
||||||
Level: hard
|
|
||||||
Answer: 2
|
|
||||||
Author: DoctorLard
|
|
||||||
|
|
||||||
Question: How many pennies in a half crown?
|
|
||||||
Answer: 30
|
|
||||||
Author: DoctorLard
|
|
||||||
|
|
||||||
Category: Units
|
|
||||||
Question: What is the old English surveying unit of area, defined as one furlong by one rod?
|
|
||||||
Tip: There are four of them to an acre.
|
|
||||||
Tip: r...
|
|
||||||
Answer: rood
|
|
||||||
Author: DoctorLard
|
|
||||||
|
|
||||||
Category: Units
|
|
||||||
Question: What is the SI prefix that denotes a multiplier of ten to the negative eighteenth power (10¯¹⁸)?
|
|
||||||
Tip: It's used really really small quantities.
|
|
||||||
Tip: a...
|
|
||||||
Answer: atto
|
|
||||||
Author: DoctorLard
|
|
||||||
|
|
||||||
Category: Temporal anomalies
|
|
||||||
Question: How many times do the minute and hour hands on a clockface overlap in a 24 hour period?
|
|
||||||
Answer: 22
|
|
||||||
Author: DoctorLard
|
|
||||||
|
|
||||||
Category: xG
|
|
||||||
Question: Which country did hell- visit in August 2014?
|
|
||||||
Answer: USA
|
|
||||||
Author: DoctorLard
|
|
||||||
|
|
||||||
Category: Music
|
|
||||||
Question: A traditional Arabian and Turkish string instrument, distinguished from the lute by having no frets.
|
|
||||||
Answer: oud
|
|
||||||
Author: Bill Bailey
|
|
||||||
|
|
||||||
Category: Pharmacology
|
|
||||||
Question: In Breaking Bad, Walter and Jesse used a "P2P cook" process to make very pure methamphetamine (by reduction with methylamine over aluminium). What does P2P stand for?
|
|
||||||
Answer: phenyl-2-propanone
|
|
||||||
Author: DoctorLard
|
|
||||||
|
|
||||||
Category: General ignorance
|
|
||||||
Question: What are igloos normally made of?
|
|
||||||
Answer: animal skins
|
|
||||||
Regexp: (animal )?skins
|
|
||||||
Tip: It isn't snow.
|
|
||||||
Tip: It isn't any form of frozen water.
|
|
||||||
Author: DoctorLard
|
|
||||||
|
|
||||||
Category: New Zealand
|
|
||||||
Question: In what year did New Zealand become self-governing (by gaining its own representative government, separate from the United Kingdom)?
|
|
||||||
Answer: 1852
|
|
||||||
Author: DoctorLard
|
|
||||||
|
|
||||||
Category: Geography
|
|
||||||
Question: How many of the Commonwealth of Nations' member states are Realms?
|
|
||||||
Answer: 16
|
|
||||||
Level: hard
|
|
||||||
Author: DoctorLard
|
|
||||||
|
|
||||||
Category: Sculpture
|
|
||||||
Question: Which Lord of the Rings actor, in an interview with Jay Leno, admitted to urinating in Wellington's Bucket Fountain sculpture while filming in New Zealand?
|
|
||||||
Answer: Elijah Wood
|
|
||||||
Author: DoctorLard
|
|
||||||
|
|
||||||
Category: TV
|
|
||||||
Question: Which British comedy actor played Richmond in The IT Crowd, and Vincent Noir in The Mighty Boosh?
|
|
||||||
Answer: Noel Fielding
|
|
||||||
Author: DoctorLard
|
|
||||||
|
|
||||||
Category: Video Games
|
|
||||||
Question: Who composed the music for the Elder Scrolls and Guild Wars games, thinks he's God's gift to composers, and takes fucking ages to ship CDs of his soundtracks?
|
|
||||||
Answer: Jeremy Soule
|
|
||||||
Author: DoctorLard
|
|
||||||
|
|
||||||
Category: Video Games
|
|
||||||
Question: In the Guild Wars world of Tyria, name the once great human kingdom, laid waste by the Charr?
|
|
||||||
Answer: Ascalon
|
|
||||||
Author: DoctorLard
|
|
||||||
|
|
||||||
Category: Video Games
|
|
||||||
Question: In Mass Effect 2 and 3, which Oscar-nominated American actor provided the voice for The Illusive Man?
|
|
||||||
Answer: Martin Sheen
|
|
||||||
Author: DoctorLard
|
|
||||||
|
|
||||||
Category: Cuisine
|
|
||||||
Question: Which spice is made from the dried and ground aril that surrounds a nutmeg (Myristica fragrans) seed?
|
|
||||||
Answer: Mace
|
|
||||||
Author: DoctorLard
|
|
||||||
|
|
||||||
Category: Cuisine
|
|
||||||
Question: What is the main ingredient of borscht?
|
|
||||||
Answer: beetroot
|
|
||||||
Author: DoctorLard
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,182 +0,0 @@
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
#
|
|
||||||
# Author: Lee Clarke, 1st April 2002
|
|
||||||
# Editor:
|
|
||||||
# Last edited: 2002/07/05 19:09:11
|
|
||||||
#
|
|
||||||
# Comment: many mixed quiz questions, Authors nick removed on request
|
|
||||||
#
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
## Demo-Entry:
|
|
||||||
# ----------
|
|
||||||
# Category: History
|
|
||||||
# Question: Chinese philosopher (um 500 v. Chr.) ?
|
|
||||||
# Answer: Konfuzius
|
|
||||||
# Regexp: [ck]onfu(ts|z)ius
|
|
||||||
# Author: anonymous
|
|
||||||
# Level: hard
|
|
||||||
# Comment: demo-entry, ÄÖÜäöüß ^° !"§$%&/()=? `Ž
|
|
||||||
# Score: 5
|
|
||||||
# Tip: Kon......
|
|
||||||
# Tip: ...fuz...
|
|
||||||
# Tip: ......ius
|
|
||||||
|
|
||||||
## valid keys:
|
|
||||||
# ----------
|
|
||||||
# Category? (should always be on top!)
|
|
||||||
# Question (should always stand after Category)
|
|
||||||
# Answer (will be matched if no regexp is provided)
|
|
||||||
# Regexp? (use UNIX-style expressions)
|
|
||||||
# Author? (the brain behind this question)
|
|
||||||
# Level? [baby|easy|normal|hard|extreme] (difficulty)
|
|
||||||
# Comment? (comment line)
|
|
||||||
# Score? [#] (credits for answering this question)
|
|
||||||
# Tip* (provide one or more hints)
|
|
||||||
# TipCycle? [#] (Specify number of generated tips)
|
|
||||||
|
|
||||||
## WARNING:
|
|
||||||
# -------
|
|
||||||
# DO NOT ADD COMMENTS BEYOND THIS LINE, since they might get lost.
|
|
||||||
# you may add as much comments as you want into the part above
|
|
||||||
# <!========================================================!>
|
|
||||||
|
|
||||||
Category: Animals
|
|
||||||
Question: What is the only animal, other than a human that can catch leprosy?
|
|
||||||
Answer: The Armadillo
|
|
||||||
|
|
||||||
Category: Computer Games
|
|
||||||
Question: Which legendary games designer/producer created the Super Mario Brothers franchise for Nintendo?
|
|
||||||
Answer: Shigeru Miyamoto
|
|
||||||
|
|
||||||
Category: General
|
|
||||||
Question: Aesthetic principles derived from the literature and art of ancient Greece & Rome, but found as ideals in all ages is called?
|
|
||||||
Answer: Classicism
|
|
||||||
Author: DonkeyTron
|
|
||||||
|
|
||||||
Category: General
|
|
||||||
Question: North American Indian language family including languages of Alaska and north-western Canada, the Pacific coast and the south-western United States.
|
|
||||||
Answer: Athapascan
|
|
||||||
Author: DonkeyTron
|
|
||||||
|
|
||||||
Category: General
|
|
||||||
Question: What is the literal translation of the Latin word 'video'?
|
|
||||||
Answer: I See
|
|
||||||
Author: DonkeyTron
|
|
||||||
|
|
||||||
Category: General
|
|
||||||
Question: Which 1946 Louis Reard creation, was nicknamed "four triangles of nothing"?
|
|
||||||
Answer: The Bikini
|
|
||||||
Author: DonkeyTron
|
|
||||||
|
|
||||||
Category: General
|
|
||||||
Question: Who is the supreme head of the Church Of England?
|
|
||||||
Answer: Queen Elizabeth II
|
|
||||||
|
|
||||||
Category: General
|
|
||||||
Question: Whose picture was on the first adhesive nickel postage stamp in the US?
|
|
||||||
Answer: Benjamin Franklin
|
|
||||||
Author: DonkeyTron
|
|
||||||
|
|
||||||
Category: General
|
|
||||||
Question: One of the twelve members of the administrative council of the Mormon church, is called a(n) .......?
|
|
||||||
Answer: Apostle
|
|
||||||
Author: DonkeyTron
|
|
||||||
|
|
||||||
Category: General
|
|
||||||
Question: The process of adding a number to itself a certain number of times is called?
|
|
||||||
Answer: Multiplication
|
|
||||||
Author: DonkeyTron
|
|
||||||
|
|
||||||
Category: Literature
|
|
||||||
Question: Which novel by Mary Shelley was subtitled 'The Modern Prometheus'?
|
|
||||||
Answer: Frankenstein
|
|
||||||
Author: DonkeyTron
|
|
||||||
|
|
||||||
Category: Magazines
|
|
||||||
Question: Which magazine always features an obituary on its last page?
|
|
||||||
Answer: Rolling Stone
|
|
||||||
Author: DonkeyTron
|
|
||||||
|
|
||||||
Category: Magazines
|
|
||||||
Question: Who was the first male to appear on the cover of Playboy in 1964?
|
|
||||||
Answer: Peter Sellers
|
|
||||||
Author: DonkeyTron
|
|
||||||
|
|
||||||
Category: Movies
|
|
||||||
Question: In which movie did Bruce Willis play the role of Corben Dallas?
|
|
||||||
Answer: The Fifth Element
|
|
||||||
|
|
||||||
Category: Movies
|
|
||||||
Question: What does Steven Spielberg try to include in every film he makes, claiming it is for luck?
|
|
||||||
Answer: Scene With A Shooting Star
|
|
||||||
Author: DonkeyTron
|
|
||||||
|
|
||||||
Category: Movies
|
|
||||||
Question: Which actor played the role of Chewbacca in the Star Wars trilogy?
|
|
||||||
Answer: Peter Mayhew
|
|
||||||
Author: DonkeyTron
|
|
||||||
|
|
||||||
Category: Movies
|
|
||||||
Question: Which actress won the 2002 Academy Award for best actress in a leading role, for her part in the movie, 'Monster's Ball'?
|
|
||||||
Answer: Halle Berry
|
|
||||||
Author: DonkeyTron
|
|
||||||
|
|
||||||
Category: Music
|
|
||||||
Question: The theme tune for 'Monty Python's Flying Circus' was written by which composer?
|
|
||||||
Answer: John Philip Sousa
|
|
||||||
Author: DonkeyTron
|
|
||||||
|
|
||||||
Category: Music
|
|
||||||
Question: What was the working title for The Beatles' song, 'Yesterday'?
|
|
||||||
Answer: Scrambled Eggs
|
|
||||||
Author: DonkeyTron
|
|
||||||
|
|
||||||
Category: Music
|
|
||||||
Question: Which native of Flint, Michigan, once advised us to "drive your Chevrolet through the USA"?
|
|
||||||
Answer: Pat Boone
|
|
||||||
Author: DonkeyTron
|
|
||||||
|
|
||||||
Category: Quotes
|
|
||||||
Question: Which tennis player , when asked if he had learned anything from his US Open loss said, "Yeah...I learned I needed to lose 15 pounds"?
|
|
||||||
Answer: Andre Agassi
|
|
||||||
Author: DonkeyTron
|
|
||||||
|
|
||||||
Category: Quotes
|
|
||||||
Question: Who said, "People don't credit me with much of a brain, so why should I disillusion them."?
|
|
||||||
Answer: Sylvester Stallone
|
|
||||||
Author: DonkeyTron
|
|
||||||
|
|
||||||
Category: Soccer
|
|
||||||
Question: Which English Premier League team plays their home games at Elland Road?
|
|
||||||
Answer: Leeds United
|
|
||||||
Author: DonkeyTron
|
|
||||||
|
|
||||||
Category: Sports
|
|
||||||
Question: According to Olympic rules, what number of feathers must a badminton bird (shuttlecock) have?
|
|
||||||
Answer: Fourteen
|
|
||||||
Author: DonkeyTron
|
|
||||||
|
|
||||||
Category: Sports
|
|
||||||
Question: What is the name of the oldest National Hockey League team in the US?
|
|
||||||
Answer: The Boston Bruins
|
|
||||||
Author: DonkeyTron
|
|
||||||
|
|
||||||
Category: Star Trek
|
|
||||||
Question: What is Mr Spock's pulse rate?
|
|
||||||
Answer: 242 Beats Per Minute
|
|
||||||
Author: DonkeyTron
|
|
||||||
|
|
||||||
Category: TV
|
|
||||||
Question: What is the address of The Munsters?
|
|
||||||
Answer: 1313 Mockingbird Lane
|
|
||||||
Author: DonkeyTron
|
|
||||||
|
|
||||||
Category: The Simpsons
|
|
||||||
Question: Who has starred in such movies as 'The Erotic Adventures Of Hercules' & 'Dial M For Murderousness'?
|
|
||||||
Answer: Troy McClure
|
|
||||||
|
|
||||||
Category: Weights & Measures
|
|
||||||
Question: The liquid measure of a capacity equal to 1/8 of a fluid ounce is a(n) ..........?
|
|
||||||
Answer: Fluid Dram
|
|
||||||
Author: DonkeyTron
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,618 +0,0 @@
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
#
|
|
||||||
# Author: OllyPomm
|
|
||||||
# Editor: stanstime
|
|
||||||
# Last edited: 2002/07/05 19:09:10
|
|
||||||
#
|
|
||||||
# Comment: OllyPomm has submitted about 200 questions with more to come
|
|
||||||
#
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
## Demo-Entry:
|
|
||||||
# ----------
|
|
||||||
# Category: History
|
|
||||||
# Question: Chinese philosopher (um 500 v. Chr.) ?
|
|
||||||
# Answer: Konfuzius
|
|
||||||
# Regexp: [ck]onfu(ts|z)ius
|
|
||||||
# Author: anonymous
|
|
||||||
# Level: hard
|
|
||||||
# Comment: demo-entry, ÄÖÜäöüß ^° !"§$%&/()=? `Ž
|
|
||||||
# Score: 5
|
|
||||||
# Tip: Kon......
|
|
||||||
# Tip: ...fuz...
|
|
||||||
# Tip: ......ius
|
|
||||||
|
|
||||||
## valid keys:
|
|
||||||
# ----------
|
|
||||||
# Category? (should always be on top!)
|
|
||||||
# Question (should always stand after Category)
|
|
||||||
# Answer (will be matched if no regexp is provided)
|
|
||||||
# Regexp? (use UNIX-style expressions)
|
|
||||||
# Author? (the brain behind this question)
|
|
||||||
# Level? [baby|easy|normal|hard|extreme] (difficulty)
|
|
||||||
# Comment? (comment line)
|
|
||||||
# Score? [#] (credits for answering this question)
|
|
||||||
# Tip* (provide one or more hints)
|
|
||||||
# TipCycle? [#] (Specify number of generated tips)
|
|
||||||
|
|
||||||
## WARNING:
|
|
||||||
# -------
|
|
||||||
# DO NOT ADD COMMENTS BEYOND THIS LINE, since they might get lost.
|
|
||||||
# you may add as much comments as you want into the part above
|
|
||||||
# <!========================================================!>
|
|
||||||
|
|
||||||
Category: Animals
|
|
||||||
Question: An unusual feature of the wombats pouch is that it .......?
|
|
||||||
Answer: faces backwards
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Animals
|
|
||||||
Question: How many nipples does an echidna have?
|
|
||||||
Answer: None
|
|
||||||
Regexp: (None|0|Zero|Nill)
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Animals
|
|
||||||
Question: The thylacine (considered extinct) is more commonly know as the?
|
|
||||||
Answer: Tasmanian Tiger
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Animals
|
|
||||||
Question: What is a monotreme?
|
|
||||||
Answer: An egg laying mammal
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Morse Code
|
|
||||||
Question: What letter of the alphabet does 'dash dash' represent?
|
|
||||||
Answer: M
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Morse Code
|
|
||||||
Question: What letter of the alphabet does 'dash dot' represent?
|
|
||||||
Answer: N
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Morse Code
|
|
||||||
Question: What letter of the alphabet does 'dash dash dot' represent?
|
|
||||||
Answer: G
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Morse Code
|
|
||||||
Question: What letter of the alphabet does 'dash dash dot dot' represent?
|
|
||||||
Answer: Z
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Morse Code
|
|
||||||
Question: What letter of the alphabet does 'dot dot' represent?
|
|
||||||
Answer: I
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Sport
|
|
||||||
Question: The Melbourne Cup horse race is held on the first ------- in November.?
|
|
||||||
Answer: Tuesday
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Sport
|
|
||||||
Question: Over what distance is the Melbourne Cup horse race ran (in metres)?
|
|
||||||
Answer: 3200
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Pot Pourri
|
|
||||||
Question: How many weeks until Christmas Day if it is the 25th September?
|
|
||||||
Answer: 13 weeks
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Sport
|
|
||||||
Question: What famous race was established in 1903?
|
|
||||||
Answer: The Tour de France
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: History
|
|
||||||
Question: In 1893, this country was the first to give women the vote.?
|
|
||||||
Answer: New Zealand
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Metals
|
|
||||||
Question: The largest pure gold nugget (weighing 70.92kg) ever discovered was called...?
|
|
||||||
Answer: The Welcome Stranger
|
|
||||||
Regexp: (The )?Welcome Stranger
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Medicine
|
|
||||||
Question: In 1665 the first ----- ----------- was performed by Dr Richard Lower.?
|
|
||||||
Answer: Blood Transfusion
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Pot Pourri
|
|
||||||
Question: If it's 12.00 noon GMT - what time is it in Sydney, Australia?
|
|
||||||
Answer: 10.00pm
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: History
|
|
||||||
Question: Considered to be the last full blooded Tasmanian aborigine, (died 1876 - aged 73), her name is.....?
|
|
||||||
Answer: Truganini
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Olympics
|
|
||||||
Question: In what city is the Olympic torch first lit?
|
|
||||||
Answer: Olympia
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Olympics
|
|
||||||
Question: What is the latin Olympic motto?
|
|
||||||
Answer: Citius Altius Fortius
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Olympics
|
|
||||||
Question: What does the latin Olympic motto - Citius Altius Fortius stand for?
|
|
||||||
Answer: Faster Higher Stronger
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Olympics
|
|
||||||
Question: What are the colours of the Olympics rings (in order).?
|
|
||||||
Answer: Blue Yellow Black Green Red
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Olympics
|
|
||||||
Question: How many mascots did the Sydney Olympics have?
|
|
||||||
Answer: 3
|
|
||||||
Regexp: (3|Three)
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Olympics
|
|
||||||
Question: The Sydney Olympics had 3 mascots. What type of animals were they?
|
|
||||||
Answer: Kookaburra Echidna Platypus
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Olympics
|
|
||||||
Question: What were the names of the 3 mascots at the Sydney Olympic Games?
|
|
||||||
Answer: Ollie Millie Syd
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Quotes
|
|
||||||
Question: Who said "Come up and see me sometime"?
|
|
||||||
Answer: Mae West
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Quotes
|
|
||||||
Question: Who said "Tha tha that's all folks"?
|
|
||||||
Answer: Porky Pig
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Quotes
|
|
||||||
Question: Who said "Go ahead - make my day" (character name)?
|
|
||||||
Answer: Harry Callaghan
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Sport
|
|
||||||
Question: What sport do the following terms belong to - "Tight End & Wide Receiver"?
|
|
||||||
Answer: #American Football# (Gridiron)
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Sport
|
|
||||||
Question: What sport do the following terms belong to - "Pull & Lolly"?
|
|
||||||
Answer: Cricket
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Sport
|
|
||||||
Question: What sport do the following terms belong to - "Jerk & Snatch"?
|
|
||||||
Answer: Weightlifting
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Sport
|
|
||||||
Question: What sport do the following terms belong to - "Hotdog & Bottom Trun"?
|
|
||||||
Answer: Surfing
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Sport
|
|
||||||
Question: What sport do the following terms belong to - "Toucher & Dead Length"?
|
|
||||||
Answer: Lawn or Indoor Bowls
|
|
||||||
Regexp: (Lawn)?(Indoor Bowls)?
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Sport
|
|
||||||
Question: What sport do the following terms belong to - "Pist & Telemark"?
|
|
||||||
Answer: Skiing
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Sport
|
|
||||||
Question: What sport do the following terms belong to - "Touches & Lunges"?
|
|
||||||
Answer: Fencing
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Sport
|
|
||||||
Question: What sport do the following terms belong to - "Behind & Banana Kick"?
|
|
||||||
Answer: Australian Football League
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Sport
|
|
||||||
Question: What sport do the following terms belong to - "Sweeper & Advantage Rule"?
|
|
||||||
Answer: Soccer
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Astronomy
|
|
||||||
Question: How many stars make up the 'Southern Cross'?
|
|
||||||
Answer: 5
|
|
||||||
Regexp: (5|Five)
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Astronomy
|
|
||||||
Question: How many Earths would it take to match the size of the sun? Over 1000, 100,000 or 1,000,000?
|
|
||||||
Answer: 1,000,000
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Astronomy
|
|
||||||
Question: What planet position is the Earth from the Sun?
|
|
||||||
Answer: 3rd
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Astronomy
|
|
||||||
Question: How long does it take for Earth to travel around the Sun?
|
|
||||||
Answer: 1 Year
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Astronomy
|
|
||||||
Question: The Moon orbits around the Earth -Tue or False.?
|
|
||||||
Answer: True
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Famous Aliases
|
|
||||||
Question: By what name is Maurice Micklewhite better known as?
|
|
||||||
Answer: Michael Caine
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Famous Aliases
|
|
||||||
Question: By what name is Arthur Leech better known as?
|
|
||||||
Answer: Cary Grant
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Famous Aliases
|
|
||||||
Question: By what name is Robert Zimmerman better known as?
|
|
||||||
Answer: Bob Dylan
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Famous Aliases
|
|
||||||
Question: By what name is Francis Gumm better known as?
|
|
||||||
Answer: Judy Garland
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Famous Aliases
|
|
||||||
Question: By what name is Richard Starkey better known as?
|
|
||||||
Answer: Ringo Starr
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Famous Aliases
|
|
||||||
Question: By what name is Allan Stewart Konisburg better known as?
|
|
||||||
Answer: Woody Allan
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Famous Aliases
|
|
||||||
Question: By what name is Marion Morrison better known as?
|
|
||||||
Answer: John Wayne
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Famous Aliases
|
|
||||||
Question: By what name is Reginald Dwight better known as?
|
|
||||||
Answer: Elton John
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Famous Aliases
|
|
||||||
Question: By what name is Norma Jean Baker better known as?
|
|
||||||
Answer: Marilyn Monroe
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Food & Drink
|
|
||||||
Question: What is the main ingredient in the soup Borscht?
|
|
||||||
Answer: Beetroot
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: General
|
|
||||||
Question: How many axles does an 18 wheeler truck have?
|
|
||||||
Answer: 5
|
|
||||||
Regexp: (5|Five)
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Animals
|
|
||||||
Question: What bird has the biggest wingspan?
|
|
||||||
Answer: Albatross
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Animals
|
|
||||||
Question: What do you call a group of rhinocerus?
|
|
||||||
Answer: A Crash
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Geography
|
|
||||||
Question: What country is Mt Etna in?
|
|
||||||
Answer: Italy
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Plants
|
|
||||||
Question: What genus of tree does the wattle belong?
|
|
||||||
Answer: Acacia
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Plants
|
|
||||||
Question: What do you offer someone as a peace gesture?
|
|
||||||
Answer: An Olive Branch
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Plants
|
|
||||||
Question: What word describes part of your hand and a type of tree?
|
|
||||||
Answer: Palm
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Plants
|
|
||||||
Question: What is the name given to the art of miniaturising trees and maintaining their small size?
|
|
||||||
Answer: Bonsai
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Plants
|
|
||||||
Question: What part of a rhubarb plant is poisonous?
|
|
||||||
Answer: The Leaves
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Flags
|
|
||||||
Question: What are the 2 background colours of the Welsh flag?
|
|
||||||
Answer: Green and White
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Flags
|
|
||||||
Question: What creature is depicted on the Welsh Flag?
|
|
||||||
Answer: A Red Dragon
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Emblems
|
|
||||||
Question: What is the flower emblem of Wales?
|
|
||||||
Answer: Daffodil
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Saints
|
|
||||||
Question: Who is the patron saint of Wales?
|
|
||||||
Answer: St David
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Food & Drink
|
|
||||||
Question: What nut is used to make marzipan?
|
|
||||||
Answer: Almond
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Flags
|
|
||||||
Question: What 3 colours are featured on the Australian Aboriginal flag?
|
|
||||||
Answer: Black Red Yellow
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Music
|
|
||||||
Question: What other well known singer shares the same birthday as Elvis Presley (Jan 8)?
|
|
||||||
Answer: David Bowie
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Music
|
|
||||||
Question: Name the band - songs include "Add It Up, Blister In The Sun, Kiss Off"?
|
|
||||||
Answer: Violet Femmes
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Music
|
|
||||||
Question: Name the band - songs include "Baby I Don't Care, I Want Your Love"?
|
|
||||||
Answer: Transvision Vamp
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Music
|
|
||||||
Question: Name the band - songs include "Strange Brew, White Room"?
|
|
||||||
Answer: Cream
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Anniversaries
|
|
||||||
Question: What gift is associated with the 60th Wedding Anniversary?
|
|
||||||
Answer: Diamonds
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Anniversaries
|
|
||||||
Question: What gift is associated with the 20th Wedding Anniversary?
|
|
||||||
Answer: China
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Anniversaries
|
|
||||||
Question: What gift is associated with the 30th Wedding Anniversary?
|
|
||||||
Answer: Pearls
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Anniversaries
|
|
||||||
Question: What gift is associated with the 40th Wedding Anniversary?
|
|
||||||
Answer: Rubies
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: General
|
|
||||||
Question: Bowline, Figure Eight & Square are all types of what?
|
|
||||||
Answer: Knots
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Honours & Awards
|
|
||||||
Question: What does OBE stand for?
|
|
||||||
Answer: Officer of the Order of the British Empire
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Dates
|
|
||||||
Question: What is celebrated on April 1st?
|
|
||||||
Answer: April Fools Day
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Dates
|
|
||||||
Question: What famous playwrite has his birthday on 23rd April?
|
|
||||||
Answer: William Shakespeare
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Dates
|
|
||||||
Question: What country celebrates its National Day on 17th May?
|
|
||||||
Answer: Norway
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Dates
|
|
||||||
Question: What famous battle was fought on 4th June 1942?
|
|
||||||
Answer: The Battle of Midway
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Dates
|
|
||||||
Question: What country celebrates its National Day on 6th June?
|
|
||||||
Answer: Sweden
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Dates
|
|
||||||
Question: What country celebrates its National Day on 2nd June?
|
|
||||||
Answer: Italy
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Dates
|
|
||||||
Question: What country celebrates its National Day on 17th June?
|
|
||||||
Answer: Iceland
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Dates
|
|
||||||
Question: What country celebrates its National Day on 25th June?
|
|
||||||
Answer: Slovenia
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Dates
|
|
||||||
Question: What was signed on 15th June 1215?
|
|
||||||
Answer: The Magna Carta
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Dates
|
|
||||||
Question: What country celebrates its National Day on 14th July?
|
|
||||||
Answer: France
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Dates
|
|
||||||
Question: What country celebrates its National Day on 21st July?
|
|
||||||
Answer: Belgium
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Date
|
|
||||||
Question: This date is the date in the middle of the year.?
|
|
||||||
Answer: 2nd July
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Dates
|
|
||||||
Question: What country celebrates its National Day on 25th August?
|
|
||||||
Answer: Uruguay
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Dates
|
|
||||||
Question: What country celebrates its National Day on 29th October?
|
|
||||||
Answer: Turkey
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Dates
|
|
||||||
Question: What country celebrates its National Day on 12th October?
|
|
||||||
Answer: Spain
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Dates
|
|
||||||
Question: What country celebrates its National Day on 26th October?
|
|
||||||
Answer: Austria
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Flags
|
|
||||||
Question: What 3 flags does the Union Jack comprise of?
|
|
||||||
Answer: England Scotland Ireland
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Dates
|
|
||||||
Question: What country celebrates its National Day on 29th October?
|
|
||||||
Answer: Turkey
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Dates
|
|
||||||
Question: What country celebrated its National Day on 1st March?
|
|
||||||
Answer: Wales
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Dates
|
|
||||||
Question: What country celebrated its National Day on 15th March?
|
|
||||||
Answer: Hungary
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Dates
|
|
||||||
Question: What well known bard (poems & songs) was born on 25th January 1759?
|
|
||||||
Answer: Robert Burns
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Music
|
|
||||||
Question: Name the band - songs include "Aqualung, Thick as a Brick"?
|
|
||||||
Answer: Jethro Tull
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Music
|
|
||||||
Question: Name the band - songs include "Mystify, Listen Like Thieves, Original Sin"?
|
|
||||||
Answer: INXS
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Music
|
|
||||||
Question: Name the band - songs include "Heart of Glass, The Tide is High"?
|
|
||||||
Answer: Blondie
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Music
|
|
||||||
Question: Name the singer - songs include "Me & Bobby McGee, Mercedes Benz"?
|
|
||||||
Answer: Janis Joplin
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Music
|
|
||||||
Question: Name the band - songs include "Black Night, Smoke On The Water"?
|
|
||||||
Answer: Deep Purple
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Music
|
|
||||||
Question: Name the band - songs include "Monday Monday, California Dreamin'"?
|
|
||||||
Answer: The Mamas and the Papas
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Music
|
|
||||||
Question: Name the band - songs include "Light My Fire, Love Her Madly"?
|
|
||||||
Answer: The Doors
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Music
|
|
||||||
Question: Name the band - songs include "Let's Stick Together, The Price of Love"?
|
|
||||||
Answer: Bryan Ferry
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Music
|
|
||||||
Question: Name the band - songs include "Psycho Killer, Road To Nowhere"?
|
|
||||||
Answer: Talkingheads
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Music
|
|
||||||
Question: Name the band - songs include "Get Down & Get With It, Mama We're All Crazy Now"?
|
|
||||||
Answer: Slade
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Music
|
|
||||||
Question: Name the band - songs include "Forgiven Not Forgotten, Runaway"?
|
|
||||||
Answer: The Coors
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Music
|
|
||||||
Question: Name the band - songs include "Doctor Doctor, Hold Me Now, Don't Mess With Dr Dream"?
|
|
||||||
Answer: Thompson Twins
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Music
|
|
||||||
Question: Name the band - songs include "Sex & Drugs & Rock & Roll, I Want To Be Straight"?
|
|
||||||
Answer: Ian Drury and The Blockheads
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Music
|
|
||||||
Question: A graphical representation of the guitar fingerboard, used to teach someone to play a guitar without actually learning how to read musical notes.?
|
|
||||||
Answer: Tablature
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Riddles?
|
|
||||||
Question: How do you name 3 consecutive days without saying Monday, Tuesday, Wednesday, Thursday, Friday, Saturday or Sunday?
|
|
||||||
Answer: Yesterday Today and Tomorrow
|
|
||||||
Author: OllyPomm
|
|
||||||
|
|
||||||
Category: Riddles?
|
|
||||||
Question: What was the highest mountain before Mt Everest was discovered?
|
|
||||||
Answer: Mt Everest
|
|
||||||
Author: OllyPomm
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +0,0 @@
|
||||||
SQLAlchemy==1.0.9
|
|
||||||
beautifulsoup4==4.4.1
|
|
||||||
irc==13.2
|
|
||||||
requests==2.8.1
|
|
||||||
22
runbot
22
runbot
|
|
@ -1,22 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
PATH=/bin:/usr/bin
|
|
||||||
|
|
||||||
NOW=`date +%Y-%m-%d_%H%M`
|
|
||||||
if [ "x$1" = "x" ]; then
|
|
||||||
CONFIG=""
|
|
||||||
else
|
|
||||||
CONFIG="--config $1"
|
|
||||||
fi
|
|
||||||
|
|
||||||
LOLBOTS=`ps -ef|grep 'lolbot.py'|grep -v grep|awk '{print $2}'`
|
|
||||||
if [ "$LOLBOTS" != "" ]; then
|
|
||||||
kill $LOLBOTS
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd `dirname $0`
|
|
||||||
APP_PATH=`pwd`
|
|
||||||
while true; do
|
|
||||||
/usr/bin/python $APP_PATH/lolbot.py $CONFIG > logs/server-$NOW.log 2> logs/error-$NOW.log
|
|
||||||
done
|
|
||||||
|
|
||||||
Loading…
Add table
Reference in a new issue