iozxv commited on
Commit
47dbfc2
·
verified ·
1 Parent(s): 1df1e5b

Upload 6 files

Browse files
Files changed (2) hide show
  1. README.md +50 -5
  2. main.py +54 -28
README.md CHANGED
@@ -1,6 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
- license: apache-2.0
3
- title: C1
4
- sdk: docker
5
- emoji: 📈
6
- ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Hugging Face Space Pinger Bot 🚀
2
+
3
+ A Telegram bot built with **Pyrogram** and **FastAPI** to keep Hugging Face spaces alive by pinging them sequentially every 5 minutes. The database containing authorized users, admins, and space URLs is automatically created and synced to a Hugging Face dataset for persistent storage.
4
+
5
+ ## 🛠️ Required Secret Environment Variables
6
+
7
+ When deploying this bot on Hugging Face Spaces (or any Docker platform), you **MUST** configure the following variables in the Space settings (under **Variables and Secrets**):
8
+
9
+ 1. **`API_ID`**: The API ID for your Telegram application (get it from [my.telegram.org](https://my.telegram.org)).
10
+ 2. **`API_HASH`**: The API Hash for your Telegram application (get it from [my.telegram.org](https://my.telegram.org)).
11
+ 3. **`BOT_TOKEN`**: The Telegram Bot Token generated by [@BotFather](https://t.me/BotFather).
12
+ 4. **`ADMIN_ID`**: The numeric Telegram ID of the **Super Admin** (e.g., `123456789`). The Super Admin has highest authority (e.g., can remove admins).
13
+ 5. **`HF_TOKEN`**: A Hugging Face User Access Token with **WRITE** permissions (generate it under your Hugging Face account settings at [huggingface.co/settings/tokens](https://huggingface.co/settings/tokens)).
14
+ 6. **`HF_DATASET_URL`**: The full URL of your Hugging Face dataset repository (e.g. `https://huggingface.co/datasets/your_username/your_dataset_name` or simply the repository ID like `your_username/your_dataset_name`). The bot will automatically create this dataset if it doesn't already exist and maintain `database.json` within it.
15
+
16
  ---
17
+
18
+ ## 🤖 Available Commands
19
+
20
+ ### 💬 Public Commands (Anyone)
21
+ - `/id` - View your Telegram User ID (used to request authorization).
22
+ - `/start` - Displays a simple welcome message.
23
+ - `/help` - Explains what the bot does.
24
+ - `/commands` - List commands matching the caller's authorization level.
25
+
26
+ ### 👤 Authorized User Commands
27
+ - `/add <hf_url>` - Register a Hugging Face Space URL. (You can also just send a raw Hugging Face URL directly, and the bot will normalize and register it automatically).
28
+ - `/remove <hf_url>` - Remove a Space URL you registered.
29
+ - `/list_url` - List the Space URLs that *you* registered.
30
+
31
+ ### 👮 Admin Commands
32
+ - `/add_user <user_id>` - Authorize a user to register and manage their own URLs.
33
+ - `/remove_user <user_id>` - Deauthorize a user.
34
+ - `/add_admin <user_id>` - Promote a user to Admin.
35
+ - `/list_url` - List **ALL** registered Space URLs in the system along with who registered them.
36
+ - `/list` - List all Admins and Users (excluding the Super Admin).
37
+
38
+ ### 👑 Super Admin Commands
39
+ - `/remove_admin <user_id>` - Demote an Admin back to a regular user.
40
+ - `/list` - List the Super Admin, all Admins, and all Users.
41
+
42
+ ---
43
+
44
+ ## 🐳 Deployment to Hugging Face Spaces
45
+
46
+ 1. Create a new Space on Hugging Face: [huggingface.co/new-space](https://huggingface.co/new-space).
47
+ 2. Choose **Docker** as the SDK.
48
+ 3. Select **Blank** (or any Docker template).
49
+ 4. Go to the Space **Settings** page and add the **Secrets** listed above.
50
+ 5. Push the repository files (`Dockerfile`, `requirements.txt`, `config.py`, `database.py`, `main.py`) to the Space.
51
+ 6. The space will automatically build the Docker image, run the FastAPI web server on port `7860`, launch the Telegram bot, and begin the sequential 5-minute pinger loop.
main.py CHANGED
@@ -141,10 +141,10 @@ async def start_command(client, message):
141
  user_id = message.from_user.id
142
  if not database.is_authorized(user_id):
143
  await message.reply_text(
144
- " **Unauthorized User**\n\n"
145
- f"You are unauthorized to use the bot.\n"
146
- f"Your ID: `{user_id}`\n\n"
147
- "Tell an admin to add you."
148
  )
149
  return
150
 
@@ -232,20 +232,25 @@ async def add_url_command(client, message):
232
  return
233
 
234
  if len(message.command) < 2:
235
- await message.reply_text("Usage: `/add <hf_space_url>`\n\nExample:\n`/add https://huggingface.co/spaces/iozxv/C1`")
236
  return
237
 
238
- url_input = message.command[1]
239
- try:
240
- success, normalized = database.add_url(url_input, user_id)
241
- if success:
242
- await message.reply_text(f"✅ **Success!** URL normalized and added to ping list:\n`{normalized}`")
243
- else:
244
- await message.reply_text(f"⚠️ This space is already in the ping list:\n`{normalized}`")
245
- except ValueError as e:
246
- await message.reply_text(f"❌ **Invalid URL:** {str(e)}")
247
- except Exception as e:
248
- await message.reply_text(f"❌ **Error:** {str(e)}")
 
 
 
 
 
249
 
250
  @bot.on_message(filters.command("remove"))
251
  async def remove_url_command(client, message):
@@ -294,9 +299,21 @@ async def list_url_command(client, message):
294
  # If admin or super admin, show who added it. Otherwise, just list URLs
295
  if database.is_admin(user_id):
296
  response = f"🔗 **All Monitored Space URLs ({len(urls_data)}):**\n\n"
 
 
 
297
  for item in urls_data:
298
- added_by_display = database.get_user_display(item["added_by"])
299
- response += f"- `{item['url']}`\n Added by: {added_by_display}\n\n"
 
 
 
 
 
 
 
 
 
300
  else:
301
  response = f"🔗 **Your Monitored Space URLs ({len(urls_data)}):**\n\n"
302
  for item in urls_data:
@@ -482,16 +499,25 @@ async def handle_text_message(client, message):
482
  await message.reply_text("❌ You are not authorized to add URLs. Ask an Admin to authorize your ID.")
483
  return
484
 
485
- try:
486
- success, normalized = database.add_url(text, user_id)
487
- if success:
488
- await message.reply_text(f"✅ **URL Detected & Added to Ping List!**\nNormalized: `{normalized}`\nInterval: 5 minutes")
489
- else:
490
- await message.reply_text(f"⚠️ This space is already in the ping list:\n`{normalized}`")
491
- except ValueError as e:
492
- await message.reply_text(f"❌ **Invalid URL:** {str(e)}")
493
- except Exception as e:
494
- await message.reply_text(f" **Error:** {str(e)}")
 
 
 
 
 
 
 
 
 
495
 
496
  # ==================== MAIN EXECUTION ====================
497
 
 
141
  user_id = message.from_user.id
142
  if not database.is_authorized(user_id):
143
  await message.reply_text(
144
+ "👋 **Hello! Welcome to the Hugging Face Space Pinger Bot.** 🚀\n\n"
145
+ "You are currently unauthorized to use this bot.\n"
146
+ f"🔑 Your ID: `{user_id}`\n\n"
147
+ "Please contact an admin to allow you access."
148
  )
149
  return
150
 
 
232
  return
233
 
234
  if len(message.command) < 2:
235
+ await message.reply_text("Usage: `/add <hf_space_url1> <hf_space_url2> ...`\n\nExample:\n`/add https://huggingface.co/spaces/iozxv/C1`")
236
  return
237
 
238
+ urls_input = message.command[1:]
239
+ results = []
240
+
241
+ for url_input in urls_input:
242
+ try:
243
+ success, normalized = database.add_url(url_input, user_id)
244
+ if success:
245
+ results.append(f"✅ Added: `{normalized}`")
246
+ else:
247
+ results.append(f"⚠️ Already exists: `{normalized}`")
248
+ except ValueError as e:
249
+ results.append(f"❌ Invalid: {url_input} - {str(e)}")
250
+ except Exception as e:
251
+ results.append(f"❌ Error: {url_input} - {str(e)}")
252
+
253
+ await message.reply_text("\n".join(results))
254
 
255
  @bot.on_message(filters.command("remove"))
256
  async def remove_url_command(client, message):
 
299
  # If admin or super admin, show who added it. Otherwise, just list URLs
300
  if database.is_admin(user_id):
301
  response = f"🔗 **All Monitored Space URLs ({len(urls_data)}):**\n\n"
302
+
303
+ # Group by user
304
+ grouped = {}
305
  for item in urls_data:
306
+ added_by = item["added_by"]
307
+ if added_by not in grouped:
308
+ grouped[added_by] = []
309
+ grouped[added_by].append(item["url"])
310
+
311
+ for user, urls in grouped.items():
312
+ user_display = database.get_user_display(user)
313
+ response += f"👤 **Added by: {user_display}**\n"
314
+ for u in urls:
315
+ response += f"- `{u}`\n"
316
+ response += "\n"
317
  else:
318
  response = f"🔗 **Your Monitored Space URLs ({len(urls_data)}):**\n\n"
319
  for item in urls_data:
 
499
  await message.reply_text("❌ You are not authorized to add URLs. Ask an Admin to authorize your ID.")
500
  return
501
 
502
+ # Split text into possible multiple URLs
503
+ words = text.split()
504
+ potential_urls = [w for w in words if "huggingface.co/spaces" in w or "hf.space" in w]
505
+
506
+ results = []
507
+ for url_input in potential_urls:
508
+ try:
509
+ success, normalized = database.add_url(url_input, user_id)
510
+ if success:
511
+ results.append(f" Added: `{normalized}`")
512
+ else:
513
+ results.append(f"⚠️ Already exists: `{normalized}`")
514
+ except ValueError as e:
515
+ results.append(f"❌ Invalid: {url_input} - {str(e)}")
516
+ except Exception as e:
517
+ results.append(f"❌ Error: {url_input} - {str(e)}")
518
+
519
+ if results:
520
+ await message.reply_text("\n".join(results))
521
 
522
  # ==================== MAIN EXECUTION ====================
523