mirror of
https://github.com/MarkParker5/STARK.git
synced 2024-11-24 08:12:13 +02:00
Fully new layout (in progress)
This commit is contained in:
parent
9f147ada14
commit
9a08765f70
8
Controls/Control.py
Normal file
8
Controls/Control.py
Normal file
@ -0,0 +1,8 @@
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
class Control(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def start(self):
|
||||
# entry point of the control
|
||||
pass
|
4
Controls/Django/Django.py
Normal file
4
Controls/Django/Django.py
Normal file
@ -0,0 +1,4 @@
|
||||
class DJango(Control):
|
||||
def start(self):
|
||||
# run manage.py
|
||||
pass
|
97
Controls/TelegramBot/TelegramBot.py
Normal file
97
Controls/TelegramBot/TelegramBot.py
Normal file
@ -0,0 +1,97 @@
|
||||
#!/usr/local/bin/python3.8
|
||||
from Command import Command
|
||||
import Text2Speech
|
||||
import telebot
|
||||
import config
|
||||
import modules
|
||||
import time
|
||||
import os
|
||||
|
||||
class TelegramBot(Control):
|
||||
threads = []
|
||||
online = True
|
||||
voids = 0
|
||||
memory = []
|
||||
voice = Text2Speech.Engine()
|
||||
bot = telebot.TeleBot(config.telebot)
|
||||
|
||||
# Singleton
|
||||
def __new__(self, cls):
|
||||
if not hasattr(cls, 'instance'):
|
||||
cls.instance = super(VoiceAssistant, cls).__new__(cls)
|
||||
return cls.instance
|
||||
|
||||
def reply(self, id, response):
|
||||
if response.text:
|
||||
bot.send_message(id, response.text)
|
||||
if response.voice:
|
||||
bot.send_voice(id, voice.generate(response.voice).getBytes() )
|
||||
if response.thread: # add background thread to list
|
||||
response.thread['id'] = id
|
||||
threads.append(response.thread)
|
||||
|
||||
def check_threads(self, threads):
|
||||
for thread in threads:
|
||||
if thread['finish_event'].is_set():
|
||||
response = thread['thread'].join()
|
||||
reply(thread['id'], response)
|
||||
thread['finish_event'].clear()
|
||||
del thread
|
||||
|
||||
def main(self, id, text):
|
||||
text = text.lower()
|
||||
if Command.isRepeat(text):
|
||||
reply(id, memory[0]['response']);
|
||||
return
|
||||
if memory:
|
||||
response = memory[0]['response']
|
||||
if response.callback:
|
||||
if new_response := response.callback.answer(text):
|
||||
reply(id, new_response)
|
||||
memory.insert(0, {
|
||||
'cmd': response.callback,
|
||||
'params': None,
|
||||
'response': new_response,
|
||||
})
|
||||
return
|
||||
try:
|
||||
cmd, params = memory[0]['cmd'].checkContext(text).values()
|
||||
if memory[0].get('params'): params = {**memory[0].get('params'), **params}
|
||||
except:
|
||||
cmd, params = Command.reg_find(text).values()
|
||||
response = cmd.start(params)
|
||||
reply(id, response)
|
||||
memory.insert(0, {
|
||||
'cmd': cmd,
|
||||
'params': params,
|
||||
'response': response,
|
||||
})
|
||||
|
||||
@bot.message_handler(commands=['vlc', 'queue', 'cmd'])
|
||||
def simple_commands(msg):
|
||||
command = msg.text.replace('/cmd', '').replace('/vlc', 'vlc')
|
||||
if '/queue' in msg.text: command = command.replace('/queue', '') + '--playlist-enqueue'
|
||||
os.system(f'lxterminal --command="{command}"')
|
||||
|
||||
@bot.message_handler(commands=['terminal'])
|
||||
def terminal(msg):
|
||||
command = msg.text.replace('/terminal', '')
|
||||
output = os.popen(command).read()
|
||||
bot.send_message(msg.chat.id, output)
|
||||
|
||||
@bot.message_handler(content_types = ['text'])
|
||||
def execute(msg):
|
||||
main(msg.chat.id, msg.text)
|
||||
|
||||
def start(self):
|
||||
while True:
|
||||
try:
|
||||
print("Start polling...")
|
||||
bot.polling(callback = check_threads, args = (threads,) )
|
||||
except:
|
||||
time.sleep(10)
|
||||
print("Polling failed")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
TelegramBot().start()
|
150
Controls/VoiceAssistant/VoiceAssistant.py
Normal file
150
Controls/VoiceAssistant/VoiceAssistant.py
Normal file
@ -0,0 +1,150 @@
|
||||
#!/usr/local/bin/python3.8
|
||||
import SpeechRecognition
|
||||
import Text2Speech
|
||||
from Command import Command
|
||||
import config
|
||||
import modules
|
||||
import os
|
||||
|
||||
if config.double_clap_activation:
|
||||
import RPi.GPIO as GPIO
|
||||
import time
|
||||
|
||||
GPIO.setmode(GPIO.BCM)
|
||||
GPIO.setup(12, GPIO.IN)
|
||||
GPIO.add_event_detect(12, GPIO.RISING, callback = checkClap)
|
||||
|
||||
class VoiceAssistant(Control):
|
||||
listener = SpeechRecognition.SpeechToText()
|
||||
voice = Text2Speech.Engine()
|
||||
threads = []
|
||||
reports = []
|
||||
memory = []
|
||||
voids = 0
|
||||
|
||||
lastClapTime = 0
|
||||
doubleClap = False
|
||||
|
||||
# Singleton
|
||||
def __new__(cls):
|
||||
if not hasattr(cls, 'instance'):
|
||||
cls.instance = super(VoiceAssistant, cls).__new__(cls)
|
||||
return cls.instance
|
||||
|
||||
def start(self):
|
||||
listener.listen_noise()
|
||||
os.system('clear')
|
||||
|
||||
while True:
|
||||
if voids >= 3:
|
||||
voids = 0
|
||||
if config.double_clap_activation:
|
||||
print('\nSleep (-_-)zzZZ\n')
|
||||
sleep()
|
||||
print('\nYou: ', end='')
|
||||
speech = listener.listen()
|
||||
print(speech.get('text') or '', end='')
|
||||
while True:
|
||||
if speech['status'] == 'error':
|
||||
break
|
||||
if speech['status'] == 'void':
|
||||
voids += 1
|
||||
break
|
||||
text = speech['text']
|
||||
cmd, params = Command.reg_find(text).values()
|
||||
try: response = cmd.start(params)
|
||||
except: break
|
||||
reply(response)
|
||||
check_threads()
|
||||
report()
|
||||
if response.callback:
|
||||
speech = recognize(response.callback, {})
|
||||
else:
|
||||
break
|
||||
|
||||
def recognize(self, callback, params):
|
||||
print('\nYou: ', end='')
|
||||
speech = listener.listen()
|
||||
if speech['status'] in ['error', 'void']:
|
||||
return speech
|
||||
text = speech['text']
|
||||
print(text, end='')
|
||||
while True:
|
||||
check_threads()
|
||||
if not callback: break
|
||||
try:
|
||||
if response := callback.answer(text):
|
||||
reply(response)
|
||||
except:
|
||||
break
|
||||
memory.insert(0, {
|
||||
'text': text,
|
||||
'cmd': cmd,
|
||||
'response': response,
|
||||
})
|
||||
speech = recognize(response.callback, params)
|
||||
if callback.once: break
|
||||
return speech
|
||||
|
||||
def report(self):
|
||||
global reports
|
||||
for response in reports:
|
||||
if response.voice:
|
||||
voice.generate(response.voice).speak()
|
||||
time.sleep(2)
|
||||
reports = []
|
||||
|
||||
def reply(self, response):
|
||||
if response.text: # print answer
|
||||
print('\nArchie: '+response.text)
|
||||
if response.voice: # say answer
|
||||
voice.generate(response.voice).speak()
|
||||
if response.thread: # add background thread to stack
|
||||
threads.append(response.thread)
|
||||
|
||||
def check_threads(self):
|
||||
for thread in threads:
|
||||
if not thread['finish_event'].is_set(): continue
|
||||
response = thread['thread'].join()
|
||||
reply(response)
|
||||
if response.callback:
|
||||
if response.callback.quiet:
|
||||
response.callback.start()
|
||||
else:
|
||||
for _ in range(3):
|
||||
print('\nYou: ', end='')
|
||||
speech = listener.listen()
|
||||
if speech['status'] == 'ok':
|
||||
print(speech['text'], '\n')
|
||||
new_response = response.callback.answer(speech['text'])
|
||||
reply(new_response)
|
||||
break
|
||||
else:
|
||||
reports.append(response)
|
||||
thread['finish_event'].clear()
|
||||
del thread
|
||||
|
||||
# check double clap from arduino microphone module
|
||||
def checkClap(self, channel):
|
||||
global lastClapTime
|
||||
global doubleClap
|
||||
now = time.time()
|
||||
delta = now - lastClapTime
|
||||
if 0.1 < delta < 0.6:
|
||||
doubleClap = True
|
||||
else:
|
||||
lastClapTime = now
|
||||
|
||||
# waiting for double clap
|
||||
def sleep(self):
|
||||
global lastClapTime
|
||||
lastClapTime = 0
|
||||
global doubleClap
|
||||
while not doubleClap:
|
||||
check_threads()
|
||||
time.sleep(1)
|
||||
else:
|
||||
doubleClap = False
|
||||
|
||||
if __name__ == '__main__':
|
||||
VoiceAssistant().start()
|
@ -26,7 +26,7 @@
|
||||
|
||||
|
||||
|
||||
from abc import ABC, abstractmethod # for abstract class and methods
|
||||
from abc import ABC, abstractmethod
|
||||
# from fuzzywuzzy import fuzz
|
||||
from threading import Thread, Event
|
||||
import re
|
72
QA/QA.py
72
QA/QA.py
@ -1,72 +0,0 @@
|
||||
from bs4 import BeautifulSoup as BS
|
||||
from Command import Command, Response
|
||||
import wikipedia as wiki
|
||||
import requests
|
||||
import random
|
||||
import json
|
||||
import re
|
||||
|
||||
class QA(Command):
|
||||
def googleDictionary(this, word):
|
||||
response = requests.get(f'https://api.dictionaryapi.dev/api/v2/entries/ru/{word}')
|
||||
if response.status_code == 200:
|
||||
response = json.loads(response.content)
|
||||
text = ''
|
||||
r = response[0]
|
||||
definition = r['meanings'][0]['definitions'][0]
|
||||
short = r['word'].lower().capitalize() + ' (' + ( r['meanings'][0]['partOfSpeech'].capitalize() if r['meanings'][0]['partOfSpeech'] != 'undefined' else 'Разговорный' ) + ') — ' + definition['definition'].lower().capitalize() + ( '. Синонимы: ' + ', '.join(definition['synonyms']) if definition['synonyms'] else '')
|
||||
short = short.replace(word[0].lower()+'.', word.lower())
|
||||
short = short.replace(word[0].upper()+'.', word.capitalize())
|
||||
short = short.replace('-н.', '-нибудь')
|
||||
short = short.replace('потр.', 'потребляется')
|
||||
short = short.replace('знач.', 'значении')
|
||||
|
||||
for r in response:
|
||||
text += '\n' + r['word'].lower().capitalize() + ' (' + (r['meanings'][0]['partOfSpeech'].capitalize() if r['meanings'][0]['partOfSpeech'] != 'undefined' else 'Разговорный') + ')\n'
|
||||
for definition in r['meanings'][0]['definitions']:
|
||||
text += '\t— ' + definition['definition'].lower().capitalize()
|
||||
if example := definition.get('example'):
|
||||
text += '\n\tНапример: ' + example
|
||||
if synonyms := definition['synonyms']:
|
||||
text += '\n\tСинонимы: ' + ', '.join(synonyms) + '.'
|
||||
if antonyms := definition['antonyms']:
|
||||
text += '\n\tАнтонимы: ' + ', '.join(antonyms) + '.'
|
||||
text += '\n\n'
|
||||
|
||||
return {
|
||||
'text': text,
|
||||
'short': short,
|
||||
}
|
||||
return {}
|
||||
|
||||
def wikipedia(this, word):
|
||||
wiki.set_lang("ru")
|
||||
article = wiki.summary(word, sentences=5)
|
||||
try: return article[:article.find('\n\n')][:600]
|
||||
except: return ''
|
||||
|
||||
def googleSearch(this, word):
|
||||
response = requests.get(f'https://www.google.ru/search?&q={word}&lr=lang_ru&lang=ru')
|
||||
page = BS(response.content, 'html.parser')
|
||||
info = page.select('div.BNeawe>div>div.BNeawe')
|
||||
return info[0].get_text() if info else ''
|
||||
|
||||
def start(this, params):
|
||||
query = params['string']
|
||||
if 'вики' in query:
|
||||
query = query.replace('википедия', '').replace('вики', '').strip()
|
||||
try: search = this.googleSearch(query)
|
||||
except: search = ''
|
||||
try: wiki = this.wikipedia(query) if not 'Википедия' in search else ''
|
||||
except: wiki = ''
|
||||
try: gdict = this.googleDictionary(query)
|
||||
except: gdict = []
|
||||
voice = search or (gdict['short'] if gdict else '') or wiki
|
||||
text = (f'Google Search:\n\t{search}' if search else '') + (f'\n\nWikipedia:\n\t{wiki}' if wiki else '') + ('\n\nDictionary:'+gdict['text'] if gdict else '')
|
||||
else:
|
||||
try: search = this.googleSearch(query)
|
||||
except: search = ''
|
||||
voice = text = search or random.choice(['Не совсем понимаю, о чём вы.', 'Вот эта последняя фраза мне не ясна.', 'А вот это не совсем понятно.', 'Можете сказать то же самое другими словами?', 'Вот сейчас я совсем вас не понимаю.', 'Попробуйте выразить свою мысль по-другому',])
|
||||
return Response(text = text, voice = voice)
|
||||
|
||||
Command.QA = QA('QA', {}, [])
|
@ -1 +0,0 @@
|
||||
from .QA import *
|
Before Width: | Height: | Size: 337 KiB After Width: | Height: | Size: 337 KiB |
@ -1,6 +0,0 @@
|
||||
import QA
|
||||
import SmallTalk
|
||||
import Media
|
||||
import SmartHome
|
||||
import Raspi
|
||||
import Zieit
|
7
start.py
Normal file
7
start.py
Normal file
@ -0,0 +1,7 @@
|
||||
#!/usr/local/bin/python3.8
|
||||
# entry point
|
||||
|
||||
# TODO:
|
||||
# import subprocess
|
||||
# start oll controls in own thread or subprocess:
|
||||
# voice assistant, telegram bot, django(api and ui)
|
@ -17,5 +17,5 @@ for name, module in modules.items():
|
||||
print(f'[error]\t{name} launch failed')
|
||||
|
||||
print('Running server...')
|
||||
os.system(f'lxterminal --command="python3.8 {config.path}/manage.py runserver 192.168.0.129:8000 & read"')
|
||||
os.system(f'lxterminal --command="python3.8 {config.path}/Controls/Django/manage.py runserver 192.168.0.129:8000 & read"')
|
||||
os.system(f'lxterminal --command="vlc"')
|
@ -1,86 +0,0 @@
|
||||
#!/usr/local/bin/python3.8
|
||||
from Command import Command
|
||||
import Text2Speech
|
||||
import telebot
|
||||
import config
|
||||
import modules
|
||||
import time
|
||||
import os
|
||||
|
||||
threads = []
|
||||
online = True
|
||||
voids = 0
|
||||
memory = []
|
||||
voice = Text2Speech.Engine()
|
||||
bot = telebot.TeleBot(config.telebot)
|
||||
|
||||
def reply(id, response):
|
||||
if response.text:
|
||||
bot.send_message(id, response.text)
|
||||
if response.voice:
|
||||
bot.send_voice(id, voice.generate(response.voice).getBytes() )
|
||||
if response.thread: # add background thread to list
|
||||
response.thread['id'] = id
|
||||
threads.append(response.thread)
|
||||
|
||||
|
||||
def check_threads(threads):
|
||||
for thread in threads:
|
||||
if thread['finish_event'].is_set():
|
||||
response = thread['thread'].join()
|
||||
reply(thread['id'], response)
|
||||
thread['finish_event'].clear()
|
||||
del thread
|
||||
|
||||
def main(id, text):
|
||||
text = text.lower()
|
||||
if Command.isRepeat(text):
|
||||
reply(id, memory[0]['response']);
|
||||
return
|
||||
if memory:
|
||||
response = memory[0]['response']
|
||||
if response.callback:
|
||||
if new_response := response.callback.answer(text):
|
||||
reply(id, new_response)
|
||||
memory.insert(0, {
|
||||
'cmd': response.callback,
|
||||
'params': None,
|
||||
'response': new_response,
|
||||
})
|
||||
return
|
||||
try:
|
||||
cmd, params = memory[0]['cmd'].checkContext(text).values()
|
||||
if memory[0].get('params'): params = {**memory[0].get('params'), **params}
|
||||
except:
|
||||
cmd, params = Command.reg_find(text).values()
|
||||
response = cmd.start(params)
|
||||
reply(id, response)
|
||||
memory.insert(0, {
|
||||
'cmd': cmd,
|
||||
'params': params,
|
||||
'response': response,
|
||||
})
|
||||
|
||||
@bot.message_handler(commands=['vlc', 'queue', 'cmd'])
|
||||
def simple_commands(msg):
|
||||
command = msg.text.replace('/cmd', '').replace('/vlc', 'vlc')
|
||||
if '/queue' in msg.text: command = command.replace('/queue', '') + '--playlist-enqueue'
|
||||
os.system(f'lxterminal --command="{command}"')
|
||||
|
||||
@bot.message_handler(commands=['terminal'])
|
||||
def terminal(msg):
|
||||
command = msg.text.replace('/terminal', '')
|
||||
output = os.popen(command).read()
|
||||
bot.send_message(msg.chat.id, output)
|
||||
|
||||
@bot.message_handler(content_types = ['text'])
|
||||
def execute(msg):
|
||||
main(msg.chat.id, msg.text)
|
||||
|
||||
while True:
|
||||
try:
|
||||
print("Start polling...")
|
||||
bot.polling(callback = check_threads, args = (threads,) )
|
||||
except:
|
||||
time.sleep(10)
|
||||
print("Polling failed")
|
@ -1,137 +0,0 @@
|
||||
#!/usr/local/bin/python3.8
|
||||
import SpeechRecognition
|
||||
import Text2Speech
|
||||
from Command import Command
|
||||
import config
|
||||
import modules
|
||||
import os
|
||||
|
||||
listener = SpeechRecognition.SpeechToText()
|
||||
voice = Text2Speech.Engine()
|
||||
threads = []
|
||||
reports = []
|
||||
memory = []
|
||||
voids = 0
|
||||
|
||||
if config.double_clap_activation:
|
||||
# check double clap from arduino microphone module
|
||||
def checkClap(channel):
|
||||
global lastClapTime
|
||||
global doubleClap
|
||||
now = time.time()
|
||||
delta = now - lastClapTime
|
||||
if 0.1 < delta < 0.6:
|
||||
doubleClap = True
|
||||
else:
|
||||
lastClapTime = now
|
||||
|
||||
# waiting for double clap
|
||||
def sleep():
|
||||
global lastClapTime
|
||||
lastClapTime = 0
|
||||
global doubleClap
|
||||
while not doubleClap:
|
||||
check_threads()
|
||||
time.sleep(1)
|
||||
else:
|
||||
doubleClap = False
|
||||
|
||||
import RPi.GPIO as GPIO
|
||||
import time
|
||||
lastClapTime = 0
|
||||
doubleClap = False
|
||||
GPIO.setmode(GPIO.BCM)
|
||||
GPIO.setup(12, GPIO.IN)
|
||||
GPIO.add_event_detect(12, GPIO.RISING, callback=checkClap)
|
||||
|
||||
def check_threads():
|
||||
for thread in threads:
|
||||
if not thread['finish_event'].is_set(): continue
|
||||
response = thread['thread'].join()
|
||||
reply(response)
|
||||
if response.callback:
|
||||
if response.callback.quiet:
|
||||
response.callback.start()
|
||||
else:
|
||||
for _ in range(3):
|
||||
print('\nYou: ', end='')
|
||||
speech = listener.listen()
|
||||
if speech['status'] == 'ok':
|
||||
print(speech['text'], '\n')
|
||||
new_response = response.callback.answer(speech['text'])
|
||||
reply(new_response)
|
||||
break
|
||||
else:
|
||||
reports.append(response)
|
||||
thread['finish_event'].clear()
|
||||
del thread
|
||||
|
||||
def report():
|
||||
global reports
|
||||
for response in reports:
|
||||
if response.voice:
|
||||
voice.generate(response.voice).speak()
|
||||
time.sleep(2)
|
||||
reports = []
|
||||
|
||||
def reply(response):
|
||||
if response.text: # print answer
|
||||
print('\nArchie: '+response.text)
|
||||
if response.voice: # say answer
|
||||
voice.generate(response.voice).speak()
|
||||
if response.thread: # add background thread to stack
|
||||
threads.append(response.thread)
|
||||
|
||||
def recognize(callback, params):
|
||||
print('\nYou: ', end='')
|
||||
speech = listener.listen()
|
||||
if speech['status'] in ['error', 'void']:
|
||||
return speech
|
||||
text = speech['text']
|
||||
print(text, end='')
|
||||
while True:
|
||||
check_threads()
|
||||
if not callback: break
|
||||
try:
|
||||
if response := callback.answer(text):
|
||||
reply(response)
|
||||
except:
|
||||
break
|
||||
memory.insert(0, {
|
||||
'text': text,
|
||||
'cmd': cmd,
|
||||
'response': response,
|
||||
})
|
||||
speech = recognize(response.callback, params)
|
||||
if callback.once: break
|
||||
return speech
|
||||
|
||||
listener.listen_noise()
|
||||
os.system('clear')
|
||||
|
||||
while True:
|
||||
if voids >= 3:
|
||||
voids = 0
|
||||
if config.double_clap_activation:
|
||||
print('\nSleep (-_-)zzZZ\n')
|
||||
sleep()
|
||||
print('\nYou: ', end='')
|
||||
speech = listener.listen()
|
||||
print(speech.get('text') or '', end='')
|
||||
while True:
|
||||
if speech['status'] == 'error':
|
||||
break
|
||||
if speech['status'] == 'void':
|
||||
voids += 1
|
||||
break
|
||||
text = speech['text']
|
||||
cmd, params = Command.reg_find(text).values()
|
||||
try: response = cmd.start(params)
|
||||
except: break
|
||||
reply(response)
|
||||
check_threads()
|
||||
report()
|
||||
if response.callback:
|
||||
speech = recognize(response.callback, {})
|
||||
else:
|
||||
break
|
Loading…
Reference in New Issue
Block a user