Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
bb84680
Added voice recognition feature
Oct 26, 2024
cb21311
Added test cases for handle_voice
Oct 26, 2024
fc8ffe6
Added more commands that can handle voice
Oct 26, 2024
7c791b2
Updated show help view
Oct 26, 2024
d705421
Improved menu display in start_and_menu_command using Inline keyboard…
Oct 26, 2024
ceda293
Added command handling for different user interactions with buttons
Oct 26, 2024
9c8fec2
Fixed UnboundLocalError in callback_query_handler
Oct 26, 2024
782b494
Added faq to command list in callback_query
Oct 26, 2024
e33563f
Added voice recognition feature
Oct 26, 2024
3481a95
Added test cases for handle_voice
Oct 26, 2024
eab7253
Added more commands that can handle voice
Oct 26, 2024
2f3062d
Added command handling for different user interactions with buttons
Oct 26, 2024
bbc1b61
Merge branch 'main' into UI-enhancement
madhumithaaravelli Oct 27, 2024
3ad53db
Merge pull request #6 from CSC510-SE-SAITEJA-MADHUMITHA-SHRUTI/UI-enh…
madhumithaaravelli Oct 27, 2024
e7a4d9c
Fixed pylint error and other bugs
Oct 27, 2024
1095cf3
Merge pull request #8 from CSC510-SE-SAITEJA-MADHUMITHA-SHRUTI/pylint…
madhumithaaravelli Oct 27, 2024
3c2f1e2
Update pylintrc to fix warnings related to overgeneral exceptions and…
Oct 27, 2024
db7779e
Added custom exceptions in exceptions.py to fix broad_exception_raise…
Oct 27, 2024
8b43c50
Fixed broad-exception-raised warnings by replacing generic Exception …
Oct 27, 2024
a1982fe
Merge pull request #9 from CSC510-SE-SAITEJA-MADHUMITHA-SHRUTI/pylint…
madhumithaaravelli Oct 27, 2024
4b464b7
Fix: Refactor bot access in add.py
Oct 27, 2024
0e974ae
Merge pull request #12 from CSC510-SE-SAITEJA-MADHUMITHA-SHRUTI/pylin…
madhumithaaravelli Oct 27, 2024
8c91628
Fixed test cases in test_voice
Oct 27, 2024
0313f92
Added test_Cases for process_command
Oct 27, 2024
1da409b
Merge pull request #13 from CSC510-SE-SAITEJA-MADHUMITHA-SHRUTI/pylin…
madhumithaaravelli Oct 27, 2024
07bff84
Updated workflow to include pandas and manage dependencies
Oct 27, 2024
0ef0be0
Added speech_recognition module to requirements.txt
Oct 27, 2024
692f452
updated speech_recognition module to requirements.txt
Oct 27, 2024
aff1e7c
Added pydub module to requirements
Oct 27, 2024
5b2cdb1
Refactor voice command processing and update tests accordingly
Oct 27, 2024
7c0889f
remove unused import
Oct 27, 2024
3baa6f6
Merge pull request #14 from CSC510-SE-SAITEJA-MADHUMITHA-SHRUTI/pylin…
madhumithaaravelli Oct 27, 2024
0831168
Fixed bugs in voice.py and add.py
Oct 27, 2024
e90846f
Merge pull request #15 from CSC510-SE-SAITEJA-MADHUMITHA-SHRUTI/pylin…
madhumithaaravelli Oct 27, 2024
8dc84c4
updated code.py
labbasaiteja Oct 29, 2024
2e3243d
update helper.py
labbasaiteja Oct 29, 2024
7f47eec
updated pdf.py
labbasaiteja Oct 29, 2024
f5022ca
updated and fixed
labbasaiteja Oct 29, 2024
094ce37
added test case for invalid date
labbasaiteja Oct 29, 2024
16087b6
fixed bad request in code.py
labbasaiteja Oct 31, 2024
e81cc0f
fixed callback query
labbasaiteja Oct 31, 2024
ae91694
improved message
labbasaiteja Oct 31, 2024
84c170e
improved
labbasaiteja Oct 31, 2024
954430a
Fixed dispaly_total func
labbasaiteja Oct 31, 2024
b5a21c4
added test cases for add.py
labbasaiteja Oct 31, 2024
046a02f
Enhanced Budget view
labbasaiteja Oct 31, 2024
e830a15
added test cases
labbasaiteja Oct 31, 2024
27a905f
fixed error handling
labbasaiteja Oct 31, 2024
02c195f
updated rubric data
labbasaiteja Nov 1, 2024
2e456ca
Fixed calculateRemainingCategoryBudget
labbasaiteja Nov 1, 2024
dc54bda
updated workfloe
labbasaiteja Nov 2, 2024
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
13 changes: 9 additions & 4 deletions .github/workflows/python-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ name: Python application

on:
push:
branches: [ "main" ]
branches: [ "feature/summary-report-sociallink" ]
pull_request:
branches: [ "main" ]

Expand All @@ -14,36 +14,41 @@ permissions:

jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Set up Python 3.10
uses: actions/setup-python@v3
with:
python-version: "3.10"

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8 pytest
pip install flake8 pytest coverage pandas # Added pandas directly here
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi

- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics

- name: Install pylint
run: |
pip install pylint

- name: Run pylint
run: |
pylint -r y code/

- name: Test with pytest
run: |
pip install coverage
coverage run -m pytest test/

- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v3
with:
Expand Down
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.

4 changes: 3 additions & 1 deletion categories.json
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
{ "categories" : "Food,Groceries,Utilities,Transport,Shopping,Miscellaneous" }
{
"categories": "Food,Groceries,Utilities,Transport,Shopping,Miscellaneous,miscelleneous"
}
13 changes: 12 additions & 1 deletion code/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,18 @@
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""

import os
import sys
from your_telegram_bot_module import bot # Replace with your actual bot import

def main():
try:
bot.polling(non_stop=True)
except Exception as e:
print(f"An error occurred: {e}")

sys.path.insert(0, os.getcwd() + "/code")
if __name__ == "__main__":
# Optionally, you could manage your project structure here
sys.path.insert(0, os.path.join(os.getcwd(), "code"))
main()
54 changes: 30 additions & 24 deletions code/add.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""

import helper
import logging
from telebot import types
from telegram_bot_calendar import DetailedTelegramCalendar, LSTEP
from helper import display_remaining_budget
from datetime import datetime
from exception import InvalidAmountError, InvalidCategoryError

option = {}

Expand All @@ -50,24 +51,24 @@ def run(message, bot):
calendar, step = DetailedTelegramCalendar().build()
bot.send_message(chat_id, f"Select {LSTEP[step]}", reply_markup=calendar)

@bot.callback_query_handler(func=DetailedTelegramCalendar.func())
def cal(c):
chat_id = c.message.chat.id
result, key, step = DetailedTelegramCalendar().process(c.data)

if not result and key:
bot.edit_message_text(
f"Select {LSTEP[step]}",
chat_id,
c.message.message_id,
reply_markup=key,
)
elif result:
data = datetime.today().date()
if (result > data):
bot.send_message(chat_id,"Cannot select future dates, Please try /add command again with correct dates")
else:
category_selection(message,bot,result)

def cal(c,bot):
chat_id = c.message.chat.id
result, key, step = DetailedTelegramCalendar().process(c.data)

if not result and key:
bot.edit_message_text(
f"Select {LSTEP[step]}",
chat_id,
c.message.message_id,
reply_markup=key,
)
elif result:
data = datetime.today().date()
if (result > data):
bot.send_message(chat_id,"Cannot select future dates, Please try /add command again with correct dates")
else:
category_selection(c.message,bot,result)

def category_selection(msg,bot,date):
"""
Expand Down Expand Up @@ -113,9 +114,7 @@ def post_category_selection(message, bot, date):
bot.send_message(
chat_id, "Invalid", reply_markup=types.ReplyKeyboardRemove()
)
raise Exception(
'Sorry, I don\'t recognise this category "{}"!'.format(selected_category)
)
raise InvalidCategoryError(selected_category, "I don’t recognize this category")
option[chat_id] = selected_category
message = bot.send_message(
chat_id, "How much did you spend on {}? \n(Numeric values only)".format(str(option[chat_id])),)
Expand Down Expand Up @@ -147,7 +146,7 @@ def post_amount_input(message, bot, selected_category, date):
amount_entered = message.text
amount_value = helper.validate_entered_amount(amount_entered) # validate
if amount_value == 0: # cannot be $0 spending
raise Exception("Spent amount has to be a non-zero number.")
raise InvalidAmountError("Spent amount has to be a non-zero number.")

date_of_entry = date.strftime(helper.getDateFormat())
date_str, category_str, amount_str = (
Expand All @@ -166,7 +165,8 @@ def post_amount_input(message, bot, selected_category, date):
amount_str, category_str, date_str
),
)
helper.display_remaining_budget(message, bot)
helper.display_remaining_budget(message, bot, selected_category) # Use 'selected_category' instead of 'cat'

except Exception as e:
logging.exception(str(e))
bot.send_message(chat_id, "Oh no. " + str(e))
Expand All @@ -178,6 +178,12 @@ def add_user_record(chat_id, record_to_be_added):
is the expense record to be added to the store. It then stores this expense record in the store.
"""
user_list = helper.read_json()
print(f"user_list before addition: {user_list}") # Debug output

# Ensure user_list is initialized properly
if user_list is None:
user_list = {} # Initialize as empty dictionary if read_json returned None

if str(chat_id) not in user_list:
user_list[str(chat_id)] = helper.createNewUserRecord()

Expand Down
8 changes: 4 additions & 4 deletions code/add_recurring.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
from telebot import types
from datetime import datetime
from dateutil.relativedelta import relativedelta

from exception import InvalidCategoryError, InvalidAmountError, InvalidDurationError

option = {}

Expand Down Expand Up @@ -73,7 +73,7 @@ def post_category_selection(message, bot):
selected_category = message.text
if selected_category not in helper.getSpendCategories():
bot.send_message(chat_id, 'Invalid', reply_markup=types.ReplyKeyboardRemove())
raise Exception("Sorry I don't recognise this category \"{}\"!".format(selected_category))
raise InvalidCategoryError(selected_category, "I don’t recognize this category")

option[chat_id] = selected_category
message = bot.send_message(chat_id, 'How much did you spend on {}? \n(Enter numeric values only)'.format(str(option[chat_id])))
Expand Down Expand Up @@ -107,7 +107,7 @@ def post_amount_input(message, bot, selected_category):
amount_entered = message.text
amount_value = helper.validate_entered_amount(amount_entered) # validate
if amount_value == 0: # cannot be $0 spending
raise Exception("Spent amount has to be a non-zero number.")
raise InvalidAmountError("Spent amount has to be a non-zero number.")

message = bot.send_message(chat_id, 'For how many months in the future will the expense be there? \n(Enter integer values only)')
bot.register_next_step_handler(message, post_duration_input, bot, selected_category, amount_value)
Expand Down Expand Up @@ -135,7 +135,7 @@ def post_duration_input(message, bot, selected_category, amount_value):
duration_entered = message.text
duration_value = helper.validate_entered_duration(duration_entered)
if duration_value == 0:
raise Exception("Duration has to be a non-zero integer.")
raise InvalidDurationError("Duration has to be a non-zero integer.")

for i in range(int(duration_value)):
date_of_entry = (datetime.today().date() + relativedelta(months=+i)).strftime(helper.getDateFormat())
Expand Down
66 changes: 44 additions & 22 deletions code/analytics.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import logging
from telebot import types
import get_analysis
from exception import InvalidOperationError

def run(message, bot):
"""
Expand All @@ -45,30 +46,51 @@ def run(message, bot):
markup.add(c)
msg = bot.reply_to(message, "Select the type of analysis (grouped by category):", reply_markup=markup)
bot.register_next_step_handler(msg, post_operation_selection, bot)

def post_operation_selection(message, bot):
"""
post_operation_selection(message, bot): It takes 2 arguments for processing - message which
is the message from the user, and bot which is the telegram bot object from the
run(message, bot): function in the analytics.py file. Depending on the action chosen by the user,
it passes on control to the corresponding functions which are all located in different files.
post_operation_selection(message, bot): Processes user-selected operations and
invokes corresponding analysis functions.

Args:
message: The message object containing user input.
bot: The Telegram bot object for sending messages.
"""
chat_id = message.chat.id
op = message.text
options = helper.getAnalyticsOptions()

try:
chat_id = message.chat.id
op = message.text
options = helper.getAnalyticsOptions()
if op not in options.values():
bot.send_message(
chat_id, "Invalid", reply_markup=types.ReplyKeyboardRemove()
)
raise Exception('Sorry I don\'t recognise this operation "{}"!'.format(op))
if op == options["overall"]:
get_analysis.viewOverallBudget(chat_id, bot)
elif op == options["spend"]:
get_analysis.viewSpendWise(chat_id, bot)
elif op == options["remaining"]:
get_analysis.viewRemaining(chat_id, bot)
elif op == options["history"]:
get_analysis.viewHistory(chat_id, bot)
# Validate the operation
validate_operation(op, options)

# Mapping operations to functions
operation_mapping = {
options["overall"]: get_analysis.viewOverallBudget,
options["spend"]: get_analysis.viewSpendWise,
options["remaining"]: get_analysis.viewRemaining,
options["history"]: get_analysis.viewHistory,
}

# Execute the corresponding function
operation_mapping[op](chat_id, bot)

except InvalidOperationError as e:
bot.send_message(chat_id, f"Invalid operation selected: '{e.operation}'. Please choose a valid option.")
except Exception as e:
helper.throw_exception(e, message, bot, logging)
helper.throw_exception(e, message, bot, logging)


def validate_operation(op, options):
"""
Validates whether the provided operation is in the available options.

Args:
op: The operation to validate.
options: A dictionary of valid operations.

Raises:
InvalidOperationError: If the operation is not valid.
"""
if op not in options.values():
raise InvalidOperationError(op)
3 changes: 2 additions & 1 deletion code/budget.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import budget_delete
import logging
from telebot import types
from exception import InvalidOperationError

# === Documentation of budget.py ===

Expand Down Expand Up @@ -65,7 +66,7 @@ def post_operation_selection(message, bot):
bot.send_message(
chat_id, "Invalid", reply_markup=types.ReplyKeyboardRemove()
)
raise Exception('Sorry I don\'t recognise this operation "{}"!'.format(op))
raise InvalidOperationError(op, "Sorry, I don’t recognize this operation")
if op == options["update"]:
budget_update.run(message, bot)
elif op == options["view"]:
Expand Down
Loading