Speaking fortunes
This commit is contained in:
parent
e4e70aef67
commit
b3e3baded5
2 changed files with 157 additions and 30 deletions
|
@ -2,7 +2,7 @@
|
|||
#-*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Get a fortune from a JSON file.
|
||||
Get a fortune from a JSON file and say it.
|
||||
|
||||
File is under EUPL1.2
|
||||
Author: kujiu
|
||||
|
@ -11,51 +11,167 @@ Author: kujiu
|
|||
import json
|
||||
import argparse
|
||||
import logging
|
||||
import threading
|
||||
|
||||
import sys
|
||||
import os.path
|
||||
import random
|
||||
try:
|
||||
import speechd
|
||||
except ImportError:
|
||||
speechd = None
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
ch = logging.StreamHandler(sys.stderr)
|
||||
ch.setLevel(logging.WARNING)
|
||||
logger.addHandler(ch)
|
||||
|
||||
def get_quote(srcfile):
|
||||
"""
|
||||
Get a quote
|
||||
"""
|
||||
with open(srcfile) as fin:
|
||||
quotes = json.load(fin)
|
||||
class JsonFortune:
|
||||
def __init__(self, srcfile, speak, module, rate, cycle, timer):
|
||||
"""
|
||||
Fortune software
|
||||
"""
|
||||
self.speak = speak
|
||||
self.module = module
|
||||
self.rate = rate
|
||||
self.cycle = cycle
|
||||
self.timer = timer
|
||||
if not module:
|
||||
module = 'default'
|
||||
|
||||
quote = ""
|
||||
count = 0
|
||||
while not quote and count < 50:
|
||||
count += 1
|
||||
lang = random.choice([lang for lang in quotes.keys()])
|
||||
category = random.choice([cat for cat in quotes[lang].keys()])
|
||||
if not quotes[lang][category]:
|
||||
continue
|
||||
author = random.choice(
|
||||
[author for author in quotes[lang][category].keys()])
|
||||
if not quotes[lang][category][author]:
|
||||
continue
|
||||
quote = random.choice(quotes[lang][category][author])
|
||||
if quote:
|
||||
quote += "\n-- %s" % author
|
||||
with open(srcfile) as fin:
|
||||
self.quotes = json.load(fin)
|
||||
|
||||
return quote
|
||||
def get_quote(self):
|
||||
"""
|
||||
Get a quote, returns (quote, lang, author)
|
||||
"""
|
||||
quote = ""
|
||||
count = 0
|
||||
while not quote and count < 50:
|
||||
count += 1
|
||||
lang = random.choice([lang for lang in self.quotes])
|
||||
category = random.choice([cat for cat in self.quotes[lang]])
|
||||
if not self.quotes[lang][category]:
|
||||
continue
|
||||
author = random.choice(
|
||||
[author for author in self.quotes[lang][category]])
|
||||
if not self.quotes[lang][category][author]:
|
||||
continue
|
||||
quote = random.choice(self.quotes[lang][category][author])
|
||||
|
||||
return (quote, lang, author)
|
||||
|
||||
def say_quote(self):
|
||||
"""
|
||||
Say a random quote
|
||||
"""
|
||||
quote, lang, author = self.get_quote()
|
||||
|
||||
if not speechd:
|
||||
logger.error("Speech Dispatcher is not loaded.")
|
||||
return
|
||||
|
||||
if not quote:
|
||||
logger.error("No quote found")
|
||||
return
|
||||
|
||||
quote += "\n %s" % author
|
||||
|
||||
speech_client = speechd.client.Client()
|
||||
speech_client.set_priority('important')
|
||||
speech_client.set_rate(self.rate)
|
||||
if self.module != 'default' and self.module:
|
||||
speech_client.set_output_module(self.module)
|
||||
|
||||
voices = [
|
||||
voice[0]
|
||||
for voice
|
||||
in speech_client.list_synthesis_voices()
|
||||
if voice[1] == lang]
|
||||
speech_client.set_language(lang)
|
||||
speech_client.set_synthesis_voice(random.choice(voices))
|
||||
logger.info("Say: %s", quote)
|
||||
speech_client.say(quote)
|
||||
speech_client.close()
|
||||
|
||||
def print_quote(self):
|
||||
"""
|
||||
Print a random quote.
|
||||
"""
|
||||
if self.cycle:
|
||||
print(chr(27) + "[2J")
|
||||
|
||||
quote_dict = self.get_quote()
|
||||
if not quote_dict:
|
||||
logger.error("No quote found")
|
||||
return
|
||||
|
||||
print(quote_dict[0] + "\n -- " + quote_dict[2])
|
||||
|
||||
def run(self):
|
||||
"""
|
||||
Run
|
||||
"""
|
||||
if self.speak:
|
||||
self.say_quote()
|
||||
else:
|
||||
self.print_quote()
|
||||
if self.cycle:
|
||||
threading.Timer(self.timer, self.run).start()
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description="Get a quote from JSON file.")
|
||||
parser = argparse.ArgumentParser(description="Print/say a quote from JSON file.")
|
||||
parser.add_argument(
|
||||
'--source', default='~/.fortunes.json',
|
||||
'-s', '--source', default='~/.fortunes.json',
|
||||
help='JSON file with quotes')
|
||||
parser.add_argument(
|
||||
'-v', '--verbose', default=False, action='store_true',
|
||||
help='Verbose')
|
||||
parser.add_argument(
|
||||
'-k', '--speak', default=False, action='store_true',
|
||||
help='Say with Speech Dispatcher, otherwise print it')
|
||||
parser.add_argument(
|
||||
'-m', '--module', default='default',
|
||||
help='Speech Dispatcher output module')
|
||||
parser.add_argument(
|
||||
'-r', '--rate', default=20,
|
||||
help='Speech Dispatcher rate', type=int)
|
||||
parser.add_argument(
|
||||
'-c', '--cycle', default=False, action='store_true',
|
||||
help='Display/say fortunes in loop.')
|
||||
parser.add_argument(
|
||||
'-t', '--timer', default=60,
|
||||
help='Number of seconds between two quotes', type=int)
|
||||
|
||||
options = parser.parse_args()
|
||||
|
||||
source = os.path.expanduser(
|
||||
os.path.expandvars(options.source)
|
||||
)
|
||||
|
||||
print(get_quote(source))
|
||||
speak = getattr(options, 'speak', False)
|
||||
module = getattr(options, 'module', None)
|
||||
rate = getattr(options, 'rate', 20)
|
||||
verbose = getattr(options, 'verbose', False)
|
||||
cycle = getattr(options, 'cycle', False)
|
||||
|
||||
ch = logging.StreamHandler(sys.stderr)
|
||||
ch.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(message)s'))
|
||||
ch.setLevel(logging.WARNING)
|
||||
logger.addHandler(ch)
|
||||
|
||||
class VerboseFilter(logging.Filter):
|
||||
def filter(self, rec):
|
||||
return rec.levelno in (logging.DEBUG, logging.INFO)
|
||||
|
||||
if verbose:
|
||||
ch = logging.StreamHandler(sys.stdout)
|
||||
ch.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(message)s'))
|
||||
ch.setLevel(logging.DEBUG)
|
||||
ch.addFilter(VerboseFilter())
|
||||
logger.addHandler(ch)
|
||||
logger.setLevel(logging.DEBUG)
|
||||
|
||||
logger.addHandler(ch)
|
||||
|
||||
fortune = JsonFortune(source, speak, module, rate, cycle, options.timer)
|
||||
fortune.run()
|
||||
|
|
|
@ -19,6 +19,7 @@ import wikiquote
|
|||
logger = logging.getLogger(__name__)
|
||||
|
||||
ch = logging.StreamHandler(sys.stderr)
|
||||
ch.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(message)s'))
|
||||
ch.setLevel(logging.WARNING)
|
||||
logger.addHandler(ch)
|
||||
|
||||
|
@ -79,15 +80,25 @@ Source file must be a JSON in this format:\n
|
|||
'-v', '--verbose', help="Verbose mode", action='store_true')
|
||||
options = parser.parse_args()
|
||||
|
||||
class VerboseFilter(logging.Filter):
|
||||
def filter(self, rec):
|
||||
return rec.levelno in (logging.DEBUG, logging.INFO)
|
||||
|
||||
if hasattr(options, 'debug') and options.debug:
|
||||
ch = logging.StreamHandler(sys.stdout)
|
||||
ch.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(message)s'))
|
||||
ch.setLevel(logging.DEBUG)
|
||||
ch.addFilter(VerboseFilter())
|
||||
logger.addHandler(ch)
|
||||
logger.setLevel(logging.DEBUG)
|
||||
|
||||
if hasattr(options, 'verbose') and options.verbose:
|
||||
elif hasattr(options, 'verbose') and options.verbose:
|
||||
ch = logging.StreamHandler(sys.stdout)
|
||||
ch.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(message)s'))
|
||||
ch.setLevel(logging.INFO)
|
||||
ch.addFilter(VerboseFilter())
|
||||
logger.addHandler(ch)
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
source = os.path.expanduser(
|
||||
os.path.expandvars(options.source)
|
||||
|
|
Loading…
Reference in a new issue