Skip to content
Merged
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
v2.1.0
  • Loading branch information
brucewzj99 committed Jun 1, 2023
commit a34a7d65466a0e377780cc009f3053f684f3a370
22 changes: 7 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,28 +37,18 @@ pip install -r requirements.txt
* Retrieve your firebase database url
* Set up telegram bot via [BotFather](https://t.me/BotFather)
* Insert all of them into .env as follows, you can use py dotenv or set it as env variable in your venv
* You can use the same TOKEN for BOT_TOKEN & TEST_TOKEN but I recommend using two different bots for testing and production

``` .env
BOT_TOKEN=your_bot_token
TEST_TOKEN=your_test_token
DATABASE_URL=firebase_url
GOOGLE_API_EMAIL=google_api_email
FIREBASE_JSON=service_account_key
GOOGLE_JSON=service_account_key
```

### Step 3
* Run ngrok
``` terminal
ngrok http 5000
```
* Copy the link, it should look something like this 'https://<address>.ap.ngrok.io'
* Set up web hook by opening this link:
``` url
https://api.telegram.org/bot<bot_token>/setwebhook?url=https://<address>.ap.ngrok.io/webhook
```
* You should see this:
``` json
{"ok":true,"result":true,"description":"Webhook was set"}
```
* Proceed to project directory and run:
``` python
python3.9 test.py
Expand All @@ -77,7 +67,9 @@ python3.9 test.py

/addincome - Add Income Entry

/retrievetransaction - Retrieve transaction from dates
/getdaytransaction - Retrieve transaction from dates

/getoverall - Retrieve overall transaction for a month

/cancel - Cancel Conversation

Expand All @@ -101,4 +93,4 @@ Bruce Wang: [email protected]

LinkedIn: [https://www.linkedin.com/in/brucewzj/](https://www.linkedin.com/in/brucewzj/)

Project Link: [https://github.com/brucewzj99/tele-tracker](https://github.com/brucewzj99/tele-tracker)
Project Link: [https://github.com/brucewzj99/tele-tracker-v2](https://github.com/brucewzj99/tele-tracker-v2)
5 changes: 3 additions & 2 deletions bot/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ class ConversationState(Enum):
CONFIG_SUBCATEGORY,
CONFIG_PAYMENT,
CONFIG_SUBPAYMENT,
HANDLE_RETRIEVE_TRANSACTION,
HANDLE_GET_TRANSACTION,
HANDLE_GET_OVERALL,
INCOME,
WORK_PLACE,
CPF,
) = range(22)
) = range(23)
12 changes: 11 additions & 1 deletion bot/google_sheet.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
payment_main_range = "Dropdown!A12:J12"
quick_others_range = "Tracker!I3:J13"
income_range = "Dropdown!L2:L9"
overall_range = "!M13:O25"


def get_main_dropdown_value(sheet_id, entry_type):
Expand Down Expand Up @@ -266,7 +267,7 @@ def get_quick_add_others(sheet_id):
return others_list


def retrieve_transaction(sheet_id, month, date):
def get_day_transaction(sheet_id, month, date):
result = (
sheets_api.spreadsheets()
.values()
Expand Down Expand Up @@ -353,3 +354,12 @@ def update_income(sheet_id, month, row_data):
body=body_r,
).execute()
return True

def get_overall(sheet_id, month):
result = (
sheets_api.spreadsheets()
.values()
.get(spreadsheetId=sheet_id, range=f"{month}{overall_range}")
.execute()
)
return result.get("values", [])
63 changes: 51 additions & 12 deletions bot/telegram_bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ def check_date_format(date_string):
pattern = r"\b\d{1,2}\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\b"
return bool(re.fullmatch(pattern, date_string, re.IGNORECASE))

def check_month_format(month_string):
pattern = r"^(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)$"
return bool(re.fullmatch(pattern, month_string, re.IGNORECASE))


def get_category_text(sheet_id, entry_type):
msg = ""
Expand Down Expand Up @@ -608,26 +612,36 @@ def help(update, context):
update.message.reply_text(HELP_TEXT)


def retrieve_transaction(update, context):
def get_day_transaction(update, context):
context.user_data.clear()
telegram_id = update.effective_user.id
try:
context.user_data["sheet_id"] = db.get_user_sheet_id(telegram_id)
update.message.reply_text(RETRIEVE_TRANSACTION_TEXT)
return CS.HANDLE_RETRIEVE_TRANSACTION
update.message.reply_text(GET_TRANSACTION_TEXT)
return CS.HANDLE_GET_TRANSACTION
except Exception as e:
update.message.reply_text(ERROR_TEXT)
return ConversationHandler.END

def get_overall(update, context):
context.user_data.clear()
telegram_id = update.effective_user.id
try:
context.user_data["sheet_id"] = db.get_user_sheet_id(telegram_id)
update.message.reply_text(GET_OVERALL_TEXT)
return CS.HANDLE_GET_OVERALL
except Exception as e:
update.message.reply_text(ERROR_TEXT)
return ConversationHandler.END

def handle_retrieve_transaction(update, context):
def handle_get_transaction(update, context):
sheet_id = context.user_data["sheet_id"]
reply = update.message.text
msg = ""
try:
if check_date_format(reply):
day, month = reply.split(" ")
total_spend, transport_values, other_values = gs.retrieve_transaction(
total_spend, transport_values, other_values = gs.get_day_transaction(
sheet_id, month, day
)
if not total_spend:
Expand All @@ -643,11 +657,32 @@ def handle_retrieve_transaction(update, context):
update.message.reply_text(msg)
return ConversationHandler.END
else:
update.message.reply_text(RETRIEVE_TRANSACTION_TEXT)
return CS.HANDLE_RETRIEVE_TRANSACTION
update.message.reply_text(GET_TRANSACTION_TEXT)
return CS.HANDLE_GET_TRANSACTION
except Exception as e:
update.message.reply_text(ERROR_TEXT)

def handle_get_overall(update, context):
sheet_id = context.user_data["sheet_id"]
month = update.message.text
msg = ""
try:
if check_month_format(month):
values = gs.get_overall(sheet_id, month)
msg = "```\n"
for row in values:
if len(row) == 3:
msg += "{:<20} {:<10} {:<10}\n".format(*row)
elif len(row) == 2:
msg += "{:<20} {:<10}\n".format(*row)
msg += "```"
update.message.reply_text(msg, parse_mode='Markdown')
return ConversationHandler.END
else:
update.message.reply_text(GET_OVERALL_TEXT)
return CS.HANDLE_GET_OVERALL
except Exception as e:
update.message.reply_text(ERROR_TEXT)

def add_income(update, context):
context.user_data.clear()
Expand Down Expand Up @@ -749,9 +784,12 @@ def setup_handlers(dispatcher):
}

# Retrieve transaction-related states and handlers
retrieve_transaction_states = {
CS.HANDLE_RETRIEVE_TRANSACTION: [
MessageHandler(Filters.text & ~Filters.command, handle_retrieve_transaction)
get_transaction_states = {
CS.HANDLE_GET_TRANSACTION: [
MessageHandler(Filters.text & ~Filters.command, handle_get_transaction)
],
CS.HANDLE_GET_OVERALL: [
MessageHandler(Filters.text & ~Filters.command, handle_get_overall)
],
}

Expand All @@ -768,15 +806,16 @@ def setup_handlers(dispatcher):
CommandHandler("addtransport", add_transport),
CommandHandler("addothers", add_others),
CommandHandler("addincome", add_income),
CommandHandler("retrievetransaction", retrieve_transaction),
CommandHandler("getdaytransaction", get_day_transaction),
CommandHandler("getoverall", get_overall)
],
states={
CS.SET_UP: [MessageHandler(Filters.text & ~Filters.command, set_up)],
CS.RESET_UP: [CallbackQueryHandler(reset_up)],
**config_states,
**entry_states,
**quick_add_states,
**retrieve_transaction_states,
**get_transaction_states,
**add_income_states,
},
fallbacks=[CommandHandler("cancel", cancel)],
Expand Down
8 changes: 5 additions & 3 deletions bot/text_str.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,18 @@
+ "/addtransport - Quick Add Transport Entry\n"
+ "/addothers - Quick Add Other Entry\n"
+ "/addincome - Add Income Entry\n"
+ "/retrievetransaction - Retrieve transaction from dates\n"
+ "/getdaytransaction - Retrieve transaction from dates\n"
+ "/getoverall - Retrieve overall transaction for a month\n"
+ "/cancel - Cancel Conversation\n"
+ "\nTo report bugs, please create a issue at https://github.com/brucewzj99/tele-tracker-v2/issues or contact me @bruceeew on Telegram"
)

RETRIEVE_TRANSACTION_TEXT = "Please specify the date and month you wish to retrieve from in this format: DD MMM\ne.g 16 Mar\nor use /cancel to exit"
GET_TRANSACTION_TEXT = "Please specify the date and month you wish to retrieve from in this format: DD MMM\ne.g 16 Mar\nor use /cancel to exit"
GET_OVERALL_TEXT = "Please specify the month you wish to retrieve your overall transaction in this format: MMM\ne.g Mar\nor use /cancel to exit"

ADD_INCOME_TEXT = "Add income\nPlease state your income followed by any remarks (optional): [income],[remarks]\ne.g. 2000, Something"
ADD_INCOME_RETRY_TEXT = (
"Please follow this format: [income],[remarks]\ne.g. 2000, Something"
"Please follow this format:\n[income],[remarks]\ne.g. 2000, Something"
)
CHOOSE_INCOME_SOURCE_TEXT = "Please choose your income source"
CPF_TEXT = "Is there CPF?"
Expand Down
12 changes: 11 additions & 1 deletion release_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,14 @@

## Version 2.0.2 - Date 1 Jun 2023
### Bug Fix 🛠️
- Day 1 sum creation bug
- Day 1 sum creation bug

## Version 2.1.0 - Date 1 Jun 2023
### New Features 🆕
- Added get overall functions

### Enhancement 🔥
- Rename retrievetransaction to getdaytransaction

### For Developer 🧑‍💻
- When you run test.py, ngrok will auto setup with the correct webhook!
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ google-api-python-client==2.86.0
google-auth==2.17.3
google-auth-httplib2==0.1.0
pytz==2023.3
firebase-admin==6.1.0
firebase-admin==6.1.0
pyngrok==6.0.0
10 changes: 5 additions & 5 deletions test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,26 @@
from flask import Flask, request
import os
from bot.telegram_bot import setup_handlers
from pyngrok import ngrok

TOKEN = os.environ.get("TEST_TOKEN")
app = Flask(__name__)
updater = Updater(token=TOKEN)
dispatcher = updater.dispatcher


@app.route("/webhook", methods=["POST"])
def webhook():
update = Update.de_json(request.get_json(), updater.bot)
dispatcher.process_update(update)
return "OK"


@app.route("/")
def index():
return "Bot is running!"


setup_handlers(dispatcher) # Call function to set up bot handlers
setup_handlers(dispatcher)

if __name__ == "__main__":
app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 5000)))
public_url = ngrok.connect(5000, "http").public_url
updater.bot.set_webhook(url=f"{public_url}/webhook")
app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 5000)))