def play(self, fname, gain=None, wait=True): if not isinstance(fname, str) or fname[0] == '/' or fname.find('..') != -1: return False try: f = self.sdir + '/' + fname if self.cmd: cmd = self.cmd.replace( '%g', str(gain) if gain is not None else str(self.gain)).replace('%f', f) if self.cmd.find('%f') == -1: cmd += ' ' + f if not wait: cmd += ' &' import os ec = os.system(cmd) if ec: raise Exception('Command "{}" exit code: {}'.format( cmd, ec)) else: data, rate = self.sf.read(f) if data is None or not rate: raise Exception('invalid audio file %s' % fname) gain = gain if gain is not None else self.gain if gain: data = data * self._gain_multiplier(gain) self.sd.play(data, rate, blocking=wait, device=self.device) return True except: self.log_error('file %s playback failed' % fname) log_traceback() return False
def __init__(self, **kwargs): try: self.sdir = self.cfg.get('sdir') if not self.sdir: self.log_error('no audio files directory specified') raise Exception('no audio files directory specified') try: self.gain = float(self.cfg.get('g', 0)) except: self.log_error('invalid gain value: %s' % self.cfg.get('g')) raise try: if 'd' in self.cfg: self.device = int(self.cfg.get('d')) else: self.device = None except: self.log_error('invalid device number: %s' % self.cfg.get('d')) raise self.cmd = self.cfg.get('cmd') if not self.cmd: try: self.sf = importlib.import_module('soundfile') except: self.log_error('soundfile Python module not installed') raise try: self.sd = importlib.import_module('sounddevice') except: self.log_error('sounddevice Python module not installed') raise except: log_traceback() self.ready = False
def h_message(self, chat_id, text, **kwargs): try: with self.data_lock: key_id = self.data['auth'].get(str(chat_id)) if key_id: path = text.split(' ', 1) if path[0] in self.bot_commands: try: query_string = path[1] except: query_string = None return self.h_command(chat_id, '/' + path[0], query_string, **kwargs) self.tebot.send(f'API key: <b>{key_id}</b>', reply_markup=self.reply_markup) else: key_id = eva.apikey.key_id(text.strip()) if key_id == 'unknown': self.tebot.send(f'Invalid API key. Try again', reply_markup=self.remove_keyboard) else: with self.data_lock: self.data['auth'][str(chat_id)] = key_id self.data_modified = True self.tebot.send(f'Registered API key: {key_id}') self._send_help(key_id) except: log_traceback()
def say(self, text, **kwargs): if text is None: return False try: return self.tts.say(text, **kwargs) except: log_traceback() return False
def save(self): if self.data_modified: try: save_data(self) self.data_modified = False except: self.log_error('unable to save ext data') log_traceback()
def load(self): try: load_data(self) except FileNotFoundError: self.log_debug('no ext data file') except: self.log_error('unable to load ext data') log_traceback()
def __init__(self, **kwargs): try: provider = self.cfg.get('p') if not provider: self.log_error('no provider specified') raise Exception('no provider specified') try: gain = float(self.cfg.get('g', 0)) except: self.log_error('invalid gain value: %s' % self.cfg.get('g')) raise try: if 'd' in self.cfg: device = int(self.cfg.get('d')) else: device = None except: self.log_error('invalid device number: %s' % self.cfg.get('d')) raise try: mod = importlib.import_module('ttsbroker') except: self.log_error('ttsbroker Python module not installed') raise try: if 'o' in self.cfg: with open(self.cfg.get('o')) as fd: opts = rapidjson.loads(fd.read()) else: opts = {} except: self.log_error('invalid options file: %s' % self.cfg.get('o')) raise try: self.tts = mod.TTSEngine(storage_dir=self.cfg.get('sdir'), cache_dir=self.cfg.get('cdir'), cache_format=self.cfg.get('cf', 'wav'), device=device, gain=gain, provider=self.cfg.get('p'), provider_options=opts, cmd=self.cfg.get('cmd')) except: self.log_error('unable to init TTS broker') raise try: k = self.cfg.get('k') if k: self.tts.set_key(k) except: self.log_error('unable to set TTS key') raise except: log_traceback() self.ready = False
def h_logout(self, chat_id, **kwargs): with self.data_lock: try: del self.data['auth'][str(chat_id)] self.data_modified = True self.tebot.send( 'API key unregistered. Enter new API key to continue', reply_markup=self.remove_keyboard) except KeyError: self.tebot.send('API key not registered', reply_markup=self.remove_keyboard) except: log_traceback()
def __init__(self, **kwargs): try: try: mod = importlib.import_module('pyrpush') except: self.log_error('pyrpush Python module not installed') raise try: self.rpush = mod.Client(ini_file=self.cfg.get('cf')) except: self.log_error('unable to init pyrpush client') raise except: log_traceback() self.ready = False
def h_command(self, chat_id, path, query_string, **kwargs): with self.data_lock: key_id = self.data['auth'].get(str(chat_id)) if not key_id: self.tebot.send( 'Please enter valid API key before launching commands', reply_markup=self.remove_keyboard) return k = eva.apikey.key_by_id(key_id) cmd = path[1:] if cmd in self.bot_commands: try: result = api.run(k=k, i=cmd, a=query_string, kw={'chat_id': chat_id}, w=self.wait) exitcode = result.get('exitcode') if exitcode is None: self.tebot.send(f'{path} is still executing') else: if exitcode: self.tebot.send(f'{path} execution error', reply_markup=self.reply_markup) else: out = result.get('out') self.tebot.send(f'{path} executed' + (f', output:\n{out}' if out else ''), reply_markup=self.reply_markup) except AccessDenied: self.tebot.send(f'Unable to execute {path}: access denied', reply_markup=self.reply_markup) except ResourceNotFound: self.tebot.send(f'Unable to execute {path}: macro not found', reply_markup=self.reply_markup) except: self.tebot.send(f'Unable to execute {path}', reply_markup=self.reply_markup) log_traceback() else: self.tebot.send(f'Invalid command: {path}', reply_markup=self.reply_markup)
def __init__(self, **kwargs): try: try: cf = self.cfg.get('cf') if not cf: cf = eva.core.dir_etc + '/telegram.yml' with open(cf) as fh: config = yaml.load(fh.read()) except: self.log_error(f'unable to parse {cf}') raise try: mod = importlib.import_module('tebot') except: self.log_error('tebot Python module not installed') raise self.tebot = mod.TeBot(interval=config.get('interval', 2), on_error=log_traceback) self.tebot.set_token(config['token']) self.tebot.retry_interval = config.get('retry-interval') self.tebot.timeout = get_timeout() self.wait = float(config.get('wait', 60)) keyboard = [] inline_keyboard = [] self.reply_markup = {'inline_keyboard': inline_keyboard} self.reply_markup_keyboard = {'keyboard': keyboard} self.remove_keyboard = {'remove_keyboard': True} self.bot_commands = [] self.bot_help = [] self.bot_help_builtin = ['help - get help', 'logout - log out'] bot_help = set() bot_commands = set() try: inline = config.get('inline-keyboard', []) for row in inline: row_data = [] for col in row: data, text = col.split(':', 1) if data.startswith('.'): data = data[1:] else: row_data.append({ 'text': text, 'callback_data': f'/{data}' }) bot_help.add(f'{data} - {text}') bot_commands.add(data) if row_data: inline_keyboard.append(row_data) kbd = config.get('keyboard', []) for row in kbd: row_data = [] for command in row: row_data.append({ 'text': command, }) bot_commands.add(command) if row_data: keyboard.append(row_data) self.bot_commands = sorted(bot_commands) self.bot_help = sorted(bot_help) except: self.log_error('unable to parse keyboards') raise self.tebot.register_route(self.h_message, methods='message') self.tebot.register_route(self.h_start, path=['/start', '/help']) self.tebot.register_route(self.h_getcommands, path='/getcommands') self.tebot.register_route(self.h_logout, path='/logout') self.tebot.register_route(self.h_command, methods='*') with self.data_lock: self.data['auth'] = {} self.data_modified = True except: log_traceback() self.ready = False
def push(self, msg=None, media_file=None, **kwargs): try: return self.rpush.push(msg, media_file, **kwargs) except: log_traceback() return False