diff --git a/README.md b/README.md index de71671..d988ee3 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/src/main.py b/src/main.py index 5467c25..c33f019 100755 --- a/src/main.py +++ b/src/main.py @@ -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 @@ -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', diff --git a/src/text_message_handler.py b/src/text_message_handler.py index 978e61e..e16cd8d 100644 --- a/src/text_message_handler.py +++ b/src/text_message_handler.py @@ -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 @@ -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 @@ -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 @@ -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, diff --git a/src/timedate_handler.py b/src/timedate_handler.py new file mode 100644 index 0000000..1c31a83 --- /dev/null +++ b/src/timedate_handler.py @@ -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"