diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml new file mode 100644 index 0000000..455ba54 --- /dev/null +++ b/.github/workflows/linter.yml @@ -0,0 +1,23 @@ +name: PEP8 Style Guide Enforcement + +on: [push] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up Python 3.10 + uses: actions/setup-python@v2 + with: + python-version: "3.10" + - name: Install Dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + pip install -r emotional_speech_recognizing/requirements.txt + pip install -r silero_demo/requirements.txt + pip install pylint + - name: Run Pylint + run: | + pylint $(git ls-files '*.py') diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 0000000..59f159a --- /dev/null +++ b/.pylintrc @@ -0,0 +1,75 @@ +[BASIC] + +argument-naming-style=snake_case +attr-naming-style=snake_case + +bad-names= + foo, + bar, + baz, + toto, + tutu, + tata + +class-const-naming-style=UPPER_CASE +class-naming-style=PascalCase +const-naming-style=UPPER_CASE +docstring-min-length=-1 +function-naming-style=snake_case +method-naming-style=snake_case +module-naming-style=snake_case +variable-naming-style=snake_case + + +[MESSAGES CONTROL] +disable= + fixme, + missing-module-docstring, + missing-class-docstring, + missing-function-docstring, + consider-using-dict-items, + consider-iterating-dictionary, + too-few-public-methods, + unspecified-encoding, + consider-using-enumerate, + subprocess-run-check, + redefined-outer-name, + no-member, + unused-argument, + protected-access, + duplicate-code, + missing-timeout, + cyclic-import # это сложно поправить быстро + +enable= + import-error, + invalid-name, + unused-import, + missing-final-newline, + line-too-long, + wrong-import-order, + wildcard-import, + trailing-whitespace, + unused-wildcard-import, + trailing-newlines, + redefined-builtin, + singleton-comparison, + unused-variable, + no-else-return, + f-string-without-interpolation, + ungrouped-imports, + too-many-arguments, + consider-using-with, + inconsistent-return-statements, + simplifiable-condition, + reimported, + super-with-arguments + +[FORMAT] +max-line-length=150 +max-module-lines=1000 + +[DESIGN] +max-args=9 +max-branches=12 +max-returns=6 diff --git a/TestPayment/config.py b/TestPayment/config.py index 38d360e..4c1d892 100644 --- a/TestPayment/config.py +++ b/TestPayment/config.py @@ -1,2 +1,2 @@ BOT_TOKEN = '1764779366:AAHPNU-fgWI1PEl_odMuNFMf7E767lHfKC4' -PROVIDER_TOKEN = '401643678:TEST:e1dc6c64-5f3f-4d0d-a7c7-f2f2bea0aa4e' \ No newline at end of file +PROVIDER_TOKEN = '401643678:TEST:e1dc6c64-5f3f-4d0d-a7c7-f2f2bea0aa4e' diff --git a/TestPayment/pay_bot.py b/TestPayment/pay_bot.py index ba9ecad..7a7804a 100644 --- a/TestPayment/pay_bot.py +++ b/TestPayment/pay_bot.py @@ -7,14 +7,13 @@ import logging import config -from telegram import LabeledPrice, ShippingOption, Update +from telegram import LabeledPrice, Update from telegram.ext import ( Updater, CommandHandler, MessageHandler, Filters, PreCheckoutQueryHandler, - ShippingQueryHandler, CallbackContext, ) @@ -37,7 +36,8 @@ def start_without_shipping_callback(update: Update, context: CallbackContext) -> description = "Payment Example using python-telegram-bot" # select a payload just for you to recognize its the donation from your bot payload = "Custom-Payload" - # In order to get a provider_token see https://core.telegram.org/bots/payments#getting-a-token + # In order to get a provider_token see + # https://core.telegram.org/bots/payments#getting-a-token provider_token = config.PROVIDER_TOKEN start_parameter = "test-payment" currency = "RUB" diff --git a/audio_classes.py b/audio_classes.py index 3402792..6f89d83 100644 --- a/audio_classes.py +++ b/audio_classes.py @@ -1,4 +1,3 @@ -import json from dataclasses import dataclass @@ -24,10 +23,16 @@ def __add_word(self, word, start, end, conf): def generate_output_info(self): answer_list = [f"Полученное предложение: \n{self._text}\nСтатистика по сообщению:\n"] for i in self._words: - answer_list.append(f"Слово \"{i.word}\" было сказано в промежутке {i.begin_timestamp} - {i.end_timestamp} с " - f"вероятностью {i.probability}\n") + answer_list.append( + f"Слово \"{i.word}\" было сказано в промежутке {i.begin_timestamp} - {i.end_timestamp} с " + f"вероятностью {i.probability}\n" + ) return "".join(answer_list) def generate_stats(self): - return '\n'.join([f"{i.word} - {i.begin_timestamp} - {i.end_timestamp} - {i.probability}" for i in self._words]) - + return '\n'.join( + [ + f"{i.word} - {i.begin_timestamp} - {i.end_timestamp} - {i.probability}" + for i in self._words + ] + ) diff --git a/docker-compose.yml b/docker-compose.yml index e80c002..841fd21 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,7 +3,7 @@ version: "3" services: db: - image: mongo + image: mongo:6.0 restart: unless-stopped env_file: .env volumes: @@ -22,7 +22,7 @@ services: - db silero-tts-service: - image: "navatusein/silero-tts-service" + image: "navatusein/silero-tts-service:1.0.0" container_name: "silero-tts-service" restart: unless-stopped env_file: .env diff --git a/emotional_speech_recognizing/main.py b/emotional_speech_recognizing/main.py index a2a3ff4..b2ac7ca 100644 --- a/emotional_speech_recognizing/main.py +++ b/emotional_speech_recognizing/main.py @@ -1,20 +1,17 @@ import os +import time import numpy as np + import librosa from sklearn.model_selection import train_test_split -from tensorflow.keras.models import Sequential -from tensorflow.keras.layers import Dense, Dropout -#from tensorflow.keras.optimizers import Adam -from tensorflow.keras.callbacks import EarlyStopping -#from sklearn.preprocessing import LabelEncoder -#from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten -#from tensorflow.keras.layers import LSTM -import time +from keras.models import Sequential +from keras.layers import Dense +from keras.callbacks import EarlyStopping start_time = time.time() # Путь к папке с датасетом -dataset_dir = r'AudioData' +DATASET_DIR = r'AudioData' # Список эмоций и соответствующих меток emotions = {'a': 0, 'd': 1, 'f': 2, 'h': 3, 'n': 4, 'sa': 5, 'su': 6} @@ -26,7 +23,7 @@ # Проход по каждой эмоции в папке датасета for emotion in emotions.keys(): # Путь к папке с эмоцией - emotion_dir = os.path.join(dataset_dir, emotion) + emotion_dir = os.path.join(DATASET_DIR, emotion) # Проход по каждому аудиофайлу в папке с эмоцией for file in os.listdir(emotion_dir): @@ -50,20 +47,27 @@ # Создание модели нейронной сети model = Sequential() model.add(Dense(100, activation='relu', input_shape=(X_train.shape[1],))) -#model.add(Dropout(0.5)) +# model.add(Dropout(0.5)) model.add(Dense(100, activation='relu')) -#model.add(Dense(15, activation='relu')) -#model.add(Dense(120, activation='relu')) -#model.add(Dropout(0.5)) +# model.add(Dense(15, activation='relu')) +# model.add(Dense(120, activation='relu')) +# model.add(Dropout(0.5)) model.add(Dense(len(emotions), activation='softmax')) # Компиляция модели -#model.compile(loss='sparse_categorical_crossentropy', optimizer=Adam(learning_rate=0.001), metrics=['accuracy']) +# model.compile(loss='sparse_categorical_crossentropy', optimizer=Adam(learning_rate=0.001), metrics=['accuracy']) model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy']) # Обучение модели early_stopping = EarlyStopping(monitor='val_loss', patience=10) -model.fit(X_train, y_train, epochs=50, batch_size=1, validation_data=(X_test, y_test), callbacks=[early_stopping]) +model.fit( + X_train, + y_train, + epochs=50, + batch_size=1, + validation_data=(X_test, y_test), + callbacks=[early_stopping], +) # Оценка модели на тестовой выборке loss, accuracy = model.evaluate(X_test, y_test, verbose=0) diff --git a/install_all_requirements.sh b/install_all_requirements.sh new file mode 100755 index 0000000..3ab8969 --- /dev/null +++ b/install_all_requirements.sh @@ -0,0 +1,12 @@ +#! /bin/bash + +# install dependences +pip install -r requirements.txt +pip install -r emotional_speech_recognizing/requirements.txt +pip install -r silero_demo/requirements.txt + +# install pylint (for checking) +pip install pylint + +# install black (for autofix) +pip install black diff --git a/keyboard.py b/keyboard.py index 487eec4..69c4ddf 100644 --- a/keyboard.py +++ b/keyboard.py @@ -8,13 +8,11 @@ 's_22': "22:00 - 23:00", 's_23': "23:00 - 24:00", 's_right_now': "Прямо сейчас", - 'm_fun': "Веселый", 'm_sad': "Грустный", 'm_angry': "Злой", 'm_anxious': "Тревожный", 'm_urgent': "Состояние из ряда вон", - 'f_tired': "Усталость", 'f_self-doubt': "Неуверенность в себе", 'f_bad': "Все плохо", @@ -22,14 +20,12 @@ 'f_apathy': "Апатия", 'f_results': "Обычные итоги", 'f_groundhog': "День сурка", - 'r_yes': "Да", 'r_no': "Нет", 'r_1h': "Ответить через час", - 'menu_change_focus': "Сменить фокус", 'menu_share_event': "Поделиться событием", - 'menu_help': "Справка" + 'menu_help': "Справка", } @@ -38,9 +34,7 @@ def init_button(key) -> InlineKeyboardButton: def ready_keyboard() -> InlineKeyboardMarkup: - keyboard = [ - [init_button('r_yes'), init_button('r_1h')] - ] + keyboard = [[init_button('r_yes'), init_button('r_1h')]] return InlineKeyboardMarkup(keyboard) @@ -52,7 +46,7 @@ def daily_schedule_keyboard() -> InlineKeyboardMarkup: [init_button('s_21')], [init_button('s_22')], [init_button('s_23')], - [init_button('s_right_now')] + [init_button('s_right_now')], ] return InlineKeyboardMarkup(keyboard) @@ -61,7 +55,8 @@ def mood_keyboard() -> InlineKeyboardMarkup: keyboard = [ [init_button('m_fun'), init_button('m_sad')], [init_button('m_angry'), init_button('m_anxious')], - [init_button('m_urgent')], ] + [init_button('m_urgent')], + ] return InlineKeyboardMarkup(keyboard) @@ -74,24 +69,16 @@ def focus_keyboard() -> InlineKeyboardMarkup: [init_button('f_lonely')], [init_button('f_apathy')], [init_button('f_results')], - [init_button('f_groundhog')] - + [init_button('f_groundhog')], ] return InlineKeyboardMarkup(keyboard) def yes_no_keyboard() -> InlineKeyboardMarkup: - keyboard = [ - [init_button('r_yes')], - [init_button('r_no')] - ] + keyboard = [[init_button('r_yes')], [init_button('r_no')]] return InlineKeyboardMarkup(keyboard) def menu_kyeboard() -> ReplyKeyboardMarkup: - keyboard = [ - [VALUES['menu_share_event']], - [VALUES['menu_change_focus']], - [VALUES['menu_help']] - ] - return ReplyKeyboardMarkup(keyboard, one_time_keyboard=True, resize_keyboard=True) \ No newline at end of file + keyboard = [[VALUES['menu_share_event']], [VALUES['menu_change_focus']], [VALUES['menu_help']]] + return ReplyKeyboardMarkup(keyboard, one_time_keyboard=True, resize_keyboard=True) diff --git a/my_cron.py b/my_cron.py index 91893de..0613d52 100644 --- a/my_cron.py +++ b/my_cron.py @@ -9,7 +9,6 @@ from bot import ask_ready, resume_survey from db import get_schedule_list_for_feeling_ask, Schedule, get_users_not_finish_survey -from logs import init_logger MINUTES_FOR_LOOP = 1 diff --git a/requirements.txt b/requirements.txt index dc54eed..e16d67b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -26,4 +26,6 @@ pymodm==0.4.3 pymystem3==0.2.0 cPython==0.0.6 noisereduce==2.0.1 -requests==2.30.0 \ No newline at end of file +requests==2.30.0 +torchaudio==2.0.2 +whisper==1.1.10 \ No newline at end of file diff --git a/run_black.sh b/run_black.sh new file mode 100755 index 0000000..d49a30d --- /dev/null +++ b/run_black.sh @@ -0,0 +1,3 @@ +#! /bin/bash + +black --skip-string-normalization --skip-magic-trailing-comma --line-length=100 . diff --git a/run_pylint.sh b/run_pylint.sh new file mode 100755 index 0000000..6bdebe2 --- /dev/null +++ b/run_pylint.sh @@ -0,0 +1,3 @@ +#! /bin/bash + +pylint $(git ls-files '*.py') diff --git a/run_unittests.sh b/run_unittests.sh old mode 100644 new mode 100755 diff --git a/script_engine.py b/script_engine.py index 796f6f5..6c37422 100644 --- a/script_engine.py +++ b/script_engine.py @@ -1,8 +1,8 @@ import copy import json -import logging -import pytz import datetime + +import pytz from telegram import Update from telegram.ext import CallbackContext from db import init_user, get_survey_progress, init_survey_progress, get_user_answer @@ -32,20 +32,26 @@ class Step: # класс для работы с текущим шагом def __init__(self, update, survey_progress, focus): self.update = update self.survey_progress = survey_progress - self.step_info = Script(Parser("tree_example.json").parse()).get_script(focus)[survey_progress.survey_step] + self.step_info = Script(Parser("tree_example.json").parse()).get_script(focus)[ + survey_progress.survey_step + ] def processing_options(self): next_step = None for option in self.step_info['options']: if option['type'] == 'send_message': - self.update.effective_user.send_message(text=option['text'], ) + self.update.effective_user.send_message(text=option['text']) elif option['type'] == 'get_user_answer': - answer = get_user_answer(init_user(self.update.effective_user), self.step_info['script_name'], - option['step']) + answer = get_user_answer( + init_user(self.update.effective_user), + self.step_info['script_name'], + option['step'], + ) self.update.effective_user.send_message(answer) elif option['type'] == 'inline_keyboard': - self.update.effective_user.send_message(text=option['text'], - reply_markup=yes_no_keyboard()) + self.update.effective_user.send_message( + text=option['text'], reply_markup=yes_no_keyboard() + ) elif option['type'] == 'inline_answer' and self.update.callback_query is not None: if option['answer'] == self.update.callback_query.data: if option['message']['type'] == 'text': @@ -54,8 +60,9 @@ def processing_options(self): with open(option["message"]["source"], 'rb') as stream: self.update.effective_user.send_voice(voice=stream) elif option['message']['type'] == 'inline_keyboard': - self.update.effective_user.send_message(text=option["message"]["text"], - reply_markup=yes_no_keyboard()) + self.update.effective_user.send_message( + text=option["message"]["text"], reply_markup=yes_no_keyboard() + ) next_step = option['next'] elif option['type'] == 'send_voice': @@ -64,9 +71,9 @@ def processing_options(self): return next_step def execute(self) -> str: - next = self.processing_options() - if next is not None: - self.survey_progress.survey_next = next + survey_next = self.processing_options() + if survey_next is not None: + self.survey_progress.survey_next = survey_next self.survey_progress.time_send_question = pytz.utc.localize(datetime.datetime.utcnow()) self.survey_progress.need_answer = self.step_info['need_answer'] self.survey_progress.save() @@ -85,8 +92,12 @@ def get_next_step(self) -> Step: step_number = self.survey_progress.survey_step if self.update.callback_query is not None: self.update.callback_query.delete_message() - if self.survey_progress.need_answer == True and self.survey_progress.user_answer == "INIT PROGRESS" and \ - self.survey_progress.time_send_question+datetime.timedelta(days=0, seconds=7200) < datetime.datetime.utcnow(): + if ( + self.survey_progress.need_answer + and self.survey_progress.user_answer == "INIT PROGRESS" + and self.survey_progress.time_send_question + datetime.timedelta(hours=2) + < datetime.datetime.utcnow() + ): step = Step(self.update, self.survey_progress, self.last_focus) if self.update.callback_query is not None: query = self.update.callback_query @@ -111,7 +122,11 @@ def get_next_step(self) -> Step: self.survey_progress.save() step_number = self.survey_progress.survey_next # Генерация нового - new_step_info = Script(Parser("tree_example.json").parse()).get_script(self.last_focus)[step_number] - new_survey_progress = init_survey_progress(self.user, self.last_focus, self.update.update_id, step_number, new_step_info['next']) + new_step_info = Script(Parser("tree_example.json").parse()).get_script(self.last_focus)[ + step_number + ] + new_survey_progress = init_survey_progress( + self.user, self.last_focus, self.update.update_id, step_number, new_step_info['next'] + ) next_step = Step(self.update, new_survey_progress, self.last_focus) return next_step diff --git a/silero_demo/bot.py b/silero_demo/bot.py index de4860f..f038d5c 100644 --- a/silero_demo/bot.py +++ b/silero_demo/bot.py @@ -1,29 +1,26 @@ import sys -import os from telegram import Update -from telegram.ext import ( - Updater, - CommandHandler, - MessageHandler, - Filters, - CallbackContext, -) - -from silero_test import * +from telegram.ext import Updater, CommandHandler, MessageHandler, Filters, CallbackContext + +from silero_test import silero_test + + def start_callback(update: Update, context: CallbackContext) -> None: msg = "Отправь мне сообщение" update.message.reply_text(msg) + def send_audio_answer_text(update: Update, context: CallbackContext): audio = silero_test(handle_text(update, context)) - with open(audio, 'rb') as f: - update.effective_user.send_audio(f) + with open(audio, 'rb') as file_: + update.effective_user.send_audio(file_) + def send_audio_answer_voice(update: Update, context: CallbackContext): audio = silero_test() - with open(audio, 'rb') as f: - update.effective_user.send_audio(f) + with open(audio, 'rb') as file_: + update.effective_user.send_audio(file_) def handle_text(update: Update, context: CallbackContext): @@ -49,7 +46,6 @@ def main(token, mode): elif mode == 'voice': dispatcher.add_handler(MessageHandler(Filters.voice, send_audio_answer_voice)) - # Start the Bot updater.start_polling() @@ -61,4 +57,4 @@ def main(token, mode): if __name__ == '__main__': main(sys.argv[1], sys.argv[2]) - # main(config.BOT_TOKEN) \ No newline at end of file + # main(config.BOT_TOKEN) diff --git a/silero_demo/silero_test.py b/silero_demo/silero_test.py index b4e54c5..d93a6ea 100644 --- a/silero_demo/silero_test.py +++ b/silero_demo/silero_test.py @@ -1,20 +1,22 @@ +import re + import torch -import time -import sounddevice as sd import torchaudio -import re -language = 'ru' -model_id = 'v3_1_ru' -sample_rate = 48000 -speaker = 'baya' -device = torch.device('cpu') -example_text = "Привет. я бот-психолог" +LANGUAGE = 'ru' +MODEL_ID = 'v3_1_ru' +SAMPLE_RATE = 48000 +SPEAKER = 'baya' +DEVICE = torch.device('cpu') +EXAMPLE_TEXT = "Привет. я бот-психолог" + def add_intonation(text, words, intonation_parameters): text = text.lower() for word in words: - text = text.replace(word, f"<{' '.join(intonation_parameters)}>" + word + f"") + text = text.replace( + word, f"<{' '.join(intonation_parameters)}>" + word + f"" + ) return text @@ -26,22 +28,22 @@ def reformat_text(text): text = "" + '\n'.join(paragraphs) + "" return text -def silero_test(text=example_text): - model, _ = torch.hub.load(repo_or_dir='snakers4/silero-models', - model='silero_tts', - language=language, - speaker=model_id) - model.to(device) # gpu or cpu + +def silero_test(text=EXAMPLE_TEXT): + model, _ = torch.hub.load( + repo_or_dir='snakers4/silero-models', + model='silero_tts', + language=LANGUAGE, + speaker=MODEL_ID, + ) + + model.to(DEVICE) # gpu or cpu text = reformat_text(text) text = add_intonation(text, ["привет"], ['prosody', 'pitch="x-high" rate="x-slow"']) text = add_intonation(text, ["пока"], ['prosody', 'pitch="x-low" rate="x-fast"']) - audio = model.apply_tts(ssml_text=text, - speaker=speaker, - sample_rate=sample_rate) + audio = model.apply_tts(ssml_text=text, speaker=SPEAKER, sample_rate=SAMPLE_RATE) filename = 'test_1.wav' - torchaudio.save(filename, - audio.unsqueeze(0), - sample_rate=sample_rate) + torchaudio.save(filename, audio.unsqueeze(0), sample_rate=SAMPLE_RATE) return filename diff --git a/silero_module.py b/silero_module.py index 8844d2c..0713068 100644 --- a/silero_module.py +++ b/silero_module.py @@ -1,6 +1,5 @@ import os import requests -import time class VoiceSettings: @@ -12,7 +11,6 @@ class VoiceSettings: def bot_answer_audio(bot_text): - request_params = {'VOICE': VoiceSettings.speaker, 'INPUT_TEXT': bot_text} try: answer = requests.get(VoiceSettings.link + '/process', params=request_params) diff --git a/test_script_engine.py b/test_script_engine.py index 7285c7d..4b1ae45 100644 --- a/test_script_engine.py +++ b/test_script_engine.py @@ -2,46 +2,81 @@ from unittest import mock from json.decoder import JSONDecodeError import sys -from telegram import Update -import pytz -import datetime -from db import User, SurveyProgress, init_user, init_survey_progress -from script_engine import Script, Parser, Step from pymodm import connect +from db import User, init_user, init_survey_progress +from script_engine import Script, Parser, Step -class TestScript(unittest.TestCase): +class TestScript(unittest.TestCase): def test_get_script(self): - self.assertEqual(Script({'f_tired': {'script_body': [{'script_name': 'f_tired', 'options': - [{'type': 'send_message', 'text': 'message'}]}, {'script_name': 'f_tired', - 'id': 'tired_0.1'}]}}).get_script('f_tired'), [ - {'script_name': 'f_tired', 'options': [{'type': 'send_message', 'text': 'message'}]}, - {'script_name': 'f_tired', 'id': 'tired_0.1'}]) - self.assertRaises(KeyError, Script({'f_tired': {'script_body': [{'script_name': 'f_tired', 'options': - [{'type': 'send_message', 'text': 'message'}]}, {'script_name': 'f_tired', - 'id': 'tired_0.1'}]}}).get_script('ff_tired')) + self.assertEqual( + Script( + { + 'f_tired': { + 'script_body': [ + { + 'script_name': 'f_tired', + 'options': [{'type': 'send_message', 'text': 'message'}], + }, + {'script_name': 'f_tired', 'id': 'tired_0.1'}, + ] + } + } + ).get_script('f_tired'), + [ + { + 'script_name': 'f_tired', + 'options': [{'type': 'send_message', 'text': 'message'}], + }, + {'script_name': 'f_tired', 'id': 'tired_0.1'}, + ], + ) + self.assertRaises( + KeyError, + Script( + { + 'f_tired': { + 'script_body': [ + { + 'script_name': 'f_tired', + 'options': [{'type': 'send_message', 'text': 'message'}], + }, + {'script_name': 'f_tired', 'id': 'tired_0.1'}, + ] + } + } + ).get_script('ff_tired'), + ) class TestParser(unittest.TestCase): - def test_parse(self): - self.assertEqual(Parser("test_tree.json").parse(), - {'f_tired': {'script_body': [{'script_name': 'f_tired', 'options': - [{'type': 'send_message', 'text': 'message'}]}, - {'script_name': 'f_tired', 'id': 'tired_0.1'}]}}) + self.assertEqual( + Parser("test_tree.json").parse(), + { + 'f_tired': { + 'script_body': [ + { + 'script_name': 'f_tired', + 'options': [{'type': 'send_message', 'text': 'message'}], + }, + {'script_name': 'f_tired', 'id': 'tired_0.1'}, + ] + } + }, + ) self.assertRaises(FileNotFoundError, Parser("test_treee.json").parse()) self.assertRaises(JSONDecodeError, Parser("test_broken_tree.json").parse()) class TestStep(unittest.TestCase): - @mock.patch('telegram.Update') @mock.patch('telegram.User') - def test_processing_options(self, MockUser, MockUpdate): - update = MockUpdate() - update.effective_user = MockUser() + def test_processing_options(self, mock_user, mock_update): + update = mock_update() + update.effective_user = mock_user() update.effective_user.send_message.return_value = [] update.callback_query.data = 'r_yes' user = init_user(User(**{'id': 681004065})) @@ -52,9 +87,9 @@ def test_processing_options(self, MockUser, MockUpdate): @mock.patch('telegram.Update') @mock.patch('telegram.User') - def test_execute(self, MockUser, MockUpdate): - update = MockUpdate() - update.effective_user = MockUser() + def test_execute(self, mock_user, mock_update): + update = mock_update() + update.effective_user = mock_user() update.effective_user.send_message.return_value = [] user = init_user(User(**{'id': 681004065})) focus = 'f_tired' @@ -64,7 +99,7 @@ def test_execute(self, MockUser, MockUpdate): if __name__ == '__main__': - db_address = sys.argv[1] + db_address = sys.argv[1] # pylint: disable=invalid-name connect(db_address) res = unittest.main(argv=['first-arg-is-ignored'], exit=False) sys.exit(int(not res.result.wasSuccessful())) diff --git a/voice_module.py b/voice_module.py index 085289a..e95dd05 100644 --- a/voice_module.py +++ b/voice_module.py @@ -1,7 +1,6 @@ import json import os import subprocess -import wave from noisereduce import reduce_noise from scipy.io import wavfile @@ -34,8 +33,9 @@ def download_voice(update: Update): ogg_filename += f"/{downloaded_file.file_unique_id}.ogg" with open(ogg_filename, "wb") as voice_file: voice_file.write(voice_bytearray) - wav_filename = ogg_filename.split(".")[0]+".wav" - command = f"ffmpeg -i {ogg_filename} -ar 16000 -ac 1 -ab 256K -f wav {wav_filename}" #16000 - частота дискретизации, 1 - кол-во аудиоканалов, 256К - битрейт + wav_filename = ogg_filename.split(".")[0] + ".wav" + # 16000 - частота дискретизации, 1 - кол-во аудиоканалов, 256К - битрейт + command = f"ffmpeg -i {ogg_filename} -ar 16000 -ac 1 -ab 256K -f wav {wav_filename}" subprocess.run(command.split()) return (wav_filename, ogg_filename) @@ -58,8 +58,18 @@ def work_with_audio(update: Update, context: CallbackContext): update.effective_user.send_message(input_sentence.generate_output_info()) elif debug == "false": pass - push_user_survey_progress(update.effective_user, init_user(update.effective_user).focuses[-1]['focus'], update.update_id, user_answer=input_sentence._text, stats=stats_sentence, audio_file=open(ogg_filename, 'rb')) + push_user_survey_progress( + update.effective_user, + init_user(update.effective_user).focuses[-1]['focus'], + update.update_id, + user_answer=input_sentence._text, + stats=stats_sentence, + audio_file=open(ogg_filename, 'rb'), # pylint: disable=consider-using-with + ) os.remove(ogg_filename) if debug == "true": print(get_user_audio(update.effective_user)) - update.effective_user.send_message("ID записи с твоим аудиосообщением в базе данных: " + str(json.loads(json_util.dumps(get_user_audio(update.effective_user))))) + update.effective_user.send_message( + "ID записи с твоим аудиосообщением в базе данных: " + + str(json.loads(json_util.dumps(get_user_audio(update.effective_user)))) + )