Restore configured volume after playback stops
This commit is contained in:
@@ -98,6 +98,7 @@ username = Bragi
|
||||
music_folder = music_folder/
|
||||
tmp_folder = /tmp/
|
||||
volume = 0.5
|
||||
restore_volume_on_stop = False
|
||||
```
|
||||
|
||||
**Generate Certificate (Recommended):**
|
||||
|
||||
@@ -716,6 +716,7 @@ class MumbleBot:
|
||||
var.cache.free_and_delete(current.id)
|
||||
else:
|
||||
self._loop_status = 'Empty queue'
|
||||
self.restore_default_volume()
|
||||
else:
|
||||
# if wait_for_ready flag is true, means the pointer is already
|
||||
# pointing to target song. start playing
|
||||
@@ -855,6 +856,7 @@ class MumbleBot:
|
||||
self._cleanup_ffmpeg_process() # Ensure proper cleanup
|
||||
var.playlist.clear()
|
||||
self.wait_for_ready = False
|
||||
self.restore_default_volume()
|
||||
self.log.info("bot: music stopped. playlist trashed.")
|
||||
|
||||
def stop(self):
|
||||
@@ -865,8 +867,21 @@ class MumbleBot:
|
||||
self.wait_for_ready = True
|
||||
else:
|
||||
self.wait_for_ready = False
|
||||
self.restore_default_volume()
|
||||
self.log.info("bot: music stopped.")
|
||||
|
||||
def restore_default_volume(self):
|
||||
if not var.config.getboolean("bot", "restore_volume_on_stop"):
|
||||
return
|
||||
|
||||
max_volume = var.config.getfloat("bot", "max_volume")
|
||||
if var.db.has_option("bot", "max_volume"):
|
||||
max_volume = var.db.getfloat("bot", "max_volume")
|
||||
|
||||
target_volume = min(var.config.getfloat("bot", "volume"), max_volume)
|
||||
self.volume_helper.set_volume(target_volume)
|
||||
var.db.set("bot", "volume", str(target_volume))
|
||||
|
||||
def _cleanup_ffmpeg_process(self):
|
||||
"""Properly cleanup FFmpeg process and associated resources"""
|
||||
if self.thread:
|
||||
|
||||
@@ -61,6 +61,7 @@ playback_mode = one-shot
|
||||
rebuild_workers = 0
|
||||
redirect_stderr = True
|
||||
refresh_cache_on_startup = True
|
||||
restore_volume_on_stop = False
|
||||
save_music_library = True
|
||||
save_playlist = True
|
||||
stereo = True
|
||||
@@ -155,4 +156,3 @@ yt_search = ysearch
|
||||
#
|
||||
# File paths use fuzzy matching - the first matching file in the music database will be used
|
||||
# URLs are downloaded and played like the !url command
|
||||
|
||||
|
||||
@@ -53,7 +53,10 @@ port = 64738
|
||||
|
||||
# 'volume': The default volume, a number from 0 to 1.
|
||||
# This option will be overridden by the value set in the database.
|
||||
# 'restore_volume_on_stop': When True, stopping playback restores the live and
|
||||
# persisted volume back to this config-file default volume.
|
||||
#volume = 0.1
|
||||
#restore_volume_on_stop = False
|
||||
|
||||
# 'bandwidth': The number of bits per second used by the bot when streaming audio.
|
||||
# Enabling this option will allow you to set it higher than the default value.
|
||||
|
||||
@@ -30,19 +30,6 @@ def tr_cli(option, *argv, **kwargs):
|
||||
except KeyError:
|
||||
raise KeyError("Missed strings in language file: '{string}'. ".format(string=option))
|
||||
return _tr(string, *argv, **kwargs)
|
||||
|
||||
|
||||
def tr_web(option, *argv, **kwargs):
|
||||
try:
|
||||
if option in lang_dict['web'] and lang_dict['web'][option]:
|
||||
string = lang_dict['web'][option]
|
||||
else:
|
||||
string = default_lang_dict['web'][option]
|
||||
except KeyError:
|
||||
raise KeyError("Missed strings in language file: '{string}'. ".format(string=option))
|
||||
return _tr(string, *argv, **kwargs)
|
||||
|
||||
|
||||
def _tr(string, *argv, **kwargs):
|
||||
if argv or kwargs:
|
||||
try:
|
||||
|
||||
+3
-83
@@ -2,7 +2,7 @@
|
||||
"cli": {
|
||||
"added_tags": "Added tags <i>{tags}</i> to <b>{song}</b>.",
|
||||
"added_tags_to_all": "Added tags <i>{tags}</i> to songs on the playlist.",
|
||||
"admin_help": "<h3>Admin command</h3>\n<b>Bot</b>\n<ul>\n<li><b>!<u>k</u>ill </b> - kill the bot</li>\n<li><b>!update </b> - update the bot</li>\n<li><b>!userban </b> {user} - ban a user</li>\n<li><b>!userunban </b> {user} - unban a user</li>\n<li><b>!urlbanlist </b> - list banned url</li>\n<li><b>!urlban </b> [{url}] - ban {url} (or current item's url by default) and remove this url from the library.</li>\n<li><b>!urlunban </b> {url} - unban {url}</li>\n<li><b>!rescan </b> {url} - rebuild local music file cache</li>\n<li><b>!dropdatabase</b> - clear the entire database, you will lose all settings and music library.</li>\n</ul>\n<b>Web Interface</b>\n<ul>\n<li><b>!<u>webuserlist</u></b> - list all users that have the permission of accessing the web interface, if auth mode is 'password'.</li>\n<li><b>!<u>webuseradd</u> {nick name}</b> - grant the user with {nick name} the access to the web interface, if auth mode is 'password'.</li>\n<li><b>!<u>webuserdel</u> {nick name}</b> - revoke the access to the web interface of {nick name}, if auth mode is 'password'.</li>\n</ul>",
|
||||
"admin_help": "<h3>Admin command</h3>\n<b>Bot</b>\n<ul>\n<li><b>!<u>k</u>ill </b> - kill the bot</li>\n<li><b>!update </b> - update the bot</li>\n<li><b>!userban </b> {user} - ban a user</li>\n<li><b>!userunban </b> {user} - unban a user</li>\n<li><b>!urlbanlist </b> - list banned url</li>\n<li><b>!urlban </b> [{url}] - ban {url} (or current item's url by default) and remove this url from the library.</li>\n<li><b>!urlunban </b> {url} - unban {url}</li>\n<li><b>!rescan </b> {url} - rebuild local music file cache</li>\n<li><b>!dropdatabase</b> - clear the entire database, you will lose all settings and music library.</li>\n<li><b>!maxvolume </b> {volume} - set the maximum allowed volume.</li>\n</ul>",
|
||||
"auto_paused": "Use <i>!play</i> to resume music!",
|
||||
"bad_command": "<i>{command}</i>: command not found.",
|
||||
"bad_parameter": "<i>{command}</i>: invalid parameter.",
|
||||
@@ -28,7 +28,7 @@
|
||||
"file_deleted": "Deleted {item} from the library.",
|
||||
"file_item": "<b>{artist} - {title}</b> <i>added by</i> {user}",
|
||||
"file_missed": "Music file '{file}' missed! This item has been removed from the playlist.",
|
||||
"help": "<h3>Commands</h3>\n<b>Control</b>\n<ul>\n<li> <b>!<u>w</u>eb</b> - get the URL of the web interface, if enabled. </li>\n<li> <b>!play </b> (or <b>!p</b>) [{num}] [{start_from}] - resume from pausing / start to play (the num-th song is num if given) </li>\n<li> <b>!<u>pa</u>use </b> - pause </li>\n<li> <b>!<u>st</u>op </b> - stop playing </li>\n<li> <b>!<u>sk</u>ip </b> - jump to the next song </li>\n<li> <b>!<u>la</u>st </b> - jump to the last song </li>\n<li> <b>!<u>v</u>olume </b> {volume} - get or change the volume (from 0 to 100) </li>\n<li> <b>!<u>m</u>ode </b> [{mode}] - get or set the playback mode, {mode} should be one of <i>one-shot</i> (remove\nitem once played), <i>repeat</i> (looping through the playlist), <i>random</i> (randomize the playlist),\n<i>autoplay</i> (randomly grab something from the music library).</li>\n<li> <b>!duck </b> on/off - enable or disable ducking function </li>\n<li> <b>!duckv </b> {volume} - set the volume of the bot when ducking is activated </li>\n<li> <b>!<u>duckt</u>hres </b> - set the threshold of volume to activate ducking (3000 by default) </li>\n<li> <b>!<u>o</u>ust </b> - stop playing and go to default channel </li>\n</ul>\n<b>Playlist</b>\n<ul>\n<li> <b>!<u>n</u>ow </b> (or <b>!np</b>) - display the current song </li>\n<li> <b>!<u>q</u>ueue </b> - display items in the playlist </li>\n<li> <b>!<u>t</u>ag </b> {tags} - add all items with tags {tags}, tags separated by \",\". </li>\n<li> <b>!file </b>(or <b>!f</b>) {path/folder/keyword} - add a single file to the playlist by its path or keyword in its path. </li>\n<li> <b>!<u>filem</u>atch </b>(or <b>!fm</b>) {pattern} - add all files that match regex {pattern} </li>\n<li> <b>!<u>ur</u>l </b> {url} - add Youtube or SoundCloud music </li>\n<li> <b>!<u>playl</u>ist </b> {url} [{offset}] - add all items in a Youtube or SoundCloud playlist, and start with the {offset}-th item </li>\n<li> <b>!<u>rad</u>io </b> {url} - append a radio {url} to the playlist </li>\n<li> <b>!<u>rbq</u>uery </b> {keyword} - query http://www.radio-browser.info for a radio station </li>\n<li> <b>!<u>rbp</u>lay </b> {id} - play a radio station with {id} (eg. !rbplay 96746) </li>\n<li> <b>!<u>ys</u>earch </b> {keywords} - query youtube. Use <i>!ysearch -n</i> to turn the page. </li>\n<li> <b>!<u>yp</u>lay </b> {keywords} - add the first search result of {keywords} into the playlist.</li>\n<li> <b>!<u>sh</u>ortlist </b> (or <b>!sl</b>) {indexes/*} - add {indexes}-th item (or all items if * is given) on the shortlist. </li>\n<li> <b>!rm </b> {num} - remove the num-th song on the playlist </li>\n<li> <b>!<u>rep</u>eat </b> [{num}] - repeat current song {num} (1 by default) times.</li>\n<li> <b>!<u>ran</u>dom </b> - randomize the playlist.</li>\n</ul>\n<b>Music Library</b>\n<ul>\n<li> <b>!<u>se</u>arch </b> {keywords} - find item with {keywords} in the music library, keywords separated by space.</li>\n<li> <b>!<u>li</u>stfile </b> [{pattern}] - display list of available files (whose paths match the regex pattern if {pattern} is given) </li>\n<li> <b>!<u>addt</u>ag </b> [{index}] {tags} - add {tags} to {index}-th(current song if {index} is omitted) item on the playlist, tags separated by \",\". </li>\n<li> <b>!<u>addt</u>ag </b> * {tags} - add {tags} to all items on the playlist. </li>\n<li> <b>!<u>un</u>tag </b> [{index/*}] {tags}/* - remove {tags}/all tags from {index}-th(current song if {index} is omitted) item on the playlist. </li>\n<li> <b>!<u>fin</u>dtagged </b> (or <b>!ft</b>) {tags} - find item with {tags} in the music library. </li>\n<li> <b>!<u>del</u>ete </b> {index} - delete {index}-th item on the shortlist from the music library. </li>\n</ul>\n<b>Other</b>\n<ul>\n<li> <b>!<u>j</u>oinme {token} </b> - join your own channel with {token}.</li>\n<li> <b>!<u>password</u> {password} </b> - change your password, used to access the web interface.</li>\n</ul>",
|
||||
"help": "<h3>Commands</h3>\n<b>Control</b>\n<ul>\n<li> <b>!play </b> (or <b>!p</b>) [{num}] [{start_from}] - resume from pausing / start to play (the num-th song is num if given) </li>\n<li> <b>!<u>pa</u>use </b> - pause </li>\n<li> <b>!<u>st</u>op </b> - stop playing </li>\n<li> <b>!<u>sk</u>ip </b> - jump to the next song </li>\n<li> <b>!<u>la</u>st </b> - jump to the last song </li>\n<li> <b>!<u>v</u>olume </b> {volume} - get or change the volume (from 0 to 100) </li>\n<li> <b>!<u>m</u>ode </b> [{mode}] - get or set the playback mode, {mode} should be one of <i>one-shot</i> (remove\nitem once played), <i>repeat</i> (looping through the playlist), <i>random</i> (randomize the playlist),\n<i>autoplay</i> (randomly grab something from the music library).</li>\n<li> <b>!duck </b> on/off - enable or disable ducking function </li>\n<li> <b>!duckv </b> {volume} - set the volume of the bot when ducking is activated </li>\n<li> <b>!<u>duckt</u>hres </b> - set the threshold of volume to activate ducking (3000 by default) </li>\n<li> <b>!<u>o</u>ust </b> - stop playing and go to default channel </li>\n</ul>\n<b>Playlist</b>\n<ul>\n<li> <b>!<u>n</u>ow </b> (or <b>!np</b>) - display the current song </li>\n<li> <b>!<u>q</u>ueue </b> - display items in the playlist </li>\n<li> <b>!<u>t</u>ag </b> {tags} - add all items with tags {tags}, tags separated by \",\". </li>\n<li> <b>!file </b>(or <b>!f</b>) {path/folder/keyword} - add a single file to the playlist by its path or keyword in its path. </li>\n<li> <b>!<u>filem</u>atch </b>(or <b>!fm</b>) {pattern} - add all files that match regex {pattern} </li>\n<li> <b>!<u>ur</u>l </b> {url} - add Youtube or SoundCloud music </li>\n<li> <b>!<u>playl</u>ist </b> {url} [{offset}] - add all items in a Youtube or SoundCloud playlist, and start with the {offset}-th item </li>\n<li> <b>!<u>rad</u>io </b> {url} - append a radio {url} to the playlist </li>\n<li> <b>!<u>rbq</u>uery </b> {keyword} - query http://www.radio-browser.info for a radio station </li>\n<li> <b>!<u>rbp</u>lay </b> {id} - play a radio station with {id} (eg. !rbplay 96746) </li>\n<li> <b>!<u>ys</u>earch </b> {keywords} - query youtube. Use <i>!ysearch -n</i> to turn the page. </li>\n<li> <b>!<u>yp</u>lay </b> {keywords} - add the first search result of {keywords} into the playlist.</li>\n<li> <b>!<u>sh</u>ortlist </b> (or <b>!sl</b>) {indexes/*} - add {indexes}-th item (or all items if * is given) on the shortlist. </li>\n<li> <b>!rm </b> {num} - remove the num-th song on the playlist </li>\n<li> <b>!<u>rep</u>eat </b> [{num}] - repeat current song {num} (1 by default) times.</li>\n<li> <b>!<u>ran</u>dom </b> - randomize the playlist.</li>\n</ul>\n<b>Music Library</b>\n<ul>\n<li> <b>!<u>se</u>arch </b> {keywords} - find item with {keywords} in the music library, keywords separated by space.</li>\n<li> <b>!<u>li</u>stfile </b> [{pattern}] - display list of available files (whose paths match the regex pattern if {pattern} is given) </li>\n<li> <b>!<u>addt</u>ag </b> [{index}] {tags} - add {tags} to {index}-th(current song if {index} is omitted) item on the playlist, tags separated by \",\". </li>\n<li> <b>!<u>addt</u>ag </b> * {tags} - add {tags} to all items on the playlist. </li>\n<li> <b>!<u>un</u>tag </b> [{index/*}] {tags}/* - remove {tags}/all tags from {index}-th(current song if {index} is omitted) item on the playlist. </li>\n<li> <b>!<u>fin</u>dtagged </b> (or <b>!ft</b>) {tags} - find item with {tags} in the music library. </li>\n<li> <b>!<u>del</u>ete </b> {index} - delete {index}-th item on the shortlist from the music library. </li>\n</ul>\n<b>Other</b>\n<ul>\n<li> <b>!<u>j</u>oinme {token} </b> - join your own channel with {token}.</li>\n</ul>",
|
||||
"invalid_index": "Invalid index <i>{index}</i>. Use <i>!queue</i> to see the playlist.",
|
||||
"last_song_on_the_queue": "Last one on the queue.",
|
||||
"max_volume": "Volume exceeds max volume of {max}. Setting volume to max.",
|
||||
@@ -83,91 +83,11 @@
|
||||
"user_ban": "You are banned, not allowed to do that!",
|
||||
"user_ban_list": "List of banned user: <br>{list}",
|
||||
"user_ban_success": "User {user} is banned.",
|
||||
"user_password_set": "Your password has been updated.",
|
||||
"user_unban_success": "User {user} is unbanned.",
|
||||
"web_user_list": "Following users have the privilege to access the web interface: <br /> {users}",
|
||||
"webpage_address": "Your own address to access the web interface is <a href=\"{address}\">{address}</a>",
|
||||
"which_command": "Do you mean <br /> {commands}",
|
||||
"wrong_pattern": "Invalid regex: {error}.",
|
||||
"yt_no_more": "No more results!",
|
||||
"yt_query_error": "Unable to query youtube!",
|
||||
"yt_result": "Youtube query result: {result_table} Use <i>!sl {{indexes}}</i> to play the item you want. <br />\n<i>!ytquery -n</i> for the next page."
|
||||
},
|
||||
"web": {
|
||||
"action": "Action",
|
||||
"add": "Add",
|
||||
"add_all": "Add All",
|
||||
"add_radio": "Add Radio",
|
||||
"add_radio_url": "Add Radio URL",
|
||||
"add_to_bottom": "Add to bottom",
|
||||
"add_to_bottom_of_current_playlist": "Add to bottom of current playlist",
|
||||
"add_to_playlist_next": "Add to playlist right after current song",
|
||||
"add_url": "Add URL",
|
||||
"add_youtube_or_soundcloud_url": "Add Youtube or Soundcloud URL",
|
||||
"are_you_really_sure": "Are you really sure?",
|
||||
"aria_bragi_logo": "Botamusique Logo: a fox with two headphones, enjoying the music",
|
||||
"aria_default_cover": "A black square with two eighth notes beamed together.",
|
||||
"aria_empty_box": "A drawing of an empty box.",
|
||||
"aria_remove_this_song": "Remove this song from the current playlist",
|
||||
"aria_skip_current_song": "Skip current song and play this song right now",
|
||||
"aria_skip_to_next_track": "Skip to next track",
|
||||
"aria_spinner": "A loading spinner",
|
||||
"aria_warning_of_deletion": "Warning about deletion of files.",
|
||||
"autoplay": "Autoplay",
|
||||
"browse_music_file": "Browse Music file",
|
||||
"cancel": "Cancel",
|
||||
"cancel_upload_warning": "<strong>Are you really sure?</strong> <br /> Click again to abort uploading.",
|
||||
"change_playback_mode": "Change Playback Mode",
|
||||
"choose_file": "Choose file",
|
||||
"clear_playlist": "Clear Playlist",
|
||||
"close": "Close",
|
||||
"delete_all": "Delete All",
|
||||
"delete_all_files": "Delete All Listed Files",
|
||||
"delete_file_warning": "All files listed here, include files on other pages, will be deleted from your hard-drive.\n Is that what you want?",
|
||||
"directory": "Directory",
|
||||
"download_all": "Download All",
|
||||
"download_song_from_library": "Download song from library",
|
||||
"edit_submit": "Edit!",
|
||||
"edit_tags_for": "Edit tags for",
|
||||
"expand_playlist": "See item <span\n class=\"playlist-expand-item-range\"></span> on the playlist.",
|
||||
"file": "File",
|
||||
"filters": "Filters",
|
||||
"index": "#",
|
||||
"keywords": "Keywords",
|
||||
"keywords_placeholder": "Keywords...",
|
||||
"mini_player_title": "Now Playing...",
|
||||
"music_library": "Music Library",
|
||||
"next_to_play": "Next to play",
|
||||
"no_tag": "No tag",
|
||||
"oneshot": "One-shot",
|
||||
"open_volume_controls": "Open Volume Controls",
|
||||
"page_title": "bragi Web Interface",
|
||||
"pause": "Pause",
|
||||
"play": "Play",
|
||||
"playlist_controls": "Playlist controls",
|
||||
"radio": "Radio",
|
||||
"radio_url_placeholder": "Radio URL...",
|
||||
"random": "Random",
|
||||
"remove_song_from_library": "Remove song from library",
|
||||
"repeat": "Repeat",
|
||||
"rescan_files": "Rescan Files",
|
||||
"skip_track": "Skip Track",
|
||||
"submit": "Submit",
|
||||
"tags": "Tags",
|
||||
"tags_to_add": "Tags to add",
|
||||
"title": "Title",
|
||||
"token": "Token",
|
||||
"token_required": "Token Required",
|
||||
"token_required_message": "You are accessing the web interface of {{ name }}.\nA token is needed to grant you access.<br />\nPlease send \"{{ command }}\" to the bot in mumble to acquire one.",
|
||||
"type": "Type",
|
||||
"upload_file": "Upload File",
|
||||
"upload_submit": "Upload!",
|
||||
"upload_to": "Upload To",
|
||||
"uploaded_finished": "Uploaded finished!",
|
||||
"uploading_files": "Uploading files...",
|
||||
"url": "URL",
|
||||
"url_path": "Url/Path",
|
||||
"url_placeholder": "URL...",
|
||||
"volume_slider": "Volume Slider"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
import configparser
|
||||
import logging
|
||||
import os
|
||||
import tempfile
|
||||
import types
|
||||
import unittest
|
||||
from unittest import mock
|
||||
|
||||
import bragi
|
||||
import constants
|
||||
from database import DatabaseMigration, MusicDatabase, SettingsDatabase
|
||||
import command
|
||||
import util
|
||||
import variables as var
|
||||
|
||||
|
||||
class FakeBot:
|
||||
def __init__(self):
|
||||
self.registered = []
|
||||
|
||||
def register_command(self, cmd, handle, no_partial_match=False, access_outside_channel=False, admin=False):
|
||||
self.registered.append(cmd)
|
||||
|
||||
|
||||
class FakePlaylist:
|
||||
def __init__(self, item=None):
|
||||
self.item = item
|
||||
|
||||
def __len__(self):
|
||||
return 1 if self.item is not None else 0
|
||||
|
||||
def current_item(self):
|
||||
return self.item
|
||||
|
||||
|
||||
class ExhaustedPlaylist:
|
||||
current_index = -1
|
||||
|
||||
def next(self):
|
||||
return False
|
||||
|
||||
|
||||
class FakeSoundOutput:
|
||||
def get_buffer_size(self):
|
||||
return 0
|
||||
|
||||
|
||||
class FakeMumble:
|
||||
def __init__(self):
|
||||
self.sound_output = FakeSoundOutput()
|
||||
self.alive_checks = 0
|
||||
|
||||
def is_alive(self):
|
||||
self.alive_checks += 1
|
||||
return self.alive_checks < 2
|
||||
|
||||
|
||||
class VolumeRestoreTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
settings_file = tempfile.NamedTemporaryFile(delete=False)
|
||||
settings_file.close()
|
||||
music_file = tempfile.NamedTemporaryFile(delete=False)
|
||||
music_file.close()
|
||||
self.settings_path = settings_file.name
|
||||
self.music_path = music_file.name
|
||||
|
||||
self.settings_db = SettingsDatabase(self.settings_path)
|
||||
self.music_db = MusicDatabase(self.music_path)
|
||||
DatabaseMigration(self.settings_db, self.music_db).migrate()
|
||||
|
||||
self.config = configparser.ConfigParser(interpolation=None, allow_no_value=True)
|
||||
self.config.read("configuration.default.ini", encoding="utf-8")
|
||||
var.config = self.config
|
||||
var.db = self.settings_db
|
||||
var.music_db = self.music_db
|
||||
var.cache = None
|
||||
var.playlist = []
|
||||
|
||||
def tearDown(self):
|
||||
os.unlink(self.settings_path)
|
||||
os.unlink(self.music_path)
|
||||
|
||||
def make_bot(self):
|
||||
bot = bragi.MumbleBot.__new__(bragi.MumbleBot)
|
||||
bot.volume_helper = util.VolumeHelper()
|
||||
bot.volume_helper.set_volume(1.0)
|
||||
bot.thread = None
|
||||
bot.on_interrupting = False
|
||||
bot.song_start_at = -1
|
||||
bot.read_pcm_size = 0
|
||||
bot.is_pause = False
|
||||
bot.wait_for_ready = False
|
||||
bot.log = logging.getLogger("test")
|
||||
return bot
|
||||
|
||||
def test_restore_volume_on_stop_updates_runtime_and_db_from_config(self):
|
||||
self.config.set("bot", "restore_volume_on_stop", "True")
|
||||
self.config.set("bot", "volume", "0.7")
|
||||
self.settings_db.set("bot", "volume", "1.0")
|
||||
|
||||
bot = self.make_bot()
|
||||
|
||||
bot.restore_default_volume()
|
||||
|
||||
self.assertAlmostEqual(bot.volume_helper.plain_volume_set, 0.7)
|
||||
self.assertAlmostEqual(self.settings_db.getfloat("bot", "volume"), 0.7)
|
||||
|
||||
def test_restore_volume_on_stop_respects_max_volume_limit(self):
|
||||
self.config.set("bot", "restore_volume_on_stop", "True")
|
||||
self.config.set("bot", "volume", "0.9")
|
||||
self.settings_db.set("bot", "max_volume", "0.5")
|
||||
|
||||
bot = self.make_bot()
|
||||
|
||||
bot.restore_default_volume()
|
||||
|
||||
self.assertAlmostEqual(bot.volume_helper.plain_volume_set, 0.5)
|
||||
self.assertAlmostEqual(self.settings_db.getfloat("bot", "volume"), 0.5)
|
||||
|
||||
def test_restore_volume_on_stop_is_disabled_by_default(self):
|
||||
self.config.set("bot", "restore_volume_on_stop", "False")
|
||||
self.config.set("bot", "volume", "0.7")
|
||||
self.settings_db.set("bot", "volume", "1.0")
|
||||
|
||||
bot = self.make_bot()
|
||||
|
||||
bot.restore_default_volume()
|
||||
|
||||
self.assertAlmostEqual(bot.volume_helper.plain_volume_set, 1.0)
|
||||
self.assertAlmostEqual(self.settings_db.getfloat("bot", "volume"), 1.0)
|
||||
|
||||
def test_stop_restores_default_volume(self):
|
||||
self.config.set("bot", "restore_volume_on_stop", "True")
|
||||
var.playlist = [object()]
|
||||
|
||||
bot = self.make_bot()
|
||||
bot.restore_default_volume = mock.Mock()
|
||||
bot._cleanup_ffmpeg_process = mock.Mock()
|
||||
|
||||
bot.stop()
|
||||
|
||||
bot.restore_default_volume.assert_called_once_with()
|
||||
|
||||
def test_pause_does_not_restore_default_volume(self):
|
||||
var.playlist = FakePlaylist(types.SimpleNamespace(id="track-id"))
|
||||
|
||||
bot = self.make_bot()
|
||||
bot.playhead = 12.5
|
||||
bot.restore_default_volume = mock.Mock()
|
||||
|
||||
bot.pause()
|
||||
|
||||
bot.restore_default_volume.assert_not_called()
|
||||
|
||||
def test_loop_restores_volume_without_entering_pause_when_queue_runs_empty(self):
|
||||
var.playlist = ExhaustedPlaylist()
|
||||
|
||||
bot = self.make_bot()
|
||||
bot.mumble = FakeMumble()
|
||||
bot.restore_default_volume = mock.Mock()
|
||||
bot._cleanup_ffmpeg_process = mock.Mock()
|
||||
bot.exit = False
|
||||
bot.last_ffmpeg_err = ""
|
||||
bot.pcm_buffer_size = 1
|
||||
bot.read_pcm_size = 1
|
||||
bot._loop_status = ""
|
||||
|
||||
bragi.MumbleBot.loop(bot)
|
||||
|
||||
bot.restore_default_volume.assert_called_once_with()
|
||||
self.assertFalse(bot.is_pause)
|
||||
|
||||
|
||||
class HelpTextTests(unittest.TestCase):
|
||||
def test_help_text_does_not_reference_web_interface(self):
|
||||
constants.load_lang("en_US")
|
||||
|
||||
help_text = constants.tr_cli("help")
|
||||
admin_help = constants.tr_cli("admin_help")
|
||||
|
||||
self.assertNotIn("!<u>w</u>eb", help_text)
|
||||
self.assertNotIn("web interface", help_text.lower())
|
||||
self.assertNotIn("web interface", admin_help.lower())
|
||||
|
||||
|
||||
class CommandRegistrationTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.config = configparser.ConfigParser(interpolation=None, allow_no_value=True)
|
||||
self.config.read("configuration.default.ini", encoding="utf-8")
|
||||
var.config = self.config
|
||||
|
||||
def test_register_all_commands_excludes_web_commands(self):
|
||||
bot = FakeBot()
|
||||
|
||||
command.register_all_commands(bot)
|
||||
|
||||
registered = ",".join(bot.registered)
|
||||
self.assertIn(self.config.get("commands", "volume"), registered)
|
||||
self.assertNotIn("web", registered)
|
||||
self.assertNotIn("webuseradd", registered)
|
||||
self.assertNotIn("webuserlist", registered)
|
||||
self.assertNotIn("webuserdel", registered)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user