Spaces:
Runtime error
Runtime error
Update main.py
Browse files
main.py
CHANGED
@@ -1,124 +1,167 @@
|
|
1 |
import os
|
2 |
-
import requests
|
3 |
import logging
|
4 |
-
import
|
|
|
5 |
|
6 |
from hydrogram import Client, filters
|
7 |
from hydrogram.types import Message
|
|
|
8 |
|
9 |
# --- Configuration ---
|
10 |
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
11 |
logger = logging.getLogger(__name__)
|
12 |
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
TEMPLATE_URL = "https://mediaflare.adasin.workers.dev/dl/4AmNTDcYQSPNQS"
|
17 |
|
18 |
-
#
|
19 |
-
|
20 |
-
|
21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
try:
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
return
|
28 |
-
except
|
29 |
-
logger.error(f"Error
|
30 |
-
return
|
31 |
|
32 |
# --- Initialization ---
|
33 |
-
if not
|
34 |
-
logger.error("
|
35 |
exit(1)
|
36 |
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
exit(1)
|
42 |
-
|
43 |
-
# Fetch the template image content (bytes)
|
44 |
-
template_image_bytes = fetch_template(TEMPLATE_URL)
|
45 |
-
if template_image_bytes is None:
|
46 |
-
logger.warning("Proceeding without template image due to fetch error.")
|
47 |
-
|
48 |
-
# Initialize the Hydrogram (Pyrogram) client
|
49 |
-
# *** Add workdir='.' to explicitly use the current directory for the session file ***
|
50 |
-
logger.info("Initializing Hydrogram Client...")
|
51 |
try:
|
52 |
app = Client(
|
53 |
-
name="
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
)
|
59 |
logger.info("Hydrogram Client initialized.")
|
60 |
except Exception as e:
|
61 |
-
# Log the specific exception
|
62 |
logger.error(f"Failed to initialize Hydrogram Client: {type(e).__name__} - {e}")
|
63 |
exit(1)
|
64 |
|
|
|
65 |
# --- Bot Event Handlers ---
|
66 |
-
@app.on_message(filters.command("start"))
|
67 |
async def start_handler(client: Client, message: Message):
|
68 |
-
"""Handler for the /start command.
|
69 |
sender_name = message.from_user.first_name if message.from_user else "User"
|
70 |
-
|
71 |
-
logger.info(f"Received /start command from {sender_name} (ID: {sender_id})")
|
72 |
|
73 |
-
|
|
|
|
|
|
|
74 |
|
75 |
-
if
|
76 |
-
|
77 |
-
try:
|
78 |
-
# Send the image bytes directly using io.BytesIO
|
79 |
-
await message.reply_photo(
|
80 |
-
photo=io.BytesIO(template_image_bytes),
|
81 |
-
caption=start_message_caption + "\n\nHere's the template image."
|
82 |
-
)
|
83 |
-
logger.info("Template image sent successfully.")
|
84 |
-
except Exception as e:
|
85 |
-
logger.error(f"Failed to send template image: {e}")
|
86 |
-
# Fallback to text message if sending photo fails
|
87 |
-
await message.reply_text(start_message_caption + "\n\n(Could not send the template image due to an error.)")
|
88 |
else:
|
89 |
-
|
90 |
-
await message.reply_text(start_message_caption + "\n\n(Could not load the template image.)")
|
91 |
|
|
|
92 |
|
93 |
-
@app.on_message(filters.command("
|
94 |
-
async def
|
95 |
-
"""Handler for the /
|
96 |
-
|
97 |
-
logger.info(f"Received /
|
98 |
-
await message.reply_text(
|
99 |
-
"This is a sample bot (Hydrogram).\nCommands:\n/start - Show welcome message and template image\n/help - Show this help message"
|
100 |
-
)
|
101 |
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
107 |
else:
|
108 |
-
|
|
|
109 |
|
110 |
-
|
|
|
|
|
|
|
|
|
|
|
111 |
try:
|
112 |
-
app.
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
|
|
|
|
|
|
118 |
except Exception as e:
|
119 |
-
|
120 |
-
logger.error(f"An unexpected error occurred during app.run(): {type(e).__name__} - {e}")
|
121 |
finally:
|
122 |
-
|
123 |
-
|
124 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import os
|
|
|
2 |
import logging
|
3 |
+
import asyncio
|
4 |
+
from pathlib import Path # For handling file paths robustly
|
5 |
|
6 |
from hydrogram import Client, filters
|
7 |
from hydrogram.types import Message
|
8 |
+
from hydrogram.errors import SessionPasswordNeeded, PhoneCodeInvalid, PhoneNumberInvalid, PasswordHashInvalid
|
9 |
|
10 |
# --- Configuration ---
|
11 |
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
12 |
logger = logging.getLogger(__name__)
|
13 |
|
14 |
+
# Retrieve Session String from Hugging Face secrets
|
15 |
+
# MUST be set in your Hugging Face Space/Repo secrets settings as SESSION_STRING
|
16 |
+
SESSION_STRING = os.environ.get('SESSION_STRING')
|
|
|
17 |
|
18 |
+
# Path for storing the template content
|
19 |
+
DATA_DIR = Path("data")
|
20 |
+
TEMPLATE_FILE_PATH = DATA_DIR / "template_content.txt"
|
21 |
+
|
22 |
+
# Global variable to hold the loaded template content
|
23 |
+
current_template_content = None
|
24 |
+
|
25 |
+
# --- Helper Functions for Template Management ---
|
26 |
+
def ensure_data_dir_exists():
|
27 |
+
"""Ensures the data directory exists."""
|
28 |
+
DATA_DIR.mkdir(parents=True, exist_ok=True)
|
29 |
+
logger.info(f"Data directory '{DATA_DIR}' ensured.")
|
30 |
+
|
31 |
+
async def load_template_from_file():
|
32 |
+
"""Loads template content from the persistent file."""
|
33 |
+
global current_template_content
|
34 |
+
ensure_data_dir_exists()
|
35 |
+
if TEMPLATE_FILE_PATH.exists():
|
36 |
+
try:
|
37 |
+
with open(TEMPLATE_FILE_PATH, "r", encoding="utf-8") as f:
|
38 |
+
current_template_content = f.read()
|
39 |
+
logger.info(f"Template loaded successfully from {TEMPLATE_FILE_PATH}")
|
40 |
+
except Exception as e:
|
41 |
+
logger.error(f"Error loading template from {TEMPLATE_FILE_PATH}: {e}")
|
42 |
+
current_template_content = None # Or a default error message
|
43 |
+
else:
|
44 |
+
logger.info(f"Template file {TEMPLATE_FILE_PATH} not found. No template loaded.")
|
45 |
+
current_template_content = None
|
46 |
+
|
47 |
+
async def save_template_to_file(content: str):
|
48 |
+
"""Saves template content to the persistent file."""
|
49 |
+
global current_template_content
|
50 |
+
ensure_data_dir_exists()
|
51 |
try:
|
52 |
+
with open(TEMPLATE_FILE_PATH, "w", encoding="utf-8") as f:
|
53 |
+
f.write(content)
|
54 |
+
current_template_content = content
|
55 |
+
logger.info(f"Template saved successfully to {TEMPLATE_FILE_PATH}")
|
56 |
+
return True
|
57 |
+
except Exception as e:
|
58 |
+
logger.error(f"Error saving template to {TEMPLATE_FILE_PATH}: {e}")
|
59 |
+
return False
|
60 |
|
61 |
# --- Initialization ---
|
62 |
+
if not SESSION_STRING:
|
63 |
+
logger.error("SESSION_STRING environment variable not found. Please set it in Hugging Face secrets.")
|
64 |
exit(1)
|
65 |
|
66 |
+
# Initialize the Hydrogram Client using the session string
|
67 |
+
# The name "user_session" is arbitrary when using a session_string,
|
68 |
+
# as the session is loaded directly from the string into memory.
|
69 |
+
logger.info("Initializing Hydrogram Client with session string...")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
try:
|
71 |
app = Client(
|
72 |
+
name="user_session", # Name is a placeholder when session_string is used
|
73 |
+
session_string=SESSION_STRING,
|
74 |
+
# workdir="." # workdir is not strictly necessary for session file when session_string is used,
|
75 |
+
# but good if other client files are ever created.
|
76 |
+
# The template file path is handled separately.
|
77 |
)
|
78 |
logger.info("Hydrogram Client initialized.")
|
79 |
except Exception as e:
|
|
|
80 |
logger.error(f"Failed to initialize Hydrogram Client: {type(e).__name__} - {e}")
|
81 |
exit(1)
|
82 |
|
83 |
+
|
84 |
# --- Bot Event Handlers ---
|
85 |
+
@app.on_message(filters.command("start") & filters.private)
|
86 |
async def start_handler(client: Client, message: Message):
|
87 |
+
"""Handler for the /start command."""
|
88 |
sender_name = message.from_user.first_name if message.from_user else "User"
|
89 |
+
logger.info(f"Received /start command from {sender_name} (ID: {message.from_user.id})")
|
|
|
90 |
|
91 |
+
welcome_text = f"Hello {sender_name}!\n"
|
92 |
+
welcome_text += "I am ready to manage your template.\n"
|
93 |
+
welcome_text += "Use /settemplate <your text> to set a new template.\n"
|
94 |
+
welcome_text += "Use /gettemplate to view the current template."
|
95 |
|
96 |
+
if current_template_content:
|
97 |
+
welcome_text += "\n\nA template is currently set."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
98 |
else:
|
99 |
+
welcome_text += "\n\nNo template is currently set."
|
|
|
100 |
|
101 |
+
await message.reply_text(welcome_text)
|
102 |
|
103 |
+
@app.on_message(filters.command("settemplate") & filters.private)
|
104 |
+
async def set_template_handler(client: Client, message: Message):
|
105 |
+
"""Handler for the /settemplate command."""
|
106 |
+
user_id = message.from_user.id
|
107 |
+
logger.info(f"Received /settemplate command from User ID: {user_id}")
|
|
|
|
|
|
|
108 |
|
109 |
+
if len(message.command) > 1:
|
110 |
+
new_template = message.text.split(" ", 1)[1].strip() # Get content after "/settemplate "
|
111 |
+
if new_template:
|
112 |
+
if await save_template_to_file(new_template):
|
113 |
+
await message.reply_text("✅ Template updated successfully!")
|
114 |
+
else:
|
115 |
+
await message.reply_text("❌ Failed to save the template. Please check the logs.")
|
116 |
+
else:
|
117 |
+
await message.reply_text("⚠️ Please provide content for the template. Usage: `/settemplate Your template text here`")
|
118 |
+
else:
|
119 |
+
await message.reply_text("ℹ️ Usage: `/settemplate Your template text here`")
|
120 |
+
|
121 |
+
@app.on_message(filters.command("gettemplate") & filters.private)
|
122 |
+
async def get_template_handler(client: Client, message: Message):
|
123 |
+
"""Handler for the /gettemplate command."""
|
124 |
+
user_id = message.from_user.id
|
125 |
+
logger.info(f"Received /gettemplate command from User ID: {user_id}")
|
126 |
+
|
127 |
+
if current_template_content:
|
128 |
+
response_text = f"📜 **Current Template:**\n\n{current_template_content}"
|
129 |
else:
|
130 |
+
response_text = "ℹ️ No template is currently set. Use `/settemplate <your text>` to set one."
|
131 |
+
await message.reply_text(response_text)
|
132 |
|
133 |
+
# --- Main Execution ---
|
134 |
+
async def main():
|
135 |
+
"""Main function to load initial data and start the bot."""
|
136 |
+
await load_template_from_file() # Load any existing template on startup
|
137 |
+
|
138 |
+
logger.info("Attempting to connect and start the bot...")
|
139 |
try:
|
140 |
+
await app.start()
|
141 |
+
me = await app.get_me()
|
142 |
+
logger.info(f"Bot started successfully as {me.first_name} (ID: {me.id})")
|
143 |
+
logger.info("Listening for messages...")
|
144 |
+
await asyncio.Event().wait() # Keep the bot running indefinitely
|
145 |
+
except (SessionPasswordNeeded, PhoneCodeInvalid, PhoneNumberInvalid, PasswordHashInvalid) as e:
|
146 |
+
logger.error(f"Authorization error: {type(e).__name__} - {e}. Your SESSION_STRING might be invalid or expired.")
|
147 |
+
except ConnectionError as e:
|
148 |
+
logger.error(f"Connection error: {e}. Check your network or Telegram's status.")
|
149 |
except Exception as e:
|
150 |
+
logger.error(f"An unexpected error occurred during bot startup or runtime: {type(e).__name__} - {e}", exc_info=True)
|
|
|
151 |
finally:
|
152 |
+
if app.is_connected:
|
153 |
+
logger.info("Stopping the bot...")
|
154 |
+
await app.stop()
|
155 |
+
logger.info("Bot stopped.")
|
156 |
+
else:
|
157 |
+
logger.info("Bot was not connected or already stopped.")
|
158 |
+
|
159 |
+
if __name__ == '__main__':
|
160 |
+
# Run the main function in the asyncio event loop
|
161 |
+
try:
|
162 |
+
asyncio.run(main())
|
163 |
+
except KeyboardInterrupt:
|
164 |
+
logger.info("Bot manually interrupted. Exiting...")
|
165 |
+
except Exception as e:
|
166 |
+
logger.critical(f"Critical error in main execution block: {e}", exc_info=True)
|
167 |
+
|