1- # ~~~ Enhanced Read Telegram Bot Token with Configurable Fallback and Appropriate Logging ~~~
1+ # ~~~ Enhanced Read Telegram Bot Token with Configurable Fallback, Appropriate Logging, and Validity Check ~~~
22
33import os
44import configparser
@@ -39,26 +39,37 @@ def get_bot_token():
3939
4040 prefer_env = config .getboolean ('DEFAULT' , 'PreferEnvForBotToken' , fallback = True )
4141 allow_fallback = config .getboolean ('DEFAULT' , 'AllowFallback' , fallback = True )
42+ ask_for_token = config .getboolean ('DEFAULT' , 'AskForTokenIfNotFound' , fallback = True )
43+
44+ invalid_tokens = [
45+ 'YourTelegramBotToken' ,
46+ '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11' , # Example bot token from Telegram documentation
47+ '' ,
48+ None
49+ ]
50+
51+ def is_valid_token (token ):
52+ return token not in invalid_tokens and len (token .split (':' )) == 2
4253
4354 # Define retrieval methods
4455 def retrieve_from_env ():
4556 bot_token = os .getenv ('TELEGRAM_BOT_TOKEN' )
46- if bot_token :
57+ if bot_token and is_valid_token ( bot_token ) :
4758 logging .info ("Bot token successfully retrieved from environment variable." )
4859 return bot_token
4960 else :
50- logging .warning ("TELEGRAM_BOT_TOKEN environment variable not set ." )
61+ logging .warning ("Invalid or unset TELEGRAM_BOT_TOKEN environment variable." )
5162 return None
5263
5364 def retrieve_from_file ():
5465 if token_file_path .is_file ():
5566 try :
5667 bot_token = token_file_path .read_text ().strip ()
57- if bot_token :
68+ if bot_token and is_valid_token ( bot_token ) :
5869 logging .info ("Bot token successfully retrieved from bot_token.txt." )
5970 return bot_token
6071 else :
61- logging .error ("bot_token.txt is empty." )
72+ logging .error ("Invalid or empty bot_token.txt ." )
6273 return None
6374 except IOError as e :
6475 logging .error (f"Failed to read bot_token.txt. Details: { e } " )
@@ -67,16 +78,39 @@ def retrieve_from_file():
6778 logging .error (f"bot_token.txt not found at { token_file_path } ." )
6879 return None
6980
81+ def query_user_for_token ():
82+ logging .info ("No valid bot token found. Please obtain a Telegram bot token from @BotFather on Telegram and paste it below." )
83+ logging .info ("Press Enter without typing anything to quit." )
84+ token = input ("Your Telegram bot token: " ).strip ()
85+ if token and is_valid_token (token ):
86+ # Save the token to bot_token.txt for future use
87+ try :
88+ token_file_path .write_text (token )
89+ logging .info (f"Bot token saved to { token_file_path } ." )
90+ return token
91+ except IOError as e :
92+ logging .error (f"Failed to save bot token to bot_token.txt. Details: { e } " )
93+ return None
94+ else :
95+ logging .error ("No valid token entered. Exiting application." )
96+ sys .exit (1 )
97+
7098 # Retrieval logic based on configuration
7199 if prefer_env :
72100 token = retrieve_from_env ()
73101 if token :
74102 return token
75103 elif allow_fallback :
76- logging .warning ("Preferred environment variable not found. Attempting to retrieve bot token from bot_token.txt as fallback." )
104+ logging .warning ("Preferred environment variable not found or invalid . Attempting to retrieve bot token from bot_token.txt as fallback." )
77105 token = retrieve_from_file ()
78106 if token :
79107 return token
108+ elif ask_for_token :
109+ token = query_user_for_token ()
110+ if token :
111+ return token
112+ else :
113+ raise BotTokenError ("Failed to retrieve bot token from environment variable, token file, and user input." )
80114 else :
81115 raise BotTokenError ("Failed to retrieve bot token from both environment variable and token file." )
82116 else :
@@ -90,10 +124,16 @@ def retrieve_from_file():
90124 if token :
91125 return token
92126 elif allow_fallback :
93- logging .warning ("bot_token.txt not found. Attempting to retrieve bot token from environment variable as fallback." )
127+ logging .warning ("bot_token.txt not found or invalid . Attempting to retrieve bot token from environment variable as fallback." )
94128 token = retrieve_from_env ()
95129 if token :
96130 return token
131+ elif ask_for_token :
132+ token = query_user_for_token ()
133+ if token :
134+ return token
135+ else :
136+ raise BotTokenError ("Failed to retrieve bot token from token file, environment variable, and user input." )
97137 else :
98138 raise BotTokenError ("Failed to retrieve bot token from both token file and environment variable." )
99139 else :
@@ -122,49 +162,175 @@ def retrieve_from_file():
122162 sys .stderr .flush () # Ensure all stderr logs are flushed
123163 sys .exit (1 )
124164
125- # # // (old method)
126- # # ~~~ read the telegram bot token ~~~
165+ # # ((newer method; no query))
166+ # # to be cleaned up, kept only for reference atm!
167+ # # ~~~ Enhanced Read Telegram Bot Token with Configurable Fallback and Appropriate Logging ~~~
127168
128169# import os
129170# import configparser
130- # import sys
131171# import logging
172+ # from pathlib import Path
173+ # import sys
174+
175+ # # Set up basic logging configuration
176+ # # logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
177+ # logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s', handlers=[logging.StreamHandler(sys.stdout)])
178+
179+ # class BotTokenError(Exception):
180+ # """Custom exception for bot token retrieval failures."""
181+ # pass
132182
133183# def get_bot_token():
134- # # Correctly ascend two levels to get the project root from bot_token.py in src/utils
135- # base_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
136- # config_path = os.path.join(base_dir, 'config', 'config.ini')
137- # token_file_path = os.path.join(base_dir, 'config', 'bot_token.txt')
138-
139- # logging.info(f"Debug: Base directory is {base_dir}")
140- # logging.info(f"Debug: Config path is {config_path}")
141- # logging.info(f"Debug: Token file path is {token_file_path}")
142-
143- # # Check if the paths actually exist
144- # if not os.path.exists(config_path):
145- # print("Error: config.ini not found at the expected path.")
146- # sys.exit(1)
184+ # try:
185+ # # Ascend two levels to get the project root from bot_token.py in src/utils
186+ # base_dir = Path(__file__).resolve().parents[2]
187+ # config_path = base_dir / 'config' / 'config.ini'
188+ # token_file_path = base_dir / 'config' / 'bot_token.txt'
147189
148- # if not os.path.exists(token_file_path) and not os.getenv('TELEGRAM_BOT_TOKEN'):
149- # print("Error: bot_token.txt not found at the expected path and TELEGRAM_BOT_TOKEN environment variable is not set.")
150- # sys.exit(1)
190+ # logging.debug(f"Base directory: {base_dir}")
191+ # logging.debug(f"Config path: {config_path}")
192+ # logging.debug(f"Token file path: {token_file_path}")
193+
194+ # # Verify config.ini exists
195+ # if not config_path.is_file():
196+ # raise BotTokenError(f"config.ini not found at {config_path}.")
197+
198+ # # Read configuration
199+ # config = configparser.ConfigParser()
200+ # config.read(config_path)
201+
202+ # # Validate configuration
203+ # if 'DEFAULT' not in config:
204+ # raise BotTokenError("Missing 'DEFAULT' section in config.ini.")
151205
152- # # Reading the config
153- # config = configparser.ConfigParser()
154- # config.read(config_path)
155- # prefer_env = config.getboolean('DEFAULT', 'PreferEnvForBotToken', fallback=True)
206+ # prefer_env = config.getboolean('DEFAULT', 'PreferEnvForBotToken', fallback=True)
207+ # allow_fallback = config.getboolean('DEFAULT', 'AllowFallback', fallback=True)
156208
157- # if prefer_env and os.getenv('TELEGRAM_BOT_TOKEN'):
158- # return os.getenv('TELEGRAM_BOT_TOKEN')
209+ # # Define retrieval methods
210+ # def retrieve_from_env():
211+ # bot_token = os.getenv('TELEGRAM_BOT_TOKEN')
212+ # if bot_token:
213+ # logging.info("Bot token successfully retrieved from environment variable.")
214+ # return bot_token
215+ # else:
216+ # logging.warning("TELEGRAM_BOT_TOKEN environment variable not set.")
217+ # return None
159218
160- # # Try to read the token from the file if the environment variable isn't preferred or set
219+ # def retrieve_from_file():
220+ # if token_file_path.is_file():
221+ # try:
222+ # bot_token = token_file_path.read_text().strip()
223+ # if bot_token:
224+ # logging.info("Bot token successfully retrieved from bot_token.txt.")
225+ # return bot_token
226+ # else:
227+ # logging.error("bot_token.txt is empty.")
228+ # return None
229+ # except IOError as e:
230+ # logging.error(f"Failed to read bot_token.txt. Details: {e}")
231+ # return None
232+ # else:
233+ # logging.error(f"bot_token.txt not found at {token_file_path}.")
234+ # return None
235+
236+ # # Retrieval logic based on configuration
237+ # if prefer_env:
238+ # token = retrieve_from_env()
239+ # if token:
240+ # return token
241+ # elif allow_fallback:
242+ # logging.warning("Preferred environment variable not found. Attempting to retrieve bot token from bot_token.txt as fallback.")
243+ # token = retrieve_from_file()
244+ # if token:
245+ # return token
246+ # else:
247+ # raise BotTokenError("Failed to retrieve bot token from both environment variable and token file.")
248+ # else:
249+ # logging.error("Environment variable not found and fallback is disabled.")
250+ # raise BotTokenError(
251+ # "Failed to retrieve bot token. "
252+ # "Please ensure the TELEGRAM_BOT_TOKEN environment variable is set, or allow fallback by enabling it in config.ini."
253+ # )
254+ # else:
255+ # token = retrieve_from_file()
256+ # if token:
257+ # return token
258+ # elif allow_fallback:
259+ # logging.warning("bot_token.txt not found. Attempting to retrieve bot token from environment variable as fallback.")
260+ # token = retrieve_from_env()
261+ # if token:
262+ # return token
263+ # else:
264+ # raise BotTokenError("Failed to retrieve bot token from both token file and environment variable.")
265+ # else:
266+ # logging.error("Token file not found and fallback is disabled.")
267+ # raise BotTokenError(
268+ # "Failed to retrieve bot token. "
269+ # "Please ensure bot_token.txt exists at the expected location, or allow fallback by enabling it in config.ini."
270+ # )
271+
272+ # except BotTokenError as e:
273+ # logging.error(f"BotTokenError: {e}")
274+ # sys.stderr.flush() # Ensure all stderr logs are flushed
275+ # sys.exit(1) # Explicitly exit on BotTokenError
276+ # except Exception as e:
277+ # logging.error(f"Unexpected error while retrieving bot token: {e}")
278+ # sys.stderr.flush() # Ensure all stderr logs are flushed
279+ # sys.exit(1) # Explicitly exit on unexpected errors
280+
281+ # # Example usage
282+ # if __name__ == "__main__":
161283# try:
162- # with open(token_file_path, 'r') as file:
163- # return file.read().strip()
164- # except FileNotFoundError:
165- # print("Error: Failed to read bot_token.txt.")
284+ # token = get_bot_token()
285+ # logging.info("Bot token successfully retrieved.")
286+ # except Exception as e:
287+ # logging.critical("Failed to retrieve bot token. Exiting application.")
288+ # sys.stderr.flush() # Ensure all stderr logs are flushed
166289# sys.exit(1)
167290
168- # # Fallback error message
169- # print("The bot token could not be determined.")
170- # sys.exit(1)
291+ # # # // (old method)
292+ # # # ~~~ read the telegram bot token ~~~
293+
294+ # # import os
295+ # # import configparser
296+ # # import sys
297+ # # import logging
298+
299+ # # def get_bot_token():
300+ # # # Correctly ascend two levels to get the project root from bot_token.py in src/utils
301+ # # base_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
302+ # # config_path = os.path.join(base_dir, 'config', 'config.ini')
303+ # # token_file_path = os.path.join(base_dir, 'config', 'bot_token.txt')
304+
305+ # # logging.info(f"Debug: Base directory is {base_dir}")
306+ # # logging.info(f"Debug: Config path is {config_path}")
307+ # # logging.info(f"Debug: Token file path is {token_file_path}")
308+
309+ # # # Check if the paths actually exist
310+ # # if not os.path.exists(config_path):
311+ # # print("Error: config.ini not found at the expected path.")
312+ # # sys.exit(1)
313+
314+ # # if not os.path.exists(token_file_path) and not os.getenv('TELEGRAM_BOT_TOKEN'):
315+ # # print("Error: bot_token.txt not found at the expected path and TELEGRAM_BOT_TOKEN environment variable is not set.")
316+ # # sys.exit(1)
317+
318+ # # # Reading the config
319+ # # config = configparser.ConfigParser()
320+ # # config.read(config_path)
321+ # # prefer_env = config.getboolean('DEFAULT', 'PreferEnvForBotToken', fallback=True)
322+
323+ # # if prefer_env and os.getenv('TELEGRAM_BOT_TOKEN'):
324+ # # return os.getenv('TELEGRAM_BOT_TOKEN')
325+
326+ # # # Try to read the token from the file if the environment variable isn't preferred or set
327+ # # try:
328+ # # with open(token_file_path, 'r') as file:
329+ # # return file.read().strip()
330+ # # except FileNotFoundError:
331+ # # print("Error: Failed to read bot_token.txt.")
332+ # # sys.exit(1)
333+
334+ # # # Fallback error message
335+ # # print("The bot token could not be determined.")
336+ # # sys.exit(1)
0 commit comments