mirror of
https://github.com/kaaninchen/Gleiswechsel.git
synced 2026-09-17 16:52:47 +00:00
feat: voice_announcement
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
venv/
|
venv/
|
||||||
__pycache__/
|
__pycache__/
|
||||||
|
src/data/announcements/*
|
||||||
config.json
|
config.json
|
||||||
|
|||||||
@@ -35,8 +35,16 @@ uv pip install -r requirements.txt
|
|||||||
"vc": , // Server VC ID
|
"vc": , // Server VC ID
|
||||||
"random": true, // Random Zug aus der Anzeigetafel (true) oder erster Zug, der angezeigt wird (false)
|
"random": true, // Random Zug aus der Anzeigetafel (true) oder erster Zug, der angezeigt wird (false)
|
||||||
"emojis": true, // Emoji Namen beim Channel-Namen (true) oder nicht (false),
|
"emojis": true, // Emoji Namen beim Channel-Namen (true) oder nicht (false),
|
||||||
"announcemenents": true, // Announcements zur aktuellen Zugreise im VC-Kanal ja (true) oder nein (false)
|
|
||||||
"formatting": "┇", // VC Name. Davor steht der Emoji, danach der Zug.
|
"formatting": "┇", // VC Name. Davor steht der Emoji, danach der Zug.
|
||||||
|
"announcemenents": true, // Announcements zur aktuellen Zugreise im VC-Kanal ja (true) oder nein (false)
|
||||||
|
"voice_announcements": [ // siehe voice_announcements in der README
|
||||||
|
{
|
||||||
|
"enabled": false,
|
||||||
|
"stations": {
|
||||||
|
"general": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
"blacklist": [] // Blacklist für bestimmte Zug-Typen
|
"blacklist": [] // Blacklist für bestimmte Zug-Typen
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,6 +67,46 @@ Der Bot kann während der Zugreise Ankündigungen in den Textkanal vom Sprachkan
|
|||||||
- 3-5 Min vor Umstieg gibt es eine Ankündigung dafür
|
- 3-5 Min vor Umstieg gibt es eine Ankündigung dafür
|
||||||
- Info Embed bei Umstieg
|
- Info Embed bei Umstieg
|
||||||
|
|
||||||
|
#### voice_announcements:
|
||||||
|
⚠️ Announcements muss aktiviert sein
|
||||||
|
|
||||||
|
Der Bot kann 3-5 Min vor Umstieg den VC joinen und eine Audiodatei abspielen. Damit der Bot dazu die Möglichkeit hat muss ffmpeg installiert sein.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ sudo apt install ffmpeg # Debian/Ubuntu
|
||||||
|
|
||||||
|
$ brew install ffmpeg # macOS (brew)
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Außerdem sollte man über pip PyNaCl und davey installieren, sollte aber bereits automatisch durch [requirements.txt](requirements.txt) passiert sein.
|
||||||
|
|
||||||
|
```
|
||||||
|
"voice_announcements": [
|
||||||
|
{
|
||||||
|
"enabled": true,
|
||||||
|
"stations": {
|
||||||
|
"general": "general.aac",
|
||||||
|
"Hannover": "hannover.aac"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
```
|
||||||
|
|
||||||
|
Audiodateien werden in [src/data/announcements](src/data/announcements) platziert. In der Config wird dann der Name der Station (z.B. Hannover) zu dem Namen der Audiodatei (z.B. hannover.aac) bestimmt. Die Audiodatei braucht keinen Path.
|
||||||
|
|
||||||
|
Der Eintrag `general` meint die allgemeine Audiodatei, welche bei jeder Endstation (mit Ausnahme der zugewiesenen) spielt. Sollte man nur Audios bei eigenen zugewiesenen Endstationen abspielen wollen kann man `general` leerlassen, der bot skipped das ganze dann:
|
||||||
|
|
||||||
|
`"general": ""`
|
||||||
|
|
||||||
|
Es gibt außerdem die Möglichkeit, mehrere Audiodateien zu einer Endstation zuzuweisen. Der Bot sucht sich dann jedes mal wenn er den vc joined eine random aus. Dafür kann man den Endstationen eine Liste mit den Audiodateinamen zuweisen:
|
||||||
|
|
||||||
|
`json
|
||||||
|
"stations": {
|
||||||
|
"general": ["general_1.aac", "general_2.aac"]
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
#### blacklist:
|
#### blacklist:
|
||||||
Die Blacklist ist dafür gedacht, ganze Zugtypen zu ignorieren. Beispielsweise möchte man, dass der Bot keine ICE's, keine NightJets und keine European Sleepers auswählt, da diese sehr lange Strecken fahren und der VC somit lange unverändert bleibt:
|
Die Blacklist ist dafür gedacht, ganze Zugtypen zu ignorieren. Beispielsweise möchte man, dass der Bot keine ICE's, keine NightJets und keine European Sleepers auswählt, da diese sehr lange Strecken fahren und der VC somit lange unverändert bleibt:
|
||||||
```json
|
```json
|
||||||
|
|||||||
+9
-1
@@ -6,7 +6,15 @@
|
|||||||
"vc": ,
|
"vc": ,
|
||||||
"random": true,
|
"random": true,
|
||||||
"emojis": true,
|
"emojis": true,
|
||||||
"announcements": true,
|
|
||||||
"formatting": "┇",
|
"formatting": "┇",
|
||||||
|
"announcements": true,
|
||||||
|
"voice_announcements: [
|
||||||
|
{
|
||||||
|
"enabled": false,
|
||||||
|
"stations": {
|
||||||
|
"general": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
"blacklist": []
|
"blacklist": []
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,9 @@ aiohttp==3.14.1
|
|||||||
aiosignal==1.4.0
|
aiosignal==1.4.0
|
||||||
attrs==26.1.0
|
attrs==26.1.0
|
||||||
certifi==2026.6.17
|
certifi==2026.6.17
|
||||||
|
cffi==2.1.1
|
||||||
charset-normalizer==3.4.9
|
charset-normalizer==3.4.9
|
||||||
|
davey==0.1.6
|
||||||
frozenlist==1.8.0
|
frozenlist==1.8.0
|
||||||
idna==3.18
|
idna==3.18
|
||||||
multidict==6.7.1
|
multidict==6.7.1
|
||||||
@@ -11,6 +13,8 @@ numpy==2.5.1
|
|||||||
pandas==3.0.3
|
pandas==3.0.3
|
||||||
propcache==0.5.2
|
propcache==0.5.2
|
||||||
py-cord==2.8.0
|
py-cord==2.8.0
|
||||||
|
pycparser==3.0
|
||||||
|
pynacl==1.6.2
|
||||||
python-dateutil==2.9.0.post0
|
python-dateutil==2.9.0.post0
|
||||||
requests==2.34.2
|
requests==2.34.2
|
||||||
six==1.17.0
|
six==1.17.0
|
||||||
|
|||||||
+39
-1
@@ -2,6 +2,8 @@ import discord
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
import asyncio
|
import asyncio
|
||||||
import random
|
import random
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
from src.config import config
|
from src.config import config
|
||||||
from src.utils import random_connection, get_train_info, get_channel_formatting, logger
|
from src.utils import random_connection, get_train_info, get_channel_formatting, logger
|
||||||
from src.embeds import build_announcement_embed, build_info_embed
|
from src.embeds import build_announcement_embed, build_info_embed
|
||||||
@@ -14,8 +16,11 @@ async def announcer(bot, announcement):
|
|||||||
if len(voice_channel.members) > 0:
|
if len(voice_channel.members) > 0:
|
||||||
match announcement:
|
match announcement:
|
||||||
case "ende":
|
case "ende":
|
||||||
|
destination = current['destination']
|
||||||
embed = build_announcement_embed(
|
embed = build_announcement_embed(
|
||||||
f'Sehr geehrte Fahrgäste,\nIn wenigen Minuten erreichen wir {current['destination']}. Dieser Zug endet dort.\n\nWir wünschen Ihnen eine angenehme Weiterreise.\n\nVielen Dank für Ihr Vertrauen und auf Wiedersehen.')
|
f'Sehr geehrte Fahrgäste,\nIn wenigen Minuten erreichen wir {destination}. Dieser Zug endet dort.\n\nWir wünschen Ihnen eine angenehme Weiterreise.\n\nVielen Dank für Ihr Vertrauen und auf Wiedersehen.')
|
||||||
|
if config["voice_announcements"][0]["enabled"]:
|
||||||
|
await voice_announcer(bot, destination, voice_channel)
|
||||||
case "umstieg":
|
case "umstieg":
|
||||||
embed = build_info_embed()
|
embed = build_info_embed()
|
||||||
case _:
|
case _:
|
||||||
@@ -28,6 +33,39 @@ async def announcer(bot, announcement):
|
|||||||
logger(f"Announcement {announcement} wird geskipped, keiner da")
|
logger(f"Announcement {announcement} wird geskipped, keiner da")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
async def voice_announcer(bot: discord.Bot, destination, voice_channel):
|
||||||
|
voice_announcement_config = config["voice_announcements"][0]
|
||||||
|
voice_stations = voice_announcement_config["stations"]
|
||||||
|
|
||||||
|
if destination in voice_stations:
|
||||||
|
announcement_for = destination
|
||||||
|
else:
|
||||||
|
if voice_stations.get("general", "") == "":
|
||||||
|
return
|
||||||
|
announcement_for = "general"
|
||||||
|
|
||||||
|
if voice_stations.values() == list:
|
||||||
|
sound_file = random.choice(voice_stations.get(announcement_for))
|
||||||
|
else:
|
||||||
|
sound_file = voice_stations.get(announcement_for)
|
||||||
|
|
||||||
|
sound_path = f"src/data/announcements/{sound_file}"
|
||||||
|
if Path(sound_path).is_file() is False:
|
||||||
|
logger(f"Konnte Datei {sound_path} nicht finden", "error")
|
||||||
|
return
|
||||||
|
|
||||||
|
logger(f"VC wird betreten, spiele {sound_path}")
|
||||||
|
vc = await voice_channel.connect(timeout=15, reconnect=True)
|
||||||
|
audio_source = discord.FFmpegPCMAudio(sound_path)
|
||||||
|
|
||||||
|
if not vc.is_playing():
|
||||||
|
def after_playing(error):
|
||||||
|
if error:
|
||||||
|
logger(f"Player error: {error}", "error")
|
||||||
|
bot.loop.create_task(vc.disconnect())
|
||||||
|
logger("VC wird verlassen")
|
||||||
|
|
||||||
|
vc.play(audio_source, after=after_playing)
|
||||||
|
|
||||||
async def rename_vc(bot: discord.Bot, from_scheduler: bool = False):
|
async def rename_vc(bot: discord.Bot, from_scheduler: bool = False):
|
||||||
global current, train_name, train_info, train_type, _scheduled_task
|
global current, train_name, train_info, train_type, _scheduled_task
|
||||||
|
|||||||
Reference in New Issue
Block a user