pushing new things, changelog.txt might help.
Some checks are pending
Build-nightly / docker (push) Waiting to run

This commit is contained in:
Umiko 2025-05-14 04:00:49 +07:00
parent edd542f890
commit f0cedb1dff
4 changed files with 145 additions and 71 deletions

View File

@ -22,6 +22,100 @@ A media streaming bot for TeamTalk.
* On Linux run ./TTMediaBot.sh; * On Linux run ./TTMediaBot.sh;
* On Windows run python TTMediaBot.py directly. * On Windows run python TTMediaBot.py directly.
## Scheduler Commands
TTMediaBot includes a built-in scheduler system (like `cron`) that allows you to schedule bot commands to be executed automatically at specific times.
### Enable or disable the scheduler
```bash
cr toggle
```
Use this to turn the scheduler **on or off**. It must be enabled before any scheduled tasks can run.
---
### Add a scheduled command
```bash
cr add <cron expression>|<command>
```
This adds a new scheduled task. The command should be split using `|`:
* The **left side** is the cron time expression.
* The **right side** is the bot command to run.
#### Examples:
```bash
cr add */15 * * * *|p something just like this
```
Every 15 minutes, the bot will play the song **"Something Just Like This"** using the `p` command.
```bash
cr add 0 3 * * *|rsrs
```
Every day at 3:00 AM, the bot will **restart itself** using the `rsrs` command.
---
### Remove a scheduled command
```bash
cr rm <task number>
```
Removes a task from the scheduler. You can find the task number using `cr ls`.
Example:
```bash
cr rm 1
```
This removes task number 1.
---
### View all scheduled tasks
```bash
cr ls
```
This command shows all currently scheduled tasks, including:
* Cron expression
* Command
* Last run time
* Next run time
---
### Cron Expression Guide (Quick)
### 📝 Cron Expression Guide (Quick)
| Field | Allowed Values | Description |
|---------------|---------------------------|-----------------------|
| Minute | 059 | Minute of the hour |
| Hour | 023 | Hour of the day |
| Day of month | 131 | Day of the month |
| Month | 112 | Month of the year |
| Day of week | 06 or SunSat | Day of the week |
**Example:**
- `*/10 * * * *` → Every 10 minutes
- `0 9 * * 1-5` → At 9:00 AM, Monday to Friday
For example:
* `*/10 * * * *` = every 10 minutes
* `0 9 * * 1-5` = every weekday at 9:00 AM
### Running in Docker ### Running in Docker
You can also run the bot in a Docker container. You can also run the bot in a Docker container.
First of all, You should build an image from the provided Dockerfile: First of all, You should build an image from the provided Dockerfile:

View File

@ -12,25 +12,37 @@ import portalocker
if TYPE_CHECKING: if TYPE_CHECKING:
from bot.player.track import Track from bot.player.track import Track
cache_data_type = Dict[str, Any] cache_data_type = Dict[str, Any]
class Cache: class Cache:
def __init__(self, cache_data: cache_data_type): def __init__(self, cache_data: cache_data_type):
self.cache_version = cache_data["cache_version"] if "cache_version" in cache_data else CacheManager.version self.cache_version = cache_data.get("cache_version", CacheManager.version)
self.recents: deque[Track] = ( self.recents: deque[Track] = deque(
cache_data["recents"] cache_data.get("recents", []),
if "recents" in cache_data maxlen=app_vars.recents_max_lenth
else deque(maxlen=app_vars.recents_max_lenth)
)
self.favorites: Dict[str, List[Track]] = (
cache_data["favorites"] if "favorites" in cache_data else {}
) )
self.favorites: Dict[str, List[Track]] = cache_data.get("favorites", {})
@property @property
def data(self): def data(self):
return {"cache_version": self.cache_version, "recents": self.recents, "favorites": self.favorites} # Pastikan semua track di-recents & favorites adalah versi raw (non-stream)
sanitized_recents = deque(
(track.get_raw() if hasattr(track, "get_raw") else track)
for track in self.recents
)
sanitized_favorites = {
user: [
track.get_raw() if hasattr(track, "get_raw") else track
for track in tracks
]
for user, tracks in self.favorites.items()
}
return {
"cache_version": self.cache_version,
"recents": sanitized_recents,
"favorites": sanitized_favorites
}
class CacheManager: class CacheManager:

View File

@ -1,4 +1,9 @@
This change log is written to find out the changes that have been made by Pandora, and the source code still refers to TTMediaBot. This change log is written to find out the changes that have been made by Pandora, and the source code still refers to TTMediaBot.
5/14/2025
Added entry for scheduler command on readme.md
Fixed file caching:
1. Favorite list is now saving the original link , instead of internal googlevideo link.
2. Recents now store the original link (e.g. YouTube URL), so the stream will no longer expire.
5/13/2025 5/13/2025
Added more information to the client name. useless but why not? Added more information to the client name. useless but why not?

85
dd.py
View File

@ -1,69 +1,32 @@
import logging
import sys
import os import os
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from bot.TeamTalk import TeamTalk, Event, EventType, MessageType
# Load the watchlist from a file (watchlist.txt)
def load_watchlist(): def load_watchlist():
"""Load the watchlist of prohibited words."""
watchlist = []
try: try:
with open("watchlist.txt", "r") as f: with open("watchlist.txt", "r", encoding="utf-8") as f:
watchlist = [line.strip().lower() for line in f.readlines()] return [line.strip().lower() for line in f if line.strip()]
except FileNotFoundError: except FileNotFoundError:
logging.error("Watchlist file not found. Please create 'watchlist.txt'.") return []
return watchlist
def on_user_joined(user, bot):
# Check if the user's message contains any prohibited words
def contains_prohibited_word(message: str, watchlist: list) -> bool:
"""Check if a message contains any prohibited words from the watchlist."""
for word in watchlist:
if word in message.lower():
return True
return False
# Kick the user and broadcast the reason
def kick_user_and_broadcast(ttclient: TeamTalk, user_name: str) -> None:
"""Kick the user and broadcast a message about the kick."""
ttclient.kick_user(user_name)
broadcast_message = f"{user_name} has been kicked for using prohibited language."
ttclient.broadcast_message(broadcast_message)
logging.info(f"Kicked user: {user_name} for prohibited message.")
# Event handler for a user text message
def on_user_text_message(event: Event, ttclient: TeamTalk):
"""Handle the event when a user sends a text message."""
watchlist = load_watchlist()
message = event.message.text
user_name = event.message.sender.name
# Check if the message contains a prohibited word
if contains_prohibited_word(message, watchlist):
logging.info(f"User {user_name} used a prohibited word. Kicking user...")
kick_user_and_broadcast(ttclient, user_name)
else:
logging.info(f"User {user_name}'s message: '{message}' is clean.")
# Map event types to their respective handler functions
event_handlers = {
EventType.USER_TEXT_MESSAGE: on_user_text_message,
# You can add more event handlers here for different event types.
}
def run_event_handler(event: Event, ttclient: TeamTalk):
"""Run the appropriate event handler based on the event type."""
try: try:
event_handler = event_handlers.get(event.event_type) bot_channel_id = bot.ttclient.get_my_channel_id()
if event_handler: if user.channelid == bot_channel_id:
event_handler(event, ttclient) welcome_msg = f"👋 Hello {user.nickname}, welcome to the channel!"
else: bot.send_channel_message(welcome_msg)
logging.info(f"No handler for event type: {event.event_type.name}")
except Exception as e: except Exception as e:
logging.error(f"Error in event handling: {e}") print(f"[ERROR] Failed to send welcome message: {e}")
def on_user_loggedin(user, bot):
try:
watchlist = load_watchlist()
username = user.nickname.lower()
for badname in watchlist:
if badname in username:
reason = "🚫 You are kicked because your nickname contains inappropriate words."
bot.send_private_message(user.userid, reason)
bot.kick_user(user.userid, bot.ttclient.get_my_channel_id())
print(f"[INFO] Kicked user: {user.nickname}")
break
except Exception as e:
print(f"[ERROR] Failed to check user login: {e}")