From 8131b046b23f49c13d2e9e4ea23720c88112cb68 Mon Sep 17 00:00:00 2001 From: Mathieu B Date: Mon, 26 Jul 2021 18:23:32 +0200 Subject: [PATCH] Base --- .gitignore | 138 ++++++++++++++++++++ config/config.json | 10 ++ get_path_file.py | 1 + intents/__init__.py | 0 intents/daily/date_and_time/info.json | 6 + intents/daily/date_and_time/intent.py | 13 ++ intents/daily/date_and_time/lang/en-en.json | 27 ++++ intents/daily/date_and_time/lang/fr-fr.json | 26 ++++ intents/intents.py | 38 ++++++ main.py | 23 ++++ requirements.txt | 1 + utils/__init__.py | 0 utils/config_utils.py | 29 ++++ utils/flask_utils.py | 16 +++ utils/intents_utils.py | 50 +++++++ 15 files changed, 378 insertions(+) create mode 100644 .gitignore create mode 100644 config/config.json create mode 100644 get_path_file.py create mode 100644 intents/__init__.py create mode 100644 intents/daily/date_and_time/info.json create mode 100644 intents/daily/date_and_time/intent.py create mode 100644 intents/daily/date_and_time/lang/en-en.json create mode 100644 intents/daily/date_and_time/lang/fr-fr.json create mode 100644 intents/intents.py create mode 100644 main.py create mode 100644 requirements.txt create mode 100644 utils/__init__.py create mode 100644 utils/config_utils.py create mode 100644 utils/flask_utils.py create mode 100644 utils/intents_utils.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..deefc5c --- /dev/null +++ b/.gitignore @@ -0,0 +1,138 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +.idea +.idea/** +.idea/* + +# C extensions +*.so + + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + + +/ffmpeg/ +/config/secrets.json diff --git a/config/config.json b/config/config.json new file mode 100644 index 0000000..0c6a21c --- /dev/null +++ b/config/config.json @@ -0,0 +1,10 @@ +{ + "HOMEASSISTANT_API_TOKEN": "!secret HOMEASSISTANT_API_TOKEN", + "HOMEASSISTANT_API_URL": "!secret HOMEASSISTANT_API_URL", + "API_KEY": "!secret API_KEY", + "SPOTIFY_CLIENT_ID": "!secret SPOTIFY_CLIENT_ID", + "SPOTIFY_CLIENT_SECRET": "!secret SPOTIFY_CLIENT_SECRET", + "PORT": 5000, + "CLIENT_URL": "http://127.0.0.1:5001", + "TRAIN_ON_START": false +} diff --git a/get_path_file.py b/get_path_file.py new file mode 100644 index 0000000..0db5649 --- /dev/null +++ b/get_path_file.py @@ -0,0 +1 @@ +# THIS FILE DOESN'T DO ANYTHING EXCEPT GIVE THE PROJECT MAIN PATH (i'm listening for better ideas) diff --git a/intents/__init__.py b/intents/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/intents/daily/date_and_time/info.json b/intents/daily/date_and_time/info.json new file mode 100644 index 0000000..10063ca --- /dev/null +++ b/intents/daily/date_and_time/info.json @@ -0,0 +1,6 @@ +{ + "name": "Date and Time", + "languages": ["FR-FR", "EN-EN"], + "intents": ["what_time_is_it", "what_day_is_it"], + "variables": ["time", "day"] +} \ No newline at end of file diff --git a/intents/daily/date_and_time/intent.py b/intents/daily/date_and_time/intent.py new file mode 100644 index 0000000..3007ec2 --- /dev/null +++ b/intents/daily/date_and_time/intent.py @@ -0,0 +1,13 @@ +import utils.intents_utils + + +def what_time_is_it(): + return "" + + +def what_day_is_it(): + return "" + + +if __name__ == '__main__': + print(utils.intents_utils.get_response("what_time_is_it")) diff --git a/intents/daily/date_and_time/lang/en-en.json b/intents/daily/date_and_time/lang/en-en.json new file mode 100644 index 0000000..2657320 --- /dev/null +++ b/intents/daily/date_and_time/lang/en-en.json @@ -0,0 +1,27 @@ +{ + "what_time_is_it": { + "patterns": [ + "What time is it", + "Show me the time", + "Tell me the time", + "What's the time", + "What is the time" + ], + "responses": [ + "It is {time}", + "It's {time} right now", + "The time is {time}" + ] + }, + "what_day_is_it": { + "patterns": [ + "What's the day", + "Tell me the day of the week. ", + "What day are we" + ], + "response": [ + "{day}", + "Today is {day}" + ] + } +} \ No newline at end of file diff --git a/intents/daily/date_and_time/lang/fr-fr.json b/intents/daily/date_and_time/lang/fr-fr.json new file mode 100644 index 0000000..0bb1442 --- /dev/null +++ b/intents/daily/date_and_time/lang/fr-fr.json @@ -0,0 +1,26 @@ +{ + "what_time_is_it": { + "patterns": [ + "Il est quelle heure", + "C'est quelle heure", + "On vit quelle heure", + "Quelle heure est-il" + ], + "responses": [ + "Il est {time}", + "Il est actuellement {time}" + ] + }, + "what_day_is_it": { + "patterns": [ + "On est quel jour", + "Quel jour est-on", + "C'est quel jour aujourd'hui" + ], + "response": [ + "Nous somme le {day}", + "Aujourd'hui nous sommes {day}", + "On est {day}" + ] + } +} \ No newline at end of file diff --git a/intents/intents.py b/intents/intents.py new file mode 100644 index 0000000..0fbc089 --- /dev/null +++ b/intents/intents.py @@ -0,0 +1,38 @@ +import glob +import json +import os + +import get_path_file + +intents = dict() +path = os.path.dirname(get_path_file.__file__) + + +def register_all_intents(): + global intents + + result = {} + + files = glob.glob(path + "/intents/**/info.json", recursive=True) + for f in files: + with open(f, "rb") as infile: + intent_info_json = json.load(infile) + intents_in_info = intent_info_json['intents'] + intent_path = str(f).replace('info.json', '') + + for intent in intents_in_info: + result[intent] = intent_path + + intents = result + + +def get_all_intents(): + if len(intents) >= 1: + return intents + else: + register_all_intents() + return get_all_intents() + + +if __name__ == '__main__': + print(get_all_intents()) diff --git a/main.py b/main.py new file mode 100644 index 0000000..2f496dc --- /dev/null +++ b/main.py @@ -0,0 +1,23 @@ +import flask +from flask import Flask, request, jsonify, Response + +from utils import config_utils, flask_utils + +app = Flask(__name__) + + +@app.route("/process", methods=['POST']) +def process_request(): + data = flask_utils.get_data_in_request(request) + + if 'sentence' not in data: + flask.abort(Response('You must provide a \'sentence\' parameter!')) + + print(data) + return jsonify(data) + + +if __name__ == '__main__': + # start the flask server + app.config['JSON_AS_ASCII'] = False + app.run(port=config_utils.get_in_config("PORT"), debug=False, host='0.0.0.0', threaded=True) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..7e10602 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +flask diff --git a/utils/__init__.py b/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/utils/config_utils.py b/utils/config_utils.py new file mode 100644 index 0000000..cd80f0a --- /dev/null +++ b/utils/config_utils.py @@ -0,0 +1,29 @@ +import json +import os + +import get_path_file + +path = os.path.dirname(get_path_file.__file__) + + +def get_in_config(name): + config_json = json.load(open(path + "/config/config.json", encoding='utf-8', mode='r')) + if name in config_json: + if isinstance(config_json.get(name), str): + if "!secret" in config_json.get(name): + # secret_name = config_json.get(name).removeprefix('!secret ') + secret_name = config_json.get(name).replace('!secret ', '') + return get_in_secret(secret_name) + else: + return config_json.get(name) + else: + return config_json.get(name) + + +def get_in_secret(secret_name): + secrets_json = json.load(open(path + "/config/secrets.json", encoding='utf-8', mode='r')) + + if secret_name in secrets_json: + return secrets_json.get(secret_name) + else: + return "Not found!" diff --git a/utils/flask_utils.py b/utils/flask_utils.py new file mode 100644 index 0000000..a5e8c8f --- /dev/null +++ b/utils/flask_utils.py @@ -0,0 +1,16 @@ +import json + + +def get_data_in_request(request): + data_str = str(request.data.decode('utf8')).replace('"', '\"').replace("\'", "'") + + # if no data return an empty json to avoid error with json.loads below + if not data_str: + return {} + + data_json = json.loads(data_str) + + if not isinstance(data_json, dict): + data_json = json.loads(data_json) + + return data_json diff --git a/utils/intents_utils.py b/utils/intents_utils.py new file mode 100644 index 0000000..bde8c2e --- /dev/null +++ b/utils/intents_utils.py @@ -0,0 +1,50 @@ +import json +import os +import random + +import intents.intents + + +def get_patterns(intent_tag): + if exists(intent_tag): + patterns = get_lang_for_intent(intent_tag).get(intent_tag).get('patterns') + return patterns + else: + return {} + + +def get_responses(intent_tag): + if exists(intent_tag): + responses = get_lang_for_intent(intent_tag).get(intent_tag).get('responses') + return responses + else: + return {} + + +def get_response(intent_tag): + if exists(intent_tag): + responses = get_responses(intent_tag) + return random.choice(responses) + + +def get_lang_for_intent(intent_tag): + language = "fr-fr" # TODO: use config value + + # first we check the intent + if exists(intent_tag): + lang_path = str(intents.intents.get_all_intents().get(intent_tag)) + lang_path = lang_path + 'lang/' + language + '.json' + + if os.path.exists(lang_path): + lang_file = open(lang_path) + json_lang = json.load(lang_file) + return json_lang + else: + return {} + + +def exists(intent_tag): + if intent_tag in intents.intents.get_all_intents(): + return True + else: + return False