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 -*-
|
#-*- 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
|
File is under EUPL1.2
|
||||||
Author: kujiu
|
Author: kujiu
|
||||||
|
@ -11,51 +11,167 @@ Author: kujiu
|
||||||
import json
|
import json
|
||||||
import argparse
|
import argparse
|
||||||
import logging
|
import logging
|
||||||
|
import threading
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import os.path
|
import os.path
|
||||||
import random
|
import random
|
||||||
|
try:
|
||||||
|
import speechd
|
||||||
|
except ImportError:
|
||||||
|
speechd = None
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
ch = logging.StreamHandler(sys.stderr)
|
|
||||||
ch.setLevel(logging.WARNING)
|
|
||||||
logger.addHandler(ch)
|
|
||||||
|
|
||||||
def get_quote(srcfile):
|
class JsonFortune:
|
||||||
|
def __init__(self, srcfile, speak, module, rate, cycle, timer):
|
||||||
"""
|
"""
|
||||||
Get a quote
|
Fortune software
|
||||||
"""
|
"""
|
||||||
|
self.speak = speak
|
||||||
|
self.module = module
|
||||||
|
self.rate = rate
|
||||||
|
self.cycle = cycle
|
||||||
|
self.timer = timer
|
||||||
|
if not module:
|
||||||
|
module = 'default'
|
||||||
|
|
||||||
with open(srcfile) as fin:
|
with open(srcfile) as fin:
|
||||||
quotes = json.load(fin)
|
self.quotes = json.load(fin)
|
||||||
|
|
||||||
|
def get_quote(self):
|
||||||
|
"""
|
||||||
|
Get a quote, returns (quote, lang, author)
|
||||||
|
"""
|
||||||
quote = ""
|
quote = ""
|
||||||
count = 0
|
count = 0
|
||||||
while not quote and count < 50:
|
while not quote and count < 50:
|
||||||
count += 1
|
count += 1
|
||||||
lang = random.choice([lang for lang in quotes.keys()])
|
lang = random.choice([lang for lang in self.quotes])
|
||||||
category = random.choice([cat for cat in quotes[lang].keys()])
|
category = random.choice([cat for cat in self.quotes[lang]])
|
||||||
if not quotes[lang][category]:
|
if not self.quotes[lang][category]:
|
||||||
continue
|
continue
|
||||||
author = random.choice(
|
author = random.choice(
|
||||||
[author for author in quotes[lang][category].keys()])
|
[author for author in self.quotes[lang][category]])
|
||||||
if not quotes[lang][category][author]:
|
if not self.quotes[lang][category][author]:
|
||||||
continue
|
continue
|
||||||
quote = random.choice(quotes[lang][category][author])
|
quote = random.choice(self.quotes[lang][category][author])
|
||||||
if quote:
|
|
||||||
quote += "\n-- %s" % author
|
|
||||||
|
|
||||||
return quote
|
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__':
|
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(
|
parser.add_argument(
|
||||||
'--source', default='~/.fortunes.json',
|
'-s', '--source', default='~/.fortunes.json',
|
||||||
help='JSON file with quotes')
|
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()
|
options = parser.parse_args()
|
||||||
|
|
||||||
source = os.path.expanduser(
|
source = os.path.expanduser(
|
||||||
os.path.expandvars(options.source)
|
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__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
ch = logging.StreamHandler(sys.stderr)
|
ch = logging.StreamHandler(sys.stderr)
|
||||||
|
ch.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(message)s'))
|
||||||
ch.setLevel(logging.WARNING)
|
ch.setLevel(logging.WARNING)
|
||||||
logger.addHandler(ch)
|
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')
|
'-v', '--verbose', help="Verbose mode", action='store_true')
|
||||||
options = parser.parse_args()
|
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:
|
if hasattr(options, 'debug') and options.debug:
|
||||||
ch = logging.StreamHandler(sys.stdout)
|
ch = logging.StreamHandler(sys.stdout)
|
||||||
|
ch.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(message)s'))
|
||||||
ch.setLevel(logging.DEBUG)
|
ch.setLevel(logging.DEBUG)
|
||||||
|
ch.addFilter(VerboseFilter())
|
||||||
logger.addHandler(ch)
|
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 = logging.StreamHandler(sys.stdout)
|
||||||
|
ch.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(message)s'))
|
||||||
ch.setLevel(logging.INFO)
|
ch.setLevel(logging.INFO)
|
||||||
|
ch.addFilter(VerboseFilter())
|
||||||
logger.addHandler(ch)
|
logger.addHandler(ch)
|
||||||
|
logger.setLevel(logging.INFO)
|
||||||
|
|
||||||
source = os.path.expanduser(
|
source = os.path.expanduser(
|
||||||
os.path.expandvars(options.source)
|
os.path.expandvars(options.source)
|
||||||
|
|
Loading…
Reference in a new issue