Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions .idea/DollarBot.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

57 changes: 57 additions & 0 deletions code/code.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,12 @@
import monthly
import sendEmail
import add_recurring
import os
import tempfile
import speech_recognition as sr
from datetime import datetime
from jproperties import Properties
from pydub import AudioSegment


configs = Properties()
Expand Down Expand Up @@ -179,6 +183,59 @@ def command_weekly(message):
"""
weekly.run(message, bot)

@bot.message_handler(content_types=['voice'])
def handle_voice(message):
# Get the voice file
file_info = bot.get_file(message.voice.file_id)
downloaded_file = bot.download_file(file_info.file_path)

# Create a temporary OGG file
with tempfile.NamedTemporaryFile(delete=False, suffix='.ogg') as temp_ogg:
temp_ogg.write(downloaded_file)
temp_ogg_path = temp_ogg.name

# Convert OGG to WAV
temp_wav_path = tempfile.NamedTemporaryFile(delete=False, suffix='.wav').name
audio = AudioSegment.from_ogg(temp_ogg_path)
audio.export(temp_wav_path, format='wav')

# Use SpeechRecognition to convert voice to text
recognizer = sr.Recognizer()
with sr.AudioFile(temp_wav_path) as source:
audio_data = recognizer.record(source)
try:
text = recognizer.recognize_google(audio_data)
bot.send_message(message.chat.id, f"I heard: \"{text}\"")
process_command(text, message)
except sr.UnknownValueError:
bot.reply_to(message, "Sorry, I could not understand the audio.")
except sr.RequestError as e:
bot.reply_to(message, "Could not request results from the speech recognition service.")

# Cleanup: remove the temporary files
os.remove(temp_ogg_path)
os.remove(temp_wav_path)

def process_command(text, message):
if "expense" in text:
command_add(message)
elif "history" in text:
command_history(message) # Call the existing history command
elif "budget" in text:
command_budget(message) # Call the existing budget command
elif "menu" in text:
start_and_menu_command(message)
elif "help" in text:
show_help(message)
elif "weekly" in text:
command_weekly(message)
elif "monthly" in text:
command_monthly(message)
elif "predict" in text:
command_predict(message)
else:
bot.send_message(message.chat.id, "I didn't recognize that command.")

# defines how the /monthly command has to be handled/processed
@bot.message_handler(commands=["monthly"])
def command_monthly(message):
Expand Down
4 changes: 4 additions & 0 deletions history.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Date,Category,Amount
02-Oct-2024,Food,$ 12
12-Oct-2024,Groceries,$ 10.0
26-Oct-2024,Food,$ 95.0
Empty file modified run.sh
100644 → 100755
Empty file.
Empty file modified setup.sh
100644 → 100755
Empty file.
Empty file added test/__init__.py
Empty file.
72 changes: 72 additions & 0 deletions test/test_voice.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import unittest
from unittest.mock import patch, MagicMock
import tempfile
import os
from code import handle_voice, process_command

class TestVoiceHandler(unittest.TestCase):

@patch('bot.get_file')
@patch('bot.download_file')
@patch('tempfile.NamedTemporaryFile')
@patch('pydub.AudioSegment.from_ogg')
@patch('speech_recognition.Recognizer')
def test_handle_voice_success(self, MockRecognizer, MockAudioSegment, MockNamedTempFile, MockDownloadFile, MockGetFile):
# Mock file details and download
MockGetFile.return_value.file_path = 'fake_path.ogg'
MockDownloadFile.return_value = b'fake_ogg_data'

# Mock tempfile behavior
temp_ogg = MagicMock()
temp_wav = MagicMock()
MockNamedTempFile.side_effect = [temp_ogg, temp_wav]
temp_ogg.name = 'temp.ogg'
temp_wav.name = 'temp.wav'

# Mock audio conversion
MockAudioSegment.from_ogg.return_value.export = MagicMock()

# Mock speech recognition
recognizer_instance = MockRecognizer.return_value
recognizer_instance.record.return_value = "fake_audio_data"
recognizer_instance.recognize_google.return_value = "this is a test expense"

# Mock process_command function
with patch('process_command') as mock_process_command:
handle_voice(MagicMock()) # Simulate calling the voice handler

# Assertions
MockGetFile.assert_called_once()
MockDownloadFile.assert_called_once()
MockAudioSegment.from_ogg.assert_called_once_with('temp.ogg')
recognizer_instance.recognize_google.assert_called_once()
mock_process_command.assert_called_once_with("this is a test expense", MagicMock())

# Cleanup mocks
os.remove('temp.ogg')
os.remove('temp.wav')

@patch('bot.send_message')
def test_process_command(self, mock_send_message):
message = MagicMock()

# Test different commands
with patch('command_add') as mock_command_add, \
patch('command_history') as mock_command_history, \
patch('command_budget') as mock_command_budget:

process_command("add expense", message)
mock_command_add.assert_called_once_with(message)

process_command("show history", message)
mock_command_history.assert_called_once_with(message)

process_command("set budget", message)
mock_command_budget.assert_called_once_with(message)

# Test unrecognized command
process_command("unknown command", message)
mock_send_message.assert_called_once_with(message.chat.id, "I didn't recognize that command.")

if __name__ == '__main__':
unittest.main()
6 changes: 6 additions & 0 deletions user_limits.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"6365998385": {
"food": 90.0,
"grocery": 70.0
}
}