diff --git a/.github/voice_announcements_visualized.png b/.github/voice_announcements_visualized.png deleted file mode 100644 index 6d87556..0000000 Binary files a/.github/voice_announcements_visualized.png and /dev/null differ diff --git a/README.md b/README.md index bd32f75..6a90c76 100644 --- a/README.md +++ b/README.md @@ -187,6 +187,8 @@ I highly recommend keeping `"OTHER"` blacklisted, if the API doesn't know what t - `timezone` is timezone in the IANA timezone format. You can [look it up here](https://www.addevent.com/c/documentation/tools/time-zone-lookup) ##### announcements + +##### `text_announcements:` The bot can send a text announcement in the voice chat at the start/end of a trip. At the end of a trip, it would send this embed: @@ -196,37 +198,10 @@ It will also send the `/info` embed at the start of a new connection with inform To reduce spam, the bot will only send announcements if someone is in the voice chat -##### voice -⚠️ Requires `announcements` to be set to enabled - -The bot can join the voice chat, play an audio file, and leave at various points of your trip. You have to have [FFmpeg](https://www.ffmpeg.org/) installed for this to work. - -Place the audio file of your desired station in [src/data/announcements](src/data/announcements/). Then, define the stations name with the name of the audio file in either `end_stations` or `stops`. The path will be autocompleted to [src/data/announcements](src/data/announcements/). The station name has to be EXACT, if you're unsure then [get the name through the helper script](#stations) - -`end_stations` is for audio files that should play at the end of your trip, and `stops` is for audio files that should play while the train is passing through your desired station. If you set the name of a station to `general`, then the bot will always play that file before the trip ends/a new stop has been reached. - -I'm hoping that I didn't explain this too complicated. Here's an example to visualize this: - -![example_files](.github/voice_announcements_visualized.png) - -```json - "announcements": { - "enabled": true, - "voice": [ - { - "enabled": true, - "end_stations": { - "general": "general.aac", - "Hannover Hbf": "hannover.aac" - }, - "stops": { - "Amsterdam, Noorderpark": "noorderpark.aac" - } - } - ] - }, -``` +##### `voice_announcements:` +The bot can join the voice chat, play an audio file, and disconnect from the voice chat, at various points of your trip. You have to have [FFmpeg](https://www.ffmpeg.org/) installed for this to work. +Place the audio file of your desired station in [src/data/announcements](src/data/announcements/) with the EXACT name of the station. The bot will automatically check if an audio file with the stations name exists, and if it does, play it. #### http - `"user_agent"`: The user agent of the bot for the API. If you don't know what that is, then you shouldn't have to change that. Even if you do, you still probably don't have to diff --git a/config.json.example b/config.json.example index 3243519..8b1f231 100644 --- a/config.json.example +++ b/config.json.example @@ -24,17 +24,8 @@ "timezone": "Europe/Berlin" }, "announcements": { - "enabled": true, - "voice": [ - { - "enabled": false, - "end_stations": { - "general": "general.aac", - }, - "stops": { - } - } - ] + "text_announcements": true, + "voice_announcements": false }, "http": { "user_agent": "Gleiswechsel-Discord-Bot" diff --git a/src/api/transitous.py b/src/api/transitous.py index 8ce91ad..0a4f92c 100644 --- a/src/api/transitous.py +++ b/src/api/transitous.py @@ -243,7 +243,7 @@ def get_trip_details(random_connection: dict | None) -> dict | None: arrival_dt = parse_iso(end_time) departure_dt = parse_iso(start_time) - train_name = get_train_name(display_name, mode) + train_name = get_train_name(display_name, mode) # used by lang if train_from == from_station: long_name = long_name_lang.train_from() else: diff --git a/src/config.py b/src/config.py index cae1cf1..898b6cc 100644 --- a/src/config.py +++ b/src/config.py @@ -21,16 +21,10 @@ class ConnectionsConfig: max_wait_time: Optional[int] = None max_duration: Optional[int] = None -@dataclass -class VoiceAnnouncementConfig: - enabled: bool - end_stations: dict[str, str] - stops: dict[str, str] - @dataclass class AnnouncementConfig: - enabled: bool - voice: list[VoiceAnnouncementConfig] + text_announcements: bool + voice_announcements: bool @dataclass class HttpConfig: @@ -50,10 +44,7 @@ def _load_config() -> Config: return Config( discord=DiscordConfig(**raw["discord"]), connections=ConnectionsConfig(**raw["connections"]), - announcements=AnnouncementConfig( - enabled=raw["announcements"]["enabled"], - voice=[VoiceAnnouncementConfig(**v) for v in raw["announcements"]["voice"]], - ), + announcements=AnnouncementConfig(**raw["announcements"]), http=HttpConfig(**raw["http"]), ) diff --git a/src/dc/handlers.py b/src/dc/handlers.py index 39958f9..0fff4c3 100644 --- a/src/dc/handlers.py +++ b/src/dc/handlers.py @@ -39,30 +39,23 @@ async def rename_vc(bot: discord.Bot, voice_channel, from_scheduler: bool = Fals formatting = channel_formatting(mode) await voice_channel.edit(name=f"{formatting}{long_name}") await voice_channel.set_status(None) - start_next_stop_updates(bot, voice_channel) - + start_next_stop_updates(voice_channel) logger(f"Updated channel name!") await announcer("transfer", voice_channel) - _scheduled_task = asyncio.create_task(_schedule_next_transfer(bot, trip["arrival_dt"], voice_channel, trip["to"])) async def announcer(announcement: str, voice_channel: discord.VoiceChannel, destination = None): from src.dc.embeds import build_info_embed, build_announcement_embed - announcements_enabled = config.announcements.enabled - voice_announcement_enabled = config.announcements.voice[0].enabled + announcements_enabled = config.announcements.text_announcements if announcements_enabled: if len(voice_channel.members) > 0: match announcement: case "end_of_connection": - if voice_announcement_enabled: - announcement_status = await voice_announcer(destination, voice_channel, "end_stations") - if announcement_status: - return - embed = build_announcement_embed(lang.embeds.announcement.end_of_connection.message()) + embed = build_announcement_embed(lang.embeds.announcement.end_of_connection.message()) case "transfer": embed = build_info_embed() case _: @@ -72,8 +65,8 @@ async def announcer(announcement: str, voice_channel: discord.VoiceChannel, dest if embed: await voice_channel.send(embed=embed) -async def voice_announcer(destination: str, voice_channel: discord.VoiceChannel, type_announcement: str) -> bool: - sound_path = get_sound_path(destination=destination, type_announcement=type_announcement) +async def voice_announcer(station: str, voice_channel: discord.VoiceChannel) -> bool: + sound_path = get_sound_path(station=station) if sound_path is None: return False @@ -121,7 +114,7 @@ async def _schedule_next_transfer(bot: discord.Bot, arrival_dt: datetime, voice_ logger("Train arrived, searching for a new connection....") await rename_vc(bot, voice_channel, from_scheduler=True) -async def _update_next_loop(bot: discord.Bot, voice_channel: discord.VoiceChannel): +async def _update_next_loop(voice_channel: discord.VoiceChannel): global trip try: if trip is None: @@ -145,7 +138,8 @@ async def _update_next_loop(bot: discord.Bot, voice_channel: discord.VoiceChanne status_text = f"{lang.embeds.info.next_stop()}: {next_stop_str}" await voice_channel.set_status(status_text, reason="Next stop status") - await voice_announcer(next_stop_str, voice_channel, type_announcement="stops") + if config.announcements.voice_announcements: + await voice_announcer(next_stop_str, voice_channel) wait_seconds = (next_stop["arrival"] - datetime.now(LOCAL_TZ)).total_seconds() if wait_seconds > 0: @@ -154,10 +148,10 @@ async def _update_next_loop(bot: discord.Bot, voice_channel: discord.VoiceChanne except asyncio.CancelledError: raise -def start_next_stop_updates(bot: discord.bot, voice_channel: discord.VoiceChannel): +def start_next_stop_updates(voice_channel: discord.VoiceChannel): global _next_stop_task if _next_stop_task is not None and not _next_stop_task.done(): _next_stop_task.cancel() - _next_stop_task = asyncio.create_task(_update_next_loop(bot, voice_channel)) \ No newline at end of file + _next_stop_task = asyncio.create_task(_update_next_loop(voice_channel)) \ No newline at end of file diff --git a/src/utils.py b/src/utils.py index e4edb9e..0976cf8 100644 --- a/src/utils.py +++ b/src/utils.py @@ -123,31 +123,14 @@ def get_operator_metadata(agency: str, route_color: str, mode: str) -> dict: "slogans": slogans } -def get_sound_path(destination, type_announcement: str) -> str | None: - if type_announcement == "end_stations": - voice_stations = config.announcements.voice[0].end_stations - elif type_announcement == "stops": - voice_stations = config.announcements.voice[0].stops - - if destination in voice_stations: - announcement_for = destination - else: - general_sound_enabled = voice_stations.get("general", "") - if not general_sound_enabled: - return None - 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) +def get_sound_path(station: str) -> str | None: + announcement_dir = Path("src/data/announcements") - sound_path = f"src/data/announcements/{sound_file}" - if Path(sound_path).is_file() is False: - logger(f"Couldn't find {sound_path}", "error") - return None - - return sound_path + for file in announcement_dir.iterdir(): + if file.is_file(): + if station.lower() in file.stem.lower(): + sound_file = file.resolve() + return sound_file def get_next_station(stops: dict, train_from: str) -> dict | None: now = datetime.now(LOCAL_TZ)