Skip to content

Commit 7e3e2c0

Browse files
committed
v0.7504 - fixed usage charts & redone directory mapping
1 parent f1e5937 commit 7e3e2c0

File tree

3 files changed

+132
-25
lines changed

3 files changed

+132
-25
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ If you run into any issues, consult the logs or reach out on the repository's [I
236236
---
237237

238238
# Changelog
239+
- v0.7504 - fixed usage logs and charts directory mapping
239240
- v0.7503 - improved message formatting & error catching
240241
- v0.7502 - added `docker_setup.sh` for easier Docker-based deployment
241242
- v0.7501 - `Dockerfile` and better error catching when receiving `401 Unauthorized`

src/bot_commands.py

Lines changed: 92 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -107,59 +107,132 @@ async def set_system_message_command(update: Update, context: CallbackContext, b
107107
logging.info(f"User {user_id} attempted to set system message but provided no new message.")
108108
await update.message.reply_text("Please provide the new system message in the command line, i.e.: /setsystemmessage My new system message to the AI on what it is, where it is, etc.")
109109

110+
110111
# /usage (admin command)
111-
async def usage_command(update: Update, context: CallbackContext, bot_instance):
112+
# bot_commands.py
113+
async def usage_command(update: Update, context: CallbackContext):
114+
bot_instance = context.bot_data.get('bot_instance') # Retrieve the bot instance from context
115+
116+
if not bot_instance:
117+
await update.message.reply_text("Internal error: Bot instance not found.")
118+
logging.error("Bot instance not found in context.bot_data")
119+
return
120+
121+
logging.info(f"User {update.message.from_user.id} invoked /usage command")
122+
112123
if bot_instance.bot_owner_id == '0':
113124
await update.message.reply_text("The `/usage` command is disabled.")
125+
logging.info("Usage command is disabled until a bot owner is defined in `config.ini`.")
114126
return
115127

116128
if str(update.message.from_user.id) != bot_instance.bot_owner_id:
117129
await update.message.reply_text("You don't have permission to use this command.")
130+
logging.info(f"User {update.message.from_user.id} does not have permission to use /usage")
118131
return
119132

120-
# Define current_date before entering the try block
133+
# Correct path to token_usage.json inside logs/ directory
134+
# token_usage_file = os.path.join(bot_instance.data_directory, 'logs', 'token_usage.json')
135+
token_usage_file = os.path.join(bot_instance.logs_directory, 'token_usage.json')
136+
137+
logging.info(f"Looking for token usage file at: {token_usage_file}")
121138
current_date = datetime.datetime.utcnow()
122139

123140
try:
124-
if os.path.exists(bot_instance.token_usage_file):
125-
with open(bot_instance.token_usage_file, 'r') as file:
141+
if os.path.exists(token_usage_file):
142+
with open(token_usage_file, 'r') as file:
126143
token_usage_history = json.load(file)
127-
128-
# Prune token usage history based on the previously defined current_date
144+
logging.info("Loaded token usage history successfully")
145+
146+
# Prune token usage history
129147
cutoff_date = current_date - datetime.timedelta(days=bot_instance.max_history_days)
130-
token_usage_history = {date: usage for date, usage in token_usage_history.items() if datetime.datetime.strptime(date, '%Y-%m-%d') >= cutoff_date}
148+
token_usage_history = {
149+
date: usage for date, usage in token_usage_history.items()
150+
if datetime.datetime.strptime(date, '%Y-%m-%d') >= cutoff_date
151+
}
152+
logging.info("Pruned token usage history based on cutoff date")
131153
else:
132154
token_usage_history = {}
155+
logging.warning(f"Token usage file does not exist at: {token_usage_file}")
133156
except json.JSONDecodeError:
134157
await update.message.reply_text("Error reading token usage history.")
158+
logging.error("JSONDecodeError while reading token_usage.json")
159+
return
160+
except Exception as e:
161+
await update.message.reply_text(f"An unexpected error occurred: {e}")
162+
logging.error(f"Unexpected error in usage_command: {e}")
135163
return
136164

137-
# Since current_date is now defined outside the try block, it will always be available here
138165
today_usage = token_usage_history.get(current_date.strftime('%Y-%m-%d'), 0)
139-
token_cap_info = f"Today's usage: {today_usage} tokens\n" \
140-
f"Daily token cap: {'No cap' if bot_instance.max_tokens_config == 0 else f'{bot_instance.max_tokens_config} tokens'}\n\n" \
141-
"Token Usage History:\n"
166+
token_cap_info = (
167+
f"Today's usage: {today_usage} tokens\n"
168+
f"Daily token cap: {'No cap' if bot_instance.max_tokens_config == 0 else f'{bot_instance.max_tokens_config} tokens'}\n\n"
169+
"Token Usage History:\n"
170+
)
142171

143172
for date, usage in sorted(token_usage_history.items()):
144173
token_cap_info += f"{date}: {usage} tokens\n"
145174

146175
await update.message.reply_text(token_cap_info)
176+
logging.info("Sent usage information to user")
177+
178+
# /usagechart (admin command)
179+
async def usage_chart_command(update: Update, context: CallbackContext):
180+
bot_instance = context.bot_data.get('bot_instance') # Retrieve the bot instance from context
147181

148-
# /usagechart (admin command, to get chart type usage statistics)
149-
async def usage_chart_command(update: Update, context: CallbackContext, bot_instance, token_usage_file):
182+
if not bot_instance:
183+
await update.message.reply_text("Internal error: Bot instance not found.")
184+
logging.error("Bot instance not found in context.bot_data")
185+
return
186+
187+
logging.info(f"User {update.message.from_user.id} invoked /usagechart command")
188+
150189
if bot_instance.bot_owner_id == '0':
151190
await update.message.reply_text("The `/usagechart` command is disabled.")
191+
logging.info("Usagechart command is disabled")
152192
return
153193

154194
if str(update.message.from_user.id) != bot_instance.bot_owner_id:
155195
await update.message.reply_text("You don't have permission to use this command.")
196+
logging.info(f"User {update.message.from_user.id} does not have permission to use /usagechart")
156197
return
157-
158-
output_image_file = 'token_usage_chart.png'
159-
generate_usage_chart(token_usage_file, output_image_file)
160-
161-
with open(output_image_file, 'rb') as file:
162-
await context.bot.send_photo(chat_id=update.message.chat_id, photo=file)
198+
199+
# Define paths
200+
token_usage_file = os.path.join(bot_instance.logs_directory, 'token_usage.json')
201+
output_image_file = os.path.join(bot_instance.data_directory, 'token_usage_chart.png')
202+
203+
logging.info(f"Looking for token usage file at: {token_usage_file}")
204+
logging.info(f"Output image file will be at: {output_image_file}")
205+
206+
# Ensure the data directory exists
207+
try:
208+
if not os.path.exists(bot_instance.data_directory):
209+
os.makedirs(bot_instance.data_directory, exist_ok=True)
210+
bot_instance.logger.info(f"Created data directory at {bot_instance.data_directory}")
211+
except OSError as e:
212+
bot_instance.logger.error(f"Failed to create data directory {bot_instance.data_directory}: {e}")
213+
await update.message.reply_text(f"Failed to create the data directory for the chart. Please check the bot's permissions.")
214+
return
215+
216+
# Generate the usage chart
217+
try:
218+
generate_usage_chart(token_usage_file, output_image_file)
219+
bot_instance.logger.info(f"Generated usage chart at {output_image_file}")
220+
except Exception as e:
221+
bot_instance.logger.error(f"Failed to generate usage chart: {e}")
222+
await update.message.reply_text("Failed to generate usage chart.")
223+
return
224+
225+
# Try to open and send the generated chart image
226+
try:
227+
with open(output_image_file, 'rb') as file:
228+
await context.bot.send_photo(chat_id=update.message.chat_id, photo=file)
229+
bot_instance.logger.info(f"Sent usage chart to chat_id {update.message.chat_id}")
230+
except FileNotFoundError:
231+
await update.message.reply_text("Token usage chart not found. Please ensure it's being generated correctly.")
232+
bot_instance.logger.error("Token usage chart file not found: %s", output_image_file)
233+
except Exception as e:
234+
await update.message.reply_text("Failed to send the usage chart.")
235+
bot_instance.logger.error(f"Error sending usage chart: {e}")
163236

164237
# /reset
165238
async def reset_command(update: Update, context: CallbackContext, bot_owner_id, reset_enabled, admin_only_reset):

src/main.py

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
# https://github.com/FlyingFathead/TelegramBot-OpenAI-API
66
#
77
# version of this program
8-
version_number = "0.7503"
8+
version_number = "0.7504"
99

1010
# Add the project root directory to Python's path
1111
import sys
@@ -147,9 +147,35 @@ def load_config(self):
147147
self.enable_whisper = self.config.getboolean('EnableWhisper', True)
148148
self.max_voice_message_length = self.config.getint('MaxDurationMinutes', 5)
149149

150-
self.data_directory = self.config.get('DataDirectory', 'data') # Default to 'data' if not set
150+
self.data_directory = self.config.get('DataDirectory', 'data') # Default to 'data' if not set
151151
self.max_storage_mb = self.config.getint('MaxStorageMB', 100) # Default to 100 MB if not set
152152

153+
# set directories
154+
# Get the project root
155+
project_root = Path(__file__).resolve().parents[1]
156+
157+
# Combine project root with the relative data directory from config
158+
self.data_directory = str(project_root / self.config.get('DataDirectory', 'data'))
159+
160+
# Ensure the data directory exists or handle creation failure
161+
try:
162+
if not os.path.exists(self.data_directory):
163+
os.makedirs(self.data_directory, exist_ok=True)
164+
self.logger.info(f"Created data directory at {self.data_directory}")
165+
except OSError as e:
166+
self.logger.error(f"Failed to create data directory {self.data_directory}: {e} -- Some commands might be disabled due to this.")
167+
168+
# set the logs directory
169+
self.logs_directory = str(project_root / self.config.get('LogsDirectory', 'logs'))
170+
171+
# Ensure the logs directory exists or handle creation failure
172+
try:
173+
if not os.path.exists(self.logs_directory):
174+
os.makedirs(self.logs_directory, exist_ok=True)
175+
self.logger.info(f"Created logs directory at {self.logs_directory}")
176+
except OSError as e:
177+
self.logger.error(f"Failed to create logs directory {self.logs_directory}: {e} -- Some commands might be disabled due to this.")
178+
153179
self.logfile_enabled = self.config.getboolean('LogFileEnabled', True)
154180
self.logfile_file = self.config.get('LogFile', 'bot.log')
155181
self.chat_logging_enabled = self.config.getboolean('ChatLoggingEnabled', False)
@@ -304,7 +330,11 @@ def error(self, update: Update, context: CallbackContext) -> None:
304330
def run(self):
305331
application = Application.builder().token(self.telegram_bot_token).build()
306332
application.get_updates_read_timeout = self.timeout
307-
333+
334+
# Store bot_instance in bot_data for access in handlers
335+
application.bot_data['bot_instance'] = self
336+
self.logger.info("Stored bot_instance in context.bot_data")
337+
308338
# Text handler
309339
application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, self.handle_message))
310340

@@ -325,9 +355,12 @@ def run(self):
325355
# application.add_handler(CommandHandler("restart", partial(bot_commands.restart_command, bot_owner_id=self.bot_owner_id)))
326356
# application.add_handler(CommandHandler("usage", partial(bot_commands.usage_command, bot_owner_id=self.bot_owner_id, total_token_usage=self.total_token_usage, max_tokens_config=self.max_tokens_config)))
327357
# application.add_handler(CommandHandler("updateconfig", partial(bot_commands.update_config_command, bot_owner_id=self.bot_owner_id)))
328-
application.add_handler(CommandHandler("usagechart", partial(bot_commands.usage_chart_command, bot_instance=self, token_usage_file='token_usage.json')))
329-
application.add_handler(CommandHandler("usage", partial(bot_commands.usage_command, bot_instance=self)))
330-
358+
# application.add_handler(CommandHandler("usagechart", partial(bot_commands.usage_chart_command, bot_instance=self, token_usage_file='token_usage.json')))
359+
# application.add_handler(CommandHandler("usage", partial(bot_commands.usage_command, bot_instance=self)))
360+
361+
application.add_handler(CommandHandler("usagechart", bot_commands.usage_chart_command))
362+
application.add_handler(CommandHandler("usage", bot_commands.usage_command))
363+
331364
# Register the /reset command
332365
application.add_handler(CommandHandler("reset", partial(bot_commands.reset_command,
333366
bot_owner_id=self.bot_owner_id,

0 commit comments

Comments
 (0)