Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 16 additions & 7 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@ on:
push:
branches:
- master
- main
paths:
- "**/*.py"
pull_request:
branches:
- master
- main
paths:
- "**/*.py"

Expand All @@ -34,16 +32,27 @@ jobs:
- name: Install dependencies
run: |
python -m pip install uv
uv venv .venv && . .venv/bin/activate
echo PATH=$PATH >> $GITHUB_ENV
uv venv .venv
echo "$PWD/.venv/bin" >> $GITHUB_PATH
source .venv/bin/activate
uv pip install -r requirements.txt -r requirements-dev.txt
uv pip install -e .

- name: Linting and formatting with ruff
- name: Format code with ruff
run: |
ruff check .
ruff format . --diff
ruff format .

- name: Lint and fix with ruff
run: |
ruff check --fix .

- name: Check typing with mypy
run: |
mypy --install-types --non-interactive --show-traceback

- name: Commit formatting changes
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: "Apply automatic ruff formatting fixes"
file_pattern: "src/**/*.py"
28 changes: 28 additions & 0 deletions config/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,18 @@
}
]
},
"StopAll": {
"level": 10,
"triggers": [
{
"command": "!stopall",
"starts_with": false
},
{
"command": "!forcestopall"
}
]
},
"Say":
{
"level": 2,
Expand All @@ -204,6 +216,21 @@
}
}
},
"TranslateSay": {
"level": 2,
"triggers": [
{
"command": "!tsay",
"starts_with": true
}
],
"parameters": {
"default": {
"language": "en",
"tld": "com"
}
}
},
"PlayMusic": {
"level": 2,
"triggers": [
Expand All @@ -224,6 +251,7 @@
],
"parameters": {
"proxy": "",
"cookies": "",
"keywords_banned": [
"earrape",
"rape",
Expand Down
4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ dependencies = [
"geoip2",
"lxml",
"python-magic",
"yt-dlp @ git+https://github.com/yt-dlp/yt-dlp@master#egg=yt-dlp"
"yt-dlp @ git+https://github.com/yt-dlp/yt-dlp@master#egg=yt-dlp",
"translatepy",
"langdetect"
]

[project.scripts]
Expand Down
9 changes: 9 additions & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,12 @@ yt-dlp @ git+https://github.com/yt-dlp/yt-dlp@5ff7a43623e3a92270f66a7e37b5fc53d7
# via
# -c requirements.txt
# torchlight (pyproject.toml)
translatepy==2.3
# via
# -c requirements.txt
# torchlight (pyproject.toml)

langdetect==1.0.9
# via
# -c requirements.txt
# translatepy
8 changes: 7 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,11 @@ urllib3==2.1.0
# via requests
yarl==1.9.4
# via aiohttp
yt-dlp @ git+https://github.com/yt-dlp/yt-dlp@5ff7a43623e3a92270f66a7e37b5fc53d7a57fdf#egg=yt-dlp
yt-dlp>=2024.04.09
# via torchlight (pyproject.toml)

translatepy==2.3
# via torchlight (pyproject.toml)

langdetect==1.0.9
# via translatepy
1 change: 1 addition & 0 deletions src/torchlight/AudioClip.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ def Play(self, seconds: int | None = None, *args: Any) -> bool:
return self.audio_player.PlayURI(self.uri, seconds, *args)

def Stop(self) -> bool:
self.logger.info(f"AudioClip.Stop called for {self.uri}")
return self.audio_player.Stop()

def OnPlay(self) -> None:
Expand Down
78 changes: 58 additions & 20 deletions src/torchlight/AudioManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,35 +60,73 @@ def CheckLimits(self, player: Player) -> bool:

def Stop(self, player: Player, extra: str) -> None:
level = player.admin.level

stop_level = self.anti_spam.config.get("StopLevel", 3)
self.logger.info(f"Stop called by {player.name} (level {level}), extra='{extra}'")
self.logger.info(f"Currently playing {len(self.audio_clips)} audio clip(s)")
if not self.audio_clips:
self.torchlight.SayPrivate(player, "No audio is currently playing.")
return
stopped_count = 0
for audio_clip in self.audio_clips[:]:
if extra and extra.lower() not in audio_clip.player.name.lower():
clip_player = audio_clip.player
clip_level = audio_clip.level
self.logger.info(f"Checking clip: {clip_player.name} (level {clip_level}) playing {audio_clip.uri}")
if extra and extra.lower() not in clip_player.name.lower():
continue

if not level or (level < audio_clip.level and level < self.anti_spam.config["StopLevel"]):
can_stop = False
reason = ""
if player.user_id == clip_player.user_id:
can_stop = True
reason = "stopped own sound"
elif level >= stop_level:
can_stop = True
reason = f"admin (level {level} >= {stop_level})"
elif level > clip_level:
can_stop = True
reason = f"higher level (level {level} > {clip_level})"
else:
audio_clip.stops.add(player.user_id)

if len(audio_clip.stops) >= 3:
audio_clip.Stop()
self.torchlight.SayPrivate(audio_clip.player, "Your audio clip was stopped.")
if player != audio_clip.player:
self.torchlight.SayPrivate(
player,
f'Stopped "{audio_clip.player.name}"({audio_clip.player.user_id}) audio clip.',
)
votes_needed = 3 - len(audio_clip.stops)
if votes_needed <= 0:
can_stop = True
reason = "vote passed"
else:
self.torchlight.SayPrivate(
player,
f"This audio clip needs {3 - len(audio_clip.stops)} more !stop's.",
f"Need {votes_needed} more !stop(s) to stop {clip_player.name}'s sound.",
)
continue
if can_stop:
self.logger.info(f"Stopping clip: {reason}")
if audio_clip.Stop():
stopped_count += 1
if player.user_id != clip_player.user_id:
self.torchlight.SayPrivate(
clip_player,
f"Your audio was stopped by {player.name}.",
)
if stopped_count > 0:
if stopped_count == 1:
self.torchlight.SayPrivate(player, f"Stopped {stopped_count} audio clip.")
else:
self.torchlight.SayPrivate(player, f"Stopped {stopped_count} audio clips.")
elif not extra:
self.torchlight.SayPrivate(
player,
"No audio clips matched your request. Use '!stop playername' to target specific player.",
)

def StopAll(self) -> None:
self.logger.info("Force stopping all audio clips from all users.")
# Copy the list to avoid modification during iteration
for audio_clip in self.audio_clips[:]:
try:
audio_clip.Stop()
self.torchlight.SayPrivate(audio_clip.player, "Your audio clip was stopped.")
if player != audio_clip.player:
self.torchlight.SayPrivate(
player,
f'Stopped "{audio_clip.player.name}"({audio_clip.player.user_id}) audio clip.',
)
except Exception as e:
self.logger.error(f"Error stopping audio clip: {e}")
self.torchlight.SayPrivate(audio_clip.player, "All audio has been force-stopped by admin.")
# Clear the list immediately
self.audio_clips.clear()

def AudioClip(
self,
Expand Down
6 changes: 4 additions & 2 deletions src/torchlight/CommandHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ def Reload(self) -> None:
self.logger.error(traceback.format_exc())
else:
self.Setup()
self.logger.info("Commands reloaded successfully")

# @profile
async def HandleCommand(self, line: str, player: Player) -> int | None:
Expand All @@ -83,8 +84,9 @@ async def HandleCommand(self, line: str, player: Player) -> int | None:

level = player.admin.level

if not message[0].startswith("!"):
return None
# allowed_prefixes = ["!", "_", "#", "*", "$", "*", "&", "^", "~", "+"]
# if not any(message[0].startswith(prefix) for prefix in allowed_prefixes):
# return None

self.logger.info(f"{player.name}: {message}")
ret_message: str | None = None
Expand Down
Loading