Skip to content

v0.7613 - Improved timestamps on multiple timezones #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 7, 2025
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
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,10 @@ If you run into any issues, consult the logs or reach out on the repository's [I
---

# Changelog
- v0.7613 - Improved timestamps on multiple timezones
- Added a separate module to `src/timedate_handler.py` to assist the model
- => Datetime stamps now in separate system messages
- => More TZ-aware dates and times
- v0.7611 - Parsing hotfix for notifications
- v0.761 - **Timed notifications / user reminders**
- Brand-new feature: users can set timed reminders (alerts) by requesting reminders that the bot stores in an SQLite database. A separate poller picks them up as soon as they are due, and the bot automatically notifies the user on set times.
Expand Down
11 changes: 6 additions & 5 deletions src/main.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
# Multi-API Telegram Bot (Powered by ChatKeke)
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# by FlyingFathead ~*~ https://github.com/FlyingFathead
# ghostcode: ChaosWhisperer
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# https://github.com/FlyingFathead/TelegramBot-OpenAI-API
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# version of this program
version_number = "0.7612"
version_number = "0.7613"

# Add the project root directory to Python's path
import sys
Expand Down Expand Up @@ -215,7 +213,10 @@ def load_config(self):
'SystemInstructions',
'You are an OpenAI API-based chatbot on Telegram.'
)
self.system_instructions = f"[Bot's current model: {self.model}] {default_system_msg}"

# # // skip current model info
# self.system_instructions = f"[Bot's current model: {self.model}] {default_system_msg}"
self.system_instructions = f"[Instructions] {default_system_msg}"

self.start_command_response = self.config.get(
'StartCommandResponse',
Expand Down
60 changes: 44 additions & 16 deletions src/text_message_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@
from telegram.constants import ChatAction
from telegram.error import TimedOut

# time & date handling
from timedate_handler import (
get_ordinal_suffix,
get_english_timestamp_str,
get_finnish_timestamp_str
)

# reminder handling
from reminder_handler import handle_add_reminder, handle_delete_reminder, handle_edit_reminder, handle_view_reminders

Expand Down Expand Up @@ -259,16 +266,31 @@ async def handle_message(bot, update: Update, context: CallbackContext, logger)
# Debug: Print before token limit checks
bot.logger.info(f"[Debug] is_no_limit: {is_no_limit}, user_token_count: {user_token_count}, max_tokens_config: {max_tokens_config}")

# get date & time for timestamps
# ~~~~~~~~~~~~~~~
# Make timestamp
# ~~~~~~~~~~~~~~~
now_utc = datetime.datetime.utcnow()
current_time = now_utc
# utc_timestamp = now_utc.strftime("%Y-%m-%d %H:%M:%S UTC")

# display abbreviated
utc_timestamp = now_utc.strftime("%Y-%m-%d %H:%M:%S %a UTC")

# We'll keep this for session timeout comparisons
current_time = now_utc
day_of_week = now_utc.strftime("%A")
user_message_with_timestamp = f"[{utc_timestamp}] {user_message}"
system_timestamp = now_utc.strftime("%Y-%m-%d %H:%M:%S UTC")

english_line = get_english_timestamp_str(now_utc)
finnish_line = get_finnish_timestamp_str(now_utc)

# Combine them however you like, e.g.:
#
# Monday, April 9th, 2025 | Time (UTC): 12:34:56
# maanantai, 9. huhtikuuta 2025, klo 15:34:56 Suomen aikaa
#
current_timestamp_str = f"{english_line}\n{finnish_line}"

# We'll put that into a system message
timestamp_system_msg = {
"role": "system",
"content": current_timestamp_str
}

# Add the user's tokens to the total usage (JSON style)
bot.total_token_usage += user_token_count
Expand Down Expand Up @@ -316,12 +338,24 @@ async def handle_message(bot, update: Update, context: CallbackContext, logger)
# Initialize chat_history as an empty list if it doesn't exist
chat_history = context.chat_data.get('chat_history', [])

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Insert the new system msg
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
# logger info on the appended system message
logger.info(f"Inserting timestamp system message: {current_timestamp_str}")

chat_history.append(timestamp_system_msg)

# Append the new user message to the chat history
chat_history.append({"role": "user", "content": user_message_with_timestamp})
chat_history.append({"role": "user", "content": user_message})

# Prepare the conversation history to send to the OpenAI API
system_timestamp = datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S UTC")
system_message = {"role": "system", "content": f"System time+date: {system_timestamp}, {day_of_week}): {bot.system_instructions}"}

# # // old method that included the timestamp in the original system message
# system_timestamp = datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S UTC")
# system_message = {"role": "system", "content": f"System time+date: {system_timestamp}, {day_of_week}): {bot.system_instructions}"}

system_message = {"role": "system", "content": f"Instructions: {bot.system_instructions}"}

chat_history_with_system_message = [system_message] + chat_history

Expand Down Expand Up @@ -1319,12 +1353,6 @@ async def handle_message(bot, update: Update, context: CallbackContext, logger)
model_info=model_info
)

# # Log the bot's response
# bot.log_message(
# message_type='Bot',
# message=bot_reply,
# )

# # # send the response
# # await context.bot.send_message(
# # chat_id=chat_id,
Expand Down
87 changes: 87 additions & 0 deletions src/timedate_handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# timedate_handler.py
import datetime
import pytz

# Maps English day names from strftime() -> Finnish
fi_days = {
"Monday": "maanantai",
"Tuesday": "tiistai",
"Wednesday": "keskiviikko",
"Thursday": "torstai",
"Friday": "perjantai",
"Saturday": "lauantai",
"Sunday": "sunnuntai"
}

# Maps English month names -> Finnish “month in the partitive case” for typical date usage
fi_months = {
"January": "tammikuuta",
"February": "helmikuuta",
"March": "maaliskuuta",
"April": "huhtikuuta",
"May": "toukokuuta",
"June": "kesäkuuta",
"July": "heinäkuuta",
"August": "elokuuta",
"September": "syyskuuta",
"October": "lokakuuta",
"November": "marraskuuta",
"December": "joulukuuta"
}

def get_ordinal_suffix(day_num: int) -> str:
"""
Returns the English ordinal suffix for a given day of the month, e.g.
1->"1st", 2->"2nd", 3->"3rd", 4->"4th", etc.
"""
if 11 <= (day_num % 100) <= 13:
return "th"
elif day_num % 10 == 1:
return "st"
elif day_num % 10 == 2:
return "nd"
elif day_num % 10 == 3:
return "rd"
else:
return "th"

def get_english_timestamp_str(now_utc: datetime.datetime) -> str:
"""
Returns an English-formatted date/time string, e.g.:
'Monday, April 9th, 2025 | Time (UTC): 12:34:56'
"""
day_of_week_eng = now_utc.strftime("%A") # e.g. "Monday"
month_name_eng = now_utc.strftime("%B") # e.g. "April"
day_num = int(now_utc.strftime("%d"))
year_str = now_utc.strftime("%Y")
suffix = get_ordinal_suffix(day_num)
date_str = f"{month_name_eng} {day_num}{suffix}, {year_str}"
time_str = now_utc.strftime("%H:%M:%S") # "12:34:56"

return f"{day_of_week_eng}, {date_str} | Time (UTC): {time_str}"

def get_finnish_timestamp_str(now_utc: datetime.datetime) -> str:
"""
Returns a Finnish-formatted date/time string. For example:
'maanantai, 9. huhtikuuta 2025, klo 15:34:56 Suomen aikaa'

(Adjust as you like for Finnish grammar.)
"""
helsinki_tz = pytz.timezone("Europe/Helsinki")
now_fin = now_utc.astimezone(helsinki_tz)

weekday_eng = now_fin.strftime("%A") # e.g. "Monday"
day_of_week_fi = fi_days.get(weekday_eng, weekday_eng)

month_eng = now_fin.strftime("%B") # e.g. "April"
month_fi = fi_months.get(month_eng, month_eng)

day_num = int(now_fin.strftime("%d")) # e.g. 9
year_str = now_fin.strftime("%Y") # e.g. "2025"

# For Finnish style we might do e.g. "9. huhtikuuta 2025"
date_str_fi = f"{day_num}. {month_fi} {year_str}"

time_str_fi = now_fin.strftime("%H:%M:%S") # "15:34:56"
# For instance: "maanantai, 9. huhtikuuta 2025, klo 15:34:56 Suomen aikaa"
return f"{day_of_week_fi}, {date_str_fi}, klo {time_str_fi} Suomen aikaa"