Skip to content

Commit a3cd6a6

Browse files
authored
Merge branch 'master' into main-dolly11
2 parents 3560d52 + 23fad6f commit a3cd6a6

17 files changed

Lines changed: 715 additions & 58 deletions

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ Bot for source engine games with a lot of commands:
66
* Play tts messages
77
* And much more!
88

9+
> [!IMPORTANT]
10+
> You need to run SMJSONAPI 1.1.x at minimum in order to have all features working properly
911
1012
## Requirements
1113
### Linux

config/config.json

Lines changed: 76 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,29 @@
2929
"Host": "127.0.0.1",
3030
"Port": 27019,
3131
"SampleRate": 22050,
32-
"Volume": 1.0,
33-
"Proxy": ""
32+
"Proxy": "",
33+
34+
"AudioParams":
35+
{
36+
"Volume":
37+
{
38+
"Default": 1.0,
39+
"Min": 0.0,
40+
"Max": 1.0
41+
},
42+
"Speed":
43+
{
44+
"Default": 1.0,
45+
"Min": 0.5,
46+
"Max": 2.0
47+
},
48+
"Pitch":
49+
{
50+
"Default": 1.0,
51+
"Min": 0.5,
52+
"Max": 2.0
53+
}
54+
}
3455
},
3556

3657
"GeoIP":
@@ -194,7 +215,35 @@
194215
"triggers": [
195216
{
196217
"command": "!say",
197-
"starts_with": true
218+
"starts_with": true,
219+
"force_default": true
220+
},
221+
{
222+
"command": "!speak",
223+
"starts_with": true,
224+
"force_default": true
225+
}
226+
],
227+
"parameters": {
228+
"default": {
229+
"language": "en",
230+
"tld": "com"
231+
}
232+
}
233+
},
234+
"TranslateSay":
235+
{
236+
"level": 2,
237+
"triggers": [
238+
{
239+
"command": "!tsay",
240+
"starts_with": true,
241+
"force_default": true
242+
},
243+
{
244+
"command": "!translate",
245+
"starts_with": true,
246+
"force_default": true
198247
}
199248
],
200249
"parameters": {
@@ -276,6 +325,9 @@
276325
},
277326
"Search": {
278327
"level": 0,
328+
"parameters":{
329+
"max_results": 30
330+
},
279331
"triggers": [
280332
{
281333
"command": "!search"
@@ -325,6 +377,27 @@
325377
},
326378
"URLFilter": {
327379
"level": 0
380+
},
381+
"MyInstantsSearch": {
382+
"level": 2,
383+
"Cooldown": 10,
384+
"triggers": [
385+
{
386+
"command": "!mi"
387+
},
388+
{
389+
"command": "!mis"
390+
}
391+
],
392+
"parameters": {
393+
"keywords_banned": [
394+
"earrape",
395+
"rape",
396+
"porn",
397+
"algorithm",
398+
"loud"
399+
]
400+
}
328401
}
329402
}
330403
}

config/triggers.json

Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,74 @@
11
[
2-
{"names": ["!tuturu"], "sound": "Tutturuu_v1.wav"},
3-
{"names": ["!tuturulist"], "sound": ["Tutturuu_v1.wav", "Tutturuu_v1.wav"]},
4-
{
5-
"names": ["!china"],
6-
"sound": ["china1.mp3", "china 2.mp3"]
7-
}
2+
{
3+
"names": [
4+
"!tuturu"
5+
],
6+
"sound": "Tutturuu_v1.wav"
7+
},
8+
{
9+
"names": [
10+
"#usa"
11+
],
12+
"sound": "usa.wav"
13+
},
14+
{
15+
"names": [
16+
"_life"
17+
],
18+
"sound": "life_sing.wav"
19+
},
20+
{
21+
"names": [
22+
"!tuturulist"
23+
],
24+
"sound": [
25+
"Tutturuu_v1.wav",
26+
"Tutturuu_v1.wav"
27+
]
28+
},
29+
{
30+
"names": [
31+
"!china"
32+
],
33+
"sound": [
34+
"china1.mp3",
35+
"china 2.mp3"
36+
]
37+
},
38+
{
39+
"names": [
40+
"$cash"
41+
],
42+
"sound": "cash.wav"
43+
},
44+
{
45+
"names": [
46+
"@call"
47+
],
48+
"sound": "call.wav"
49+
},
50+
{
51+
"names": [
52+
"%boost"
53+
],
54+
"sound": "boost.mp3"
55+
},
56+
{
57+
"names": [
58+
"^power"
59+
],
60+
"sound": "power.mp3"
61+
},
62+
{
63+
"names": [
64+
"&combo"
65+
],
66+
"sound": "combo.mp3"
67+
},
68+
{
69+
"names": [
70+
"*star"
71+
],
72+
"sound": "star.mp3"
73+
}
874
]

pyproject.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ dependencies = [
2222
"geoip2",
2323
"lxml",
2424
"python-magic",
25-
"yt-dlp @ git+https://github.com/yt-dlp/yt-dlp@master#egg=yt-dlp"
25+
"yt-dlp @ git+https://github.com/yt-dlp/yt-dlp@master#egg=yt-dlp",
26+
"translatepy",
27+
"requests"
2628
]
2729

2830
[project.scripts]
@@ -42,6 +44,7 @@ version = {file = "VERSION"}
4244
[project.optional-dependencies]
4345
dev = [
4446
"memory_profiler",
47+
"types-requests",
4548
"mypy",
4649
"ruff",
4750
]

requirements-dev.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,13 @@ yt-dlp @ git+https://github.com/yt-dlp/yt-dlp@5ff7a43623e3a92270f66a7e37b5fc53d7
111111
# via
112112
# -c requirements.txt
113113
# torchlight (pyproject.toml)
114+
types-requests
115+
# via requests
116+
translatepy==2.3
117+
# via
118+
# -c requirements.txt
119+
# torchlight (pyproject.toml)
120+
langdetect==1.0.9
121+
# via
122+
# -c requirements.txt
123+
# translatepy

requirements.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,7 @@ yarl==1.9.4
6060
# via aiohttp
6161
yt-dlp @ git+https://github.com/yt-dlp/yt-dlp@5ff7a43623e3a92270f66a7e37b5fc53d7a57fdf#egg=yt-dlp
6262
# via torchlight (pyproject.toml)
63+
translatepy==2.3
64+
# via torchlight (pyproject.toml)
65+
langdetect==1.0.9
66+
# via translatepy

src/torchlight/AudioClip.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,15 @@ def __init__(
3333
def __del__(self) -> None:
3434
self.logger.debug("~AudioClip()")
3535

36-
def Play(self, seconds: int | None = None, *args: Any) -> bool:
37-
return self.audio_player.PlayURI(self.uri, seconds, *args)
36+
def Play(
37+
self,
38+
seconds: int | None = None,
39+
*args: Any,
40+
volume: float | None = None,
41+
speed: float | None = None,
42+
pitch: float | None = None,
43+
) -> bool:
44+
return self.audio_player.PlayURI(self.uri, seconds, *args, volume=volume, speed=speed, pitch=pitch)
3845

3946
def Stop(self) -> bool:
4047
return self.audio_player.Stop()

src/torchlight/AudioManager.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,45 @@ def __init__(self, torchlight: Torchlight) -> None:
2121
def __del__(self) -> None:
2222
self.logger.info("~AudioManager()")
2323

24+
def ParseParams(self, trigger_params: dict, msg: str) -> dict[str, float]:
25+
this_config = self.torchlight.config.config.get("VoiceServer", {}).get("AudioParams", {})
26+
if not this_config:
27+
return trigger_params
28+
29+
params: dict[str, float] = {}
30+
for param in this_config:
31+
if param in trigger_params and trigger_params[param] is not None:
32+
params[param] = float(trigger_params[param])
33+
else:
34+
if isinstance(this_config[param], dict) and "Default" in this_config[param]:
35+
params[param] = float(this_config[param]["Default"])
36+
37+
msg_args = msg.split()
38+
for arg in msg_args:
39+
if "=" in arg:
40+
key, value = arg.split("=", 1)
41+
if not key or not value:
42+
continue
43+
44+
key = key.capitalize()
45+
if key not in this_config:
46+
continue
47+
48+
if isinstance(this_config[key], dict):
49+
val: float = 1.0
50+
try:
51+
val = float(value)
52+
except ValueError:
53+
continue
54+
55+
if "Min" not in this_config[key] or "Max" not in this_config[key]:
56+
continue
57+
58+
val = max(this_config[key]["Min"], min(val, this_config[key]["Max"]))
59+
params[key] = val
60+
61+
return params
62+
2463
def CheckLimits(self, player: Player) -> bool:
2564
level = player.admin.level
2665

src/torchlight/CommandHandler.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from torchlight.AccessManager import AccessManager
99
from torchlight.AudioManager import AudioManager
10-
from torchlight.Commands import BaseCommand, VoiceTrigger
10+
from torchlight.Commands import BaseCommand, Say, VoiceTrigger
1111
from torchlight.PlayerManager import Player, PlayerManager
1212
from torchlight.Torchlight import Torchlight
1313
from torchlight.TriggerManager import TriggerManager
@@ -41,6 +41,7 @@ def Setup(self) -> None:
4141
subklasses: list[type[Any]] = []
4242
subklasses.extend(BaseCommand.__subclasses__())
4343
subklasses.extend(VoiceTrigger.__subclasses__())
44+
subklasses.extend(Say.__subclasses__())
4445
for subklass in sorted(subklasses, key=lambda x: x.order, reverse=True):
4546
try:
4647
command = subklass(
@@ -69,10 +70,15 @@ def Reload(self) -> None:
6970
self.logger.error(traceback.format_exc())
7071
else:
7172
self.Setup()
73+
self.logger.info("Commands reloaded successfully")
7274

7375
# @profile
74-
async def HandleCommand(self, line: str, player: Player) -> int | None:
75-
message = line.split(sep=" ", maxsplit=1)
76+
async def HandleCommand(self, line: str, player: Player, from_menu: bool = False) -> int | None:
77+
if from_menu:
78+
message = line.split(sep=" ", maxsplit=2) # 2 because the !search command requires another arg for page
79+
else:
80+
message = line.split(sep=" ", maxsplit=1)
81+
7682
if len(message) < 2:
7783
message.append("")
7884
message[1] = message[1].strip()
@@ -83,10 +89,9 @@ async def HandleCommand(self, line: str, player: Player) -> int | None:
8389

8490
level = player.admin.level
8591

86-
if not message[0].startswith("!"):
92+
if not message[0].startswith(("!", "#", "_", "$", "@", "%", "^", "&", "*")):
8793
return None
8894

89-
self.logger.info(f"{player.name}: {message}")
9095
ret_message: str | None = None
9196
ret: int | None = None
9297
for command in self.commands:
@@ -125,6 +130,9 @@ async def HandleCommand(self, line: str, player: Player) -> int | None:
125130
ret = ret_temp
126131
else:
127132
ret = await command._func(message, player)
133+
if from_menu and command.__class__.__name__ == "VoiceTrigger" and ret:
134+
self.torchlight.SayChat(f"{{olive}}{player.name}: {{default}}{line}")
135+
128136
except Exception as e:
129137
self.logger.error(traceback.format_exc())
130138
self.torchlight.SayChat(f"Error: {str(e)}")

0 commit comments

Comments
 (0)