Second wave of initial code changes.
This commit is contained in:
parent
b1e21af243
commit
de270bc842
10
Dockerfile
10
Dockerfile
@ -1,12 +1,12 @@
|
|||||||
ARG ARCH=
|
ARG ARCH=
|
||||||
FROM python:3.11-slim-bullseye AS python-builder
|
FROM python:3.11-slim-bullseye AS python-builder
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
WORKDIR /botamusique
|
WORKDIR /bragi
|
||||||
|
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get install --no-install-recommends -y gcc g++ ffmpeg libjpeg-dev libmagic-dev opus-tools zlib1g-dev \
|
&& apt-get install --no-install-recommends -y gcc g++ ffmpeg libjpeg-dev libmagic-dev opus-tools zlib1g-dev \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
COPY . /botamusique
|
COPY . /bragi
|
||||||
RUN python3 -m venv venv \
|
RUN python3 -m venv venv \
|
||||||
&& venv/bin/pip install wheel \
|
&& venv/bin/pip install wheel \
|
||||||
&& venv/bin/pip install -r requirements.txt
|
&& venv/bin/pip install -r requirements.txt
|
||||||
@ -17,9 +17,9 @@ EXPOSE 8181
|
|||||||
RUN apt update && \
|
RUN apt update && \
|
||||||
apt install --no-install-recommends -y opus-tools ffmpeg libmagic-dev curl tar && \
|
apt install --no-install-recommends -y opus-tools ffmpeg libmagic-dev curl tar && \
|
||||||
rm -rf /var/lib/apt/lists/*
|
rm -rf /var/lib/apt/lists/*
|
||||||
COPY --from=python-builder /botamusique /botamusique
|
COPY --from=python-builder /bragi /bragi
|
||||||
WORKDIR /botamusique
|
WORKDIR /bragi
|
||||||
RUN chmod +x entrypoint.sh
|
RUN chmod +x entrypoint.sh
|
||||||
|
|
||||||
ENTRYPOINT [ "/botamusique/entrypoint.sh" ]
|
ENTRYPOINT [ "/bragi/entrypoint.sh" ]
|
||||||
CMD ["venv/bin/python", "mumbleBot.py"]
|
CMD ["venv/bin/python", "mumbleBot.py"]
|
||||||
|
@ -3,18 +3,18 @@ ARG ARCH=
|
|||||||
FROM ${ARCH}python:3-slim-bullseye AS source
|
FROM ${ARCH}python:3-slim-bullseye AS source
|
||||||
ARG VERSION=master
|
ARG VERSION=master
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
WORKDIR /botamusique
|
WORKDIR /bragi
|
||||||
RUN apt-get update && apt-get install -y git
|
RUN apt-get update && apt-get install -y git
|
||||||
RUN git clone --recurse-submodules https://github.com/azlux/botamusique.git . && git checkout $VERSION
|
RUN git clone --recurse-submodules https://github.com/azlux/bragi.git . && git checkout $VERSION
|
||||||
|
|
||||||
|
|
||||||
FROM ${ARCH}python:3-slim-bullseye AS python-builder
|
FROM ${ARCH}python:3-slim-bullseye AS python-builder
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
WORKDIR /botamusique
|
WORKDIR /bragi
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get install -y gcc ffmpeg libjpeg-dev libmagic-dev opus-tools zlib1g-dev \
|
&& apt-get install -y gcc ffmpeg libjpeg-dev libmagic-dev opus-tools zlib1g-dev \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
COPY --from=source /botamusique .
|
COPY --from=source /bragi .
|
||||||
RUN python3 -m venv venv \
|
RUN python3 -m venv venv \
|
||||||
&& venv/bin/pip install wheel \
|
&& venv/bin/pip install wheel \
|
||||||
&& venv/bin/pip install -r requirements.txt
|
&& venv/bin/pip install -r requirements.txt
|
||||||
@ -22,30 +22,30 @@ RUN python3 -m venv venv \
|
|||||||
|
|
||||||
FROM ${ARCH}node:14-bullseye-slim AS node-builder
|
FROM ${ARCH}node:14-bullseye-slim AS node-builder
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
WORKDIR /botamusique/web
|
WORKDIR /bragi/web
|
||||||
COPY --from=source /botamusique/web .
|
COPY --from=source /bragi/web .
|
||||||
RUN npm install
|
RUN npm install
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
|
|
||||||
FROM ${ARCH}python:3-slim-bullseye AS template-builder
|
FROM ${ARCH}python:3-slim-bullseye AS template-builder
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
WORKDIR /botamusique
|
WORKDIR /bragi
|
||||||
COPY --from=python-builder /botamusique .
|
COPY --from=python-builder /bragi .
|
||||||
COPY --from=node-builder /botamusique/templates templates
|
COPY --from=node-builder /bragi/templates templates
|
||||||
RUN venv/bin/python scripts/translate_templates.py --lang-dir /botamusique/lang --template-dir /botamusique/web/templates
|
RUN venv/bin/python scripts/translate_templates.py --lang-dir /bragi/lang --template-dir /bragi/web/templates
|
||||||
|
|
||||||
|
|
||||||
FROM ${ARCH}python:3-slim-bullseye
|
FROM ${ARCH}python:3-slim-bullseye
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
EXPOSE 8181
|
EXPOSE 8181
|
||||||
WORKDIR /botamusique
|
WORKDIR /bragi
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get install -y ffmpeg libmagic-dev opus-tools zlib1g \
|
&& apt-get install -y ffmpeg libmagic-dev opus-tools zlib1g \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
COPY --from=python-builder /botamusique .
|
COPY --from=python-builder /bragi .
|
||||||
COPY --from=node-builder /botamusique/static static
|
COPY --from=node-builder /bragi/static static
|
||||||
COPY --from=template-builder /botamusique/templates templates
|
COPY --from=template-builder /bragi/templates templates
|
||||||
RUN chmod +x entrypoint.sh
|
RUN chmod +x entrypoint.sh
|
||||||
ENTRYPOINT [ "/botamusique/entrypoint.sh" ]
|
ENTRYPOINT [ "/bragi/entrypoint.sh" ]
|
||||||
CMD ["/botamusique/venv/bin/python", "/botamusique/mumbleBot.py"]
|
CMD ["/bragi/venv/bin/python", "/bragi/mumbleBot.py"]
|
||||||
|
103
command.py
103
command.py
@ -1,4 +1,8 @@
|
|||||||
# coding=utf-8
|
# coding=utf-8
|
||||||
|
#
|
||||||
|
# Bragi - A Mumble music bot
|
||||||
|
# Forked from botamusique by azlux (https://github.com/azlux/botamusque)
|
||||||
|
#
|
||||||
import logging
|
import logging
|
||||||
import secrets
|
import secrets
|
||||||
import datetime
|
import datetime
|
||||||
@ -8,7 +12,6 @@ import pymumble_py3 as pymumble
|
|||||||
|
|
||||||
from constants import tr_cli as tr
|
from constants import tr_cli as tr
|
||||||
from constants import commands
|
from constants import commands
|
||||||
import interface
|
|
||||||
import util
|
import util
|
||||||
import variables as var
|
import variables as var
|
||||||
from pyradios import RadioBrowser
|
from pyradios import RadioBrowser
|
||||||
@ -53,7 +56,6 @@ def register_all_commands(bot):
|
|||||||
bot.register_command(commands('remove'), cmd_remove)
|
bot.register_command(commands('remove'), cmd_remove)
|
||||||
bot.register_command(commands('remove_tag'), cmd_remove_tag)
|
bot.register_command(commands('remove_tag'), cmd_remove_tag)
|
||||||
bot.register_command(commands('repeat'), cmd_repeat)
|
bot.register_command(commands('repeat'), cmd_repeat)
|
||||||
bot.register_command(commands('requests_webinterface_access'), cmd_web_access)
|
|
||||||
bot.register_command(commands('rescan'), cmd_refresh_cache, no_partial_match=True)
|
bot.register_command(commands('rescan'), cmd_refresh_cache, no_partial_match=True)
|
||||||
bot.register_command(commands('search'), cmd_search_library)
|
bot.register_command(commands('search'), cmd_search_library)
|
||||||
bot.register_command(commands('skip'), cmd_skip)
|
bot.register_command(commands('skip'), cmd_skip)
|
||||||
@ -65,13 +67,9 @@ def register_all_commands(bot):
|
|||||||
bot.register_command(commands('yt_search'), cmd_yt_search)
|
bot.register_command(commands('yt_search'), cmd_yt_search)
|
||||||
|
|
||||||
# admin command
|
# admin command
|
||||||
bot.register_command(commands('add_webinterface_user'), cmd_web_user_add, admin=True)
|
|
||||||
bot.register_command(commands('drop_database'), cmd_drop_database, no_partial_match=True, admin=True)
|
bot.register_command(commands('drop_database'), cmd_drop_database, no_partial_match=True, admin=True)
|
||||||
bot.register_command(commands('kill'), cmd_kill, admin=True)
|
bot.register_command(commands('kill'), cmd_kill, admin=True)
|
||||||
bot.register_command(commands('list_webinterface_user'), cmd_web_user_list, admin=True)
|
|
||||||
bot.register_command(commands('remove_webinterface_user'), cmd_web_user_remove, admin=True)
|
|
||||||
bot.register_command(commands('max_volume'), cmd_max_volume, admin=True)
|
bot.register_command(commands('max_volume'), cmd_max_volume, admin=True)
|
||||||
bot.register_command(commands('update'), cmd_update, no_partial_match=True, admin=True)
|
|
||||||
bot.register_command(commands('url_ban'), cmd_url_ban, no_partial_match=True, admin=True)
|
bot.register_command(commands('url_ban'), cmd_url_ban, no_partial_match=True, admin=True)
|
||||||
bot.register_command(commands('url_ban_list'), cmd_url_ban_list, no_partial_match=True, admin=True)
|
bot.register_command(commands('url_ban_list'), cmd_url_ban_list, no_partial_match=True, admin=True)
|
||||||
bot.register_command(commands('url_unban'), cmd_url_unban, no_partial_match=True, admin=True)
|
bot.register_command(commands('url_unban'), cmd_url_unban, no_partial_match=True, admin=True)
|
||||||
@ -647,17 +645,6 @@ def cmd_kill(bot, user, text, command, parameter):
|
|||||||
bot.exit = True
|
bot.exit = True
|
||||||
|
|
||||||
|
|
||||||
def cmd_update(bot, user, text, command, parameter):
|
|
||||||
global log
|
|
||||||
|
|
||||||
if bot.is_admin(user):
|
|
||||||
bot.mumble.users[text.actor].send_text_message(
|
|
||||||
tr('start_updating'))
|
|
||||||
msg = util.update(bot.version)
|
|
||||||
bot.mumble.users[text.actor].send_text_message(msg)
|
|
||||||
else:
|
|
||||||
bot.mumble.users[text.actor].send_text_message(
|
|
||||||
tr('not_admin'))
|
|
||||||
|
|
||||||
|
|
||||||
def cmd_stop_and_getout(bot, user, text, command, parameter):
|
def cmd_stop_and_getout(bot, user, text, command, parameter):
|
||||||
@ -1249,88 +1236,6 @@ def cmd_refresh_cache(bot, user, text, command, parameter):
|
|||||||
bot.mumble.users[text.actor].send_text_message(tr('not_admin'))
|
bot.mumble.users[text.actor].send_text_message(tr('not_admin'))
|
||||||
|
|
||||||
|
|
||||||
def cmd_web_access(bot, user, text, command, parameter):
|
|
||||||
auth_method = var.config.get("webinterface", "auth_method")
|
|
||||||
|
|
||||||
if auth_method == 'token':
|
|
||||||
interface.banned_ip = []
|
|
||||||
interface.bad_access_count = {}
|
|
||||||
|
|
||||||
user_info = var.db.get("user", user, fallback='{}')
|
|
||||||
user_dict = json.loads(user_info)
|
|
||||||
if 'token' in user_dict:
|
|
||||||
var.db.remove_option("web_token", user_dict['token'])
|
|
||||||
|
|
||||||
token = secrets.token_urlsafe(5)
|
|
||||||
user_dict['token'] = token
|
|
||||||
user_dict['token_created'] = str(datetime.datetime.now())
|
|
||||||
user_dict['last_ip'] = ''
|
|
||||||
var.db.set("web_token", token, user)
|
|
||||||
var.db.set("user", user, json.dumps(user_dict))
|
|
||||||
|
|
||||||
access_address = var.config.get("webinterface", "access_address") + "/?token=" + token
|
|
||||||
else:
|
|
||||||
access_address = var.config.get("webinterface", "access_address")
|
|
||||||
|
|
||||||
bot.send_msg(tr('webpage_address', address=access_address), text)
|
|
||||||
|
|
||||||
|
|
||||||
def cmd_user_password(bot, user, text, command, parameter):
|
|
||||||
if not parameter:
|
|
||||||
bot.send_msg(tr('bad_parameter', command=command), text)
|
|
||||||
return
|
|
||||||
|
|
||||||
user_info = var.db.get("user", user, fallback='{}')
|
|
||||||
user_dict = json.loads(user_info)
|
|
||||||
user_dict['password'], user_dict['salt'] = util.get_salted_password_hash(parameter)
|
|
||||||
|
|
||||||
var.db.set("user", user, json.dumps(user_dict))
|
|
||||||
|
|
||||||
bot.send_msg(tr('user_password_set'), text)
|
|
||||||
|
|
||||||
|
|
||||||
def cmd_web_user_add(bot, user, text, command, parameter):
|
|
||||||
if not parameter:
|
|
||||||
bot.send_msg(tr('bad_parameter', command=command), text)
|
|
||||||
return
|
|
||||||
|
|
||||||
auth_method = var.config.get("webinterface", "auth_method")
|
|
||||||
|
|
||||||
if auth_method == 'password':
|
|
||||||
web_users = json.loads(var.db.get("privilege", "web_access", fallback='[]'))
|
|
||||||
if parameter not in web_users:
|
|
||||||
web_users.append(parameter)
|
|
||||||
var.db.set("privilege", "web_access", json.dumps(web_users))
|
|
||||||
bot.send_msg(tr('web_user_list', users=", ".join(web_users)), text)
|
|
||||||
else:
|
|
||||||
bot.send_msg(tr('command_disabled', command=command), text)
|
|
||||||
|
|
||||||
|
|
||||||
def cmd_web_user_remove(bot, user, text, command, parameter):
|
|
||||||
if not parameter:
|
|
||||||
bot.send_msg(tr('bad_parameter', command=command), text)
|
|
||||||
return
|
|
||||||
|
|
||||||
auth_method = var.config.get("webinterface", "auth_method")
|
|
||||||
|
|
||||||
if auth_method == 'password':
|
|
||||||
web_users = json.loads(var.db.get("privilege", "web_access", fallback='[]'))
|
|
||||||
if parameter in web_users:
|
|
||||||
web_users.remove(parameter)
|
|
||||||
var.db.set("privilege", "web_access", json.dumps(web_users))
|
|
||||||
bot.send_msg(tr('web_user_list', users=", ".join(web_users)), text)
|
|
||||||
else:
|
|
||||||
bot.send_msg(tr('command_disabled', command=command), text)
|
|
||||||
|
|
||||||
|
|
||||||
def cmd_web_user_list(bot, user, text, command, parameter):
|
|
||||||
auth_method = var.config.get("webinterface", "auth_method")
|
|
||||||
|
|
||||||
if auth_method == 'password':
|
|
||||||
web_users = json.loads(var.db.get("privilege", "web_access", fallback='[]'))
|
|
||||||
bot.send_msg(tr('web_user_list', users=", ".join(web_users)), text)
|
|
||||||
else:
|
|
||||||
bot.send_msg(tr('command_disabled', command=command), text)
|
|
||||||
|
|
||||||
|
|
||||||
def cmd_version(bot, user, text, command, parameter):
|
def cmd_version(bot, user, text, command, parameter):
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
# ========================================================
|
# ========================================================
|
||||||
# botamusique Default Configuration File
|
# Bragi Default Configuration File
|
||||||
|
# Forked from botamusique by azlux
|
||||||
# Version 6
|
# Version 6
|
||||||
# ========================================================
|
# ========================================================
|
||||||
# WARNING:
|
# WARNING:
|
||||||
@ -31,7 +32,6 @@ admin =
|
|||||||
allow_other_channel_message = False
|
allow_other_channel_message = False
|
||||||
allow_private_message = True
|
allow_private_message = True
|
||||||
announce_current_music = True
|
announce_current_music = True
|
||||||
auto_check_update = True
|
|
||||||
autoplay_length = 5
|
autoplay_length = 5
|
||||||
avatar =
|
avatar =
|
||||||
bandwidth = 96000
|
bandwidth = 96000
|
||||||
@ -59,28 +59,13 @@ refresh_cache_on_startup = True
|
|||||||
save_music_library = True
|
save_music_library = True
|
||||||
save_playlist = True
|
save_playlist = True
|
||||||
stereo = True
|
stereo = True
|
||||||
target_version = git
|
|
||||||
tmp_folder = /tmp/
|
tmp_folder = /tmp/
|
||||||
tmp_folder_max_size = 10
|
tmp_folder_max_size = 10
|
||||||
username = botamusique
|
username = bragi
|
||||||
volume = 0.8
|
volume = 0.8
|
||||||
when_nobody_in_channel = nothing
|
when_nobody_in_channel = nothing
|
||||||
when_nobody_in_channel_ignore =
|
when_nobody_in_channel_ignore =
|
||||||
|
|
||||||
[webinterface]
|
|
||||||
access_address = http://127.0.0.1:8181
|
|
||||||
auth_method = none
|
|
||||||
enabled = False
|
|
||||||
flask_secret = ChangeThisPassword
|
|
||||||
is_web_proxified = True
|
|
||||||
listening_addr = 127.0.0.1
|
|
||||||
listening_port = 8181
|
|
||||||
max_attempts = 10
|
|
||||||
max_upload_file_size = 30M
|
|
||||||
password =
|
|
||||||
upload_enabled = True
|
|
||||||
user =
|
|
||||||
web_logfile =
|
|
||||||
|
|
||||||
[debug]
|
[debug]
|
||||||
ffmpeg = False
|
ffmpeg = False
|
||||||
@ -102,7 +87,6 @@ user_agent =
|
|||||||
[commands]
|
[commands]
|
||||||
add_from_shortlist = shortlist, sl
|
add_from_shortlist = shortlist, sl
|
||||||
add_tag = addtag
|
add_tag = addtag
|
||||||
add_webinterface_user = webuseradd
|
|
||||||
change_user_password = password
|
change_user_password = password
|
||||||
clear = clear
|
clear = clear
|
||||||
command_symbol = !:!
|
command_symbol = !:!
|
||||||
@ -118,7 +102,6 @@ joinme = joinme
|
|||||||
kill = kill
|
kill = kill
|
||||||
last = last
|
last = last
|
||||||
list_file = listfile
|
list_file = listfile
|
||||||
list_webinterface_user = webuserlist
|
|
||||||
max_volume = maxvolume
|
max_volume = maxvolume
|
||||||
mode = mode
|
mode = mode
|
||||||
pause = pause
|
pause = pause
|
||||||
@ -135,16 +118,13 @@ rb_play = rbplay
|
|||||||
rb_query = rbquery
|
rb_query = rbquery
|
||||||
remove = rm
|
remove = rm
|
||||||
remove_tag = untag
|
remove_tag = untag
|
||||||
remove_webinterface_user = webuserdel
|
|
||||||
repeat = repeat
|
repeat = repeat
|
||||||
requests_webinterface_access = web
|
|
||||||
rescan = rescan
|
rescan = rescan
|
||||||
search = search
|
search = search
|
||||||
skip = skip
|
skip = skip
|
||||||
split_username_at_space = False
|
split_username_at_space = False
|
||||||
stop = stop
|
stop = stop
|
||||||
stop_and_getout = oust
|
stop_and_getout = oust
|
||||||
update = update
|
|
||||||
url_ban = urlban
|
url_ban = urlban
|
||||||
url_ban_list = urlbanlist
|
url_ban_list = urlbanlist
|
||||||
url_unban = urlunban
|
url_unban = urlunban
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
# ========================================================
|
# ========================================================
|
||||||
# botamusique example configuration file
|
# Bragi example configuration file
|
||||||
|
# Forked from botamusique by azlux
|
||||||
# Version 6
|
# Version 6
|
||||||
# ========================================================
|
# ========================================================
|
||||||
# Rename this file to configuration.ini after editing.
|
# Rename this file to configuration.ini after editing.
|
||||||
@ -22,7 +23,7 @@ port = 64738
|
|||||||
# 'username': The bot's username.
|
# 'username': The bot's username.
|
||||||
# 'comment': Comment displayed on the bot's profile.
|
# 'comment': Comment displayed on the bot's profile.
|
||||||
# 'avatar': Path to an image used for the bot's avatar (PNG recommended, 128 KB max).
|
# 'avatar': Path to an image used for the bot's avatar (PNG recommended, 128 KB max).
|
||||||
#username = botamusique
|
#username = bragi
|
||||||
#comment = "Hi, I'm here to play radio, local music or youtube/soundcloud music. Have fun!"
|
#comment = "Hi, I'm here to play radio, local music or youtube/soundcloud music. Have fun!"
|
||||||
#avatar =
|
#avatar =
|
||||||
|
|
||||||
@ -155,46 +156,7 @@ port = 64738
|
|||||||
# query youtube", you should provide a value here.
|
# query youtube", you should provide a value here.
|
||||||
#youtube_query_cookie = {"CONSENT": "paste your CONSENT cookie value here"}
|
#youtube_query_cookie = {"CONSENT": "paste your CONSENT cookie value here"}
|
||||||
|
|
||||||
# The [webinterface] section stores settings related to the web interface.
|
# Web interface has been removed from Bragi
|
||||||
[webinterface]
|
|
||||||
# 'enabled': Whether to enable the web interface to allow managing your playlist,
|
|
||||||
# uploading tracks, etc.
|
|
||||||
# The web interface is disabled by default for security and performance reasons.
|
|
||||||
# 'access_address': URL provided to users when the public URL for the
|
|
||||||
# web interface is requested.
|
|
||||||
#enabled = False
|
|
||||||
#listening_addr = 127.0.0.1
|
|
||||||
#listening_port = 8181
|
|
||||||
#is_web_proxified = True
|
|
||||||
#access_address = http://127.0.0.1:8181
|
|
||||||
|
|
||||||
# 'web_logfile': If this is provided, web server access logs are written to this file.
|
|
||||||
#web_logfile =
|
|
||||||
|
|
||||||
# 'auth_method': Method used to authenticate users accessing the web interface.
|
|
||||||
# One of 'none', 'password' or 'token'. If this is set to 'token', a unique token
|
|
||||||
# is used for authentication.
|
|
||||||
# 'max_attempts': Amount of incorrect login attempts needed before being banned.
|
|
||||||
# Regenerating a token or rebooting the bot will reset this number.
|
|
||||||
#auth_method = token
|
|
||||||
#max_attempts = 10
|
|
||||||
|
|
||||||
# 'user', 'password': If auth_method is set to 'password', you'll need to set
|
|
||||||
# the default username and password, which is set by these two options.
|
|
||||||
# You can add more users using the '!webadduser' command.
|
|
||||||
#user = botamusique
|
|
||||||
#password = mumble
|
|
||||||
|
|
||||||
# 'flask_secret': To use a token, Flask needs a password to encrypt/sign cookies.
|
|
||||||
# This is absolutely necessary if auth_method is 'token'!
|
|
||||||
#flask_secret = ChangeThisPassword
|
|
||||||
|
|
||||||
# 'upload_enabled': Whether to enable the upload function of the web interface.
|
|
||||||
# If this is False, only admins can upload files.
|
|
||||||
# 'maximum_upload_file_size': Maximum file size allowed for uploads.
|
|
||||||
# Can be specified in B, KB, MB, GB, or TB.
|
|
||||||
#upload_enabled = True
|
|
||||||
#max_upload_file_size = 30MB
|
|
||||||
|
|
||||||
# The [debug] section contains settings to enable debugging messaages.
|
# The [debug] section contains settings to enable debugging messaages.
|
||||||
[debug]
|
[debug]
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
#
|
||||||
|
# Bragi - A Mumble music bot
|
||||||
|
# Forked from botamusique by azlux (https://github.com/azlux/botamusque)
|
||||||
|
#
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
#
|
||||||
|
# Bragi - A Mumble music bot
|
||||||
|
# Forked from botamusique by azlux (https://github.com/azlux/botamusque)
|
||||||
|
#
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
@ -51,14 +51,14 @@ fi
|
|||||||
|
|
||||||
if [ -n "$BAM_CONFIG_file" ]; then
|
if [ -n "$BAM_CONFIG_file" ]; then
|
||||||
if [ ! -f "$BAM_CONFIG_file" ]; then
|
if [ ! -f "$BAM_CONFIG_file" ]; then
|
||||||
cp "/botamusique/configuration.example.ini" "$BAM_CONFIG_file"
|
cp "/bragi/configuration.example.ini" "$BAM_CONFIG_file"
|
||||||
fi
|
fi
|
||||||
command+=( "--config" "$BAM_CONFIG_file" )
|
command+=( "--config" "$BAM_CONFIG_file" )
|
||||||
else
|
else
|
||||||
if [ ! -f "/botamusique/configuration.ini" ]; then
|
if [ ! -f "/bragi/configuration.ini" ]; then
|
||||||
cp "/botamusique/configuration.example.ini" "/botamusique/configuration.ini"
|
cp "/bragi/configuration.example.ini" "/bragi/configuration.ini"
|
||||||
fi
|
fi
|
||||||
command+=( "--config" "/botamusique/configuration.ini" )
|
command+=( "--config" "/bragi/configuration.ini" )
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exec "${command[@]}"
|
exec "${command[@]}"
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
"multiple_file_deleted": "Multiple items deleted from the library:",
|
"multiple_file_deleted": "Multiple items deleted from the library:",
|
||||||
"multiple_file_found": "Found:",
|
"multiple_file_found": "Found:",
|
||||||
"multiple_matches": "File not found! Possible candidates:",
|
"multiple_matches": "File not found! Possible candidates:",
|
||||||
"new_version_found": "<h2>Update Available!</h2> Version {new_version} of botamusique is available! <hr />\n<h3>Changelog</h3> {changelog} <hr /> Send <i>!update</i> to update!",
|
"new_version_found": "<h2>Update Available!</h2> Version {new_version} of bragi is available! <hr />\n<h3>Changelog</h3> {changelog} <hr /> Send <i>!update</i> to update!",
|
||||||
"next_to_play": "Next song.",
|
"next_to_play": "Next song.",
|
||||||
"no_file": "File not found.",
|
"no_file": "File not found.",
|
||||||
"not_admin": "You are not an admin!",
|
"not_admin": "You are not an admin!",
|
||||||
@ -60,7 +60,7 @@
|
|||||||
"removed_tags_from_all": "Removed tags <i>{tags}</i> from songs on the playlist.",
|
"removed_tags_from_all": "Removed tags <i>{tags}</i> from songs on the playlist.",
|
||||||
"removing_item": "Removed entry {item} from playlist.",
|
"removing_item": "Removed entry {item} from playlist.",
|
||||||
"repeat": "Repeat {song} for {n} times.",
|
"repeat": "Repeat {song} for {n} times.",
|
||||||
"report_version": "The current version of botamusique is <b>{version}</b>.",
|
"report_version": "The current version of bragi is <b>{version}</b>.",
|
||||||
"shortlist_instruction": "Use <i>!sl {indexes}</i> to play the item you want.",
|
"shortlist_instruction": "Use <i>!sl {indexes}</i> to play the item you want.",
|
||||||
"start_updating": "Start updating...",
|
"start_updating": "Start updating...",
|
||||||
"stopped": "Music stopped.",
|
"stopped": "Music stopped.",
|
||||||
@ -68,7 +68,7 @@
|
|||||||
"unable_download": "Unable to download <b>{item}</b>. Removed from the library.",
|
"unable_download": "Unable to download <b>{item}</b>. Removed from the library.",
|
||||||
"unable_play": "Unable to play <b>{item}</b>. Removed from the library.",
|
"unable_play": "Unable to play <b>{item}</b>. Removed from the library.",
|
||||||
"unknown_mode": "Unknown playback mode '{mode}'. It should be one of <i>one-shot</i>, <i>repeat</i>, <i>random</i>.",
|
"unknown_mode": "Unknown playback mode '{mode}'. It should be one of <i>one-shot</i>, <i>repeat</i>, <i>random</i>.",
|
||||||
"update_successful": "<h2>botamusique v{version} Installed!</h2><hr />\n<h3>Changelog</h3> {changelog} <hr /> Visit <a href=\"https://github.com/azlux/botamusique\">our github repo</a> for more details!",
|
"update_successful": "<h2>bragi v{version} Installed!</h2><hr />\n<h3>Changelog</h3> {changelog} <hr /> Visit <a href=\"https://github.com/azlux/bragi\">our github repo</a> for more details!",
|
||||||
"url": "URL",
|
"url": "URL",
|
||||||
"url_ban": "The URL {url} is banned! Removed from playlist!",
|
"url_ban": "The URL {url} is banned! Removed from playlist!",
|
||||||
"url_ban_list": "List of banned URL: <br>{list}",
|
"url_ban_list": "List of banned URL: <br>{list}",
|
||||||
@ -105,7 +105,7 @@
|
|||||||
"add_url": "Add URL",
|
"add_url": "Add URL",
|
||||||
"add_youtube_or_soundcloud_url": "Add Youtube or Soundcloud URL",
|
"add_youtube_or_soundcloud_url": "Add Youtube or Soundcloud URL",
|
||||||
"are_you_really_sure": "Are you really sure?",
|
"are_you_really_sure": "Are you really sure?",
|
||||||
"aria_botamusique_logo": "Botamusique Logo: a fox with two headphones, enjoying the music",
|
"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_default_cover": "A black square with two eighth notes beamed together.",
|
||||||
"aria_empty_box": "A drawing of an empty box.",
|
"aria_empty_box": "A drawing of an empty box.",
|
||||||
"aria_remove_this_song": "Remove this song from the current playlist",
|
"aria_remove_this_song": "Remove this song from the current playlist",
|
||||||
@ -141,7 +141,7 @@
|
|||||||
"no_tag": "No tag",
|
"no_tag": "No tag",
|
||||||
"oneshot": "One-shot",
|
"oneshot": "One-shot",
|
||||||
"open_volume_controls": "Open Volume Controls",
|
"open_volume_controls": "Open Volume Controls",
|
||||||
"page_title": "botamusique Web Interface",
|
"page_title": "bragi Web Interface",
|
||||||
"pause": "Pause",
|
"pause": "Pause",
|
||||||
"play": "Play",
|
"play": "Play",
|
||||||
"playlist_controls": "Playlist controls",
|
"playlist_controls": "Playlist controls",
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
#
|
||||||
|
# Bragi - A Mumble music bot
|
||||||
|
# Forked from botamusique by azlux (https://github.com/azlux/botamusque)
|
||||||
|
#
|
@ -1,3 +1,8 @@
|
|||||||
|
#
|
||||||
|
# Bragi - A Mumble music bot
|
||||||
|
# Forked from botamusique by azlux (https://github.com/azlux/botamusque)
|
||||||
|
#
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
#
|
||||||
|
# Bragi - A Mumble music bot
|
||||||
|
# Forked from botamusique by azlux (https://github.com/azlux/botamusque)
|
||||||
|
#
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
#
|
||||||
|
# Bragi - A Mumble music bot
|
||||||
|
# Forked from botamusique by azlux (https://github.com/azlux/botamusque)
|
||||||
|
#
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
item_builders = {}
|
item_builders = {}
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
#
|
||||||
|
# Bragi - A Mumble music bot
|
||||||
|
# Forked from botamusique by azlux (https://github.com/azlux/botamusque)
|
||||||
|
#
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import threading
|
import threading
|
||||||
import logging
|
import logging
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
#
|
||||||
|
# Bragi - A Mumble music bot
|
||||||
|
# Forked from botamusique by azlux (https://github.com/azlux/botamusque)
|
||||||
|
#
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import logging
|
import logging
|
||||||
import struct
|
import struct
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
#
|
||||||
|
# Bragi - A Mumble music bot
|
||||||
|
# Forked from botamusique by azlux (https://github.com/azlux/botamusque)
|
||||||
|
#
|
||||||
|
|
||||||
import threading
|
import threading
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
#
|
||||||
|
# Bragi - A Mumble music bot
|
||||||
|
# Forked from botamusique by azlux (https://github.com/azlux/botamusque)
|
||||||
|
#
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import yt_dlp as youtube_dl
|
import yt_dlp as youtube_dl
|
||||||
from constants import tr_cli as tr
|
from constants import tr_cli as tr
|
||||||
|
60
mumbleBot.py
60
mumbleBot.py
@ -1,5 +1,9 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Bragi - A Mumble music bot
|
||||||
|
# Forked from botamusique by azlux (https://github.com/azlux/botamusque)
|
||||||
|
#
|
||||||
import re
|
import re
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
@ -36,7 +40,7 @@ class MumbleBot:
|
|||||||
|
|
||||||
def __init__(self, args):
|
def __init__(self, args):
|
||||||
self.log = logging.getLogger("bot")
|
self.log = logging.getLogger("bot")
|
||||||
self.log.info(f"bot: botamusique version {self.get_version()}, starting...")
|
self.log.info(f"bot: bragi version {self.get_version()}, starting...")
|
||||||
signal.signal(signal.SIGINT, self.ctrl_caught)
|
signal.signal(signal.SIGINT, self.ctrl_caught)
|
||||||
self.cmd_handle = {}
|
self.cmd_handle = {}
|
||||||
|
|
||||||
@ -48,8 +52,6 @@ class MumbleBot:
|
|||||||
self.channel = var.config.get("server", "channel")
|
self.channel = var.config.get("server", "channel")
|
||||||
|
|
||||||
var.user = args.user
|
var.user = args.user
|
||||||
var.is_proxified = var.config.getboolean(
|
|
||||||
"webinterface", "is_web_proxified")
|
|
||||||
|
|
||||||
# Flags to indicate the bot is exiting (Ctrl-C, or !kill)
|
# Flags to indicate the bot is exiting (Ctrl-C, or !kill)
|
||||||
self.exit = False
|
self.exit = False
|
||||||
@ -187,26 +189,7 @@ class MumbleBot:
|
|||||||
|
|
||||||
self.redirect_ffmpeg_log = var.config.getboolean('debug', 'redirect_ffmpeg_log')
|
self.redirect_ffmpeg_log = var.config.getboolean('debug', 'redirect_ffmpeg_log')
|
||||||
|
|
||||||
if var.config.getboolean("bot", "auto_check_update"):
|
var.db.set("bot", "version", self.version)
|
||||||
def check_update():
|
|
||||||
nonlocal self
|
|
||||||
new_version, changelog = util.check_update(self.get_version())
|
|
||||||
if new_version:
|
|
||||||
self.send_channel_msg(tr('new_version_found', new_version=new_version, changelog=changelog))
|
|
||||||
|
|
||||||
th = threading.Thread(target=check_update, name="UpdateThread")
|
|
||||||
th.daemon = True
|
|
||||||
th.start()
|
|
||||||
|
|
||||||
last_startup_version = var.db.get("bot", "version", fallback=None)
|
|
||||||
try:
|
|
||||||
if not last_startup_version or version.parse(last_startup_version) < version.parse(self.version):
|
|
||||||
var.db.set("bot", "version", self.version)
|
|
||||||
if var.config.getboolean("bot", "auto_check_update"):
|
|
||||||
changelog = util.fetch_changelog()
|
|
||||||
self.send_channel_msg(tr("update_successful", version=self.version, changelog=changelog))
|
|
||||||
except version.InvalidVersion:
|
|
||||||
var.db.set("bot", "version", self.version)
|
|
||||||
|
|
||||||
# Set the CTRL+C shortcut
|
# Set the CTRL+C shortcut
|
||||||
def ctrl_caught(self, signal, frame):
|
def ctrl_caught(self, signal, frame):
|
||||||
@ -753,31 +736,13 @@ class MumbleBot:
|
|||||||
self.pause_at_id = ""
|
self.pause_at_id = ""
|
||||||
|
|
||||||
|
|
||||||
def start_web_interface(addr, port):
|
|
||||||
global formatter
|
|
||||||
import interface
|
|
||||||
|
|
||||||
# setup logger
|
|
||||||
werkzeug_logger = logging.getLogger('werkzeug')
|
|
||||||
logfile = util.solve_filepath(var.config.get('webinterface', 'web_logfile'))
|
|
||||||
if logfile:
|
|
||||||
handler = logging.handlers.RotatingFileHandler(logfile, mode='a', maxBytes=10240, backupCount=3) # Rotate after 10KB, leave 3 old logs
|
|
||||||
else:
|
|
||||||
handler = logging.StreamHandler()
|
|
||||||
|
|
||||||
werkzeug_logger.addHandler(handler)
|
|
||||||
|
|
||||||
interface.init_proxy()
|
|
||||||
interface.web.env = 'development'
|
|
||||||
interface.web.secret_key = var.config.get('webinterface', 'flask_secret')
|
|
||||||
interface.web.run(port=port, host=addr)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
supported_languages = util.get_supported_language()
|
supported_languages = util.get_supported_language()
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description='Bot for playing music on Mumble')
|
description='Bragi - Bot for playing music on Mumble')
|
||||||
|
|
||||||
# General arguments
|
# General arguments
|
||||||
parser.add_argument("--config", dest='config', type=str, default='configuration.ini',
|
parser.add_argument("--config", dest='config', type=str, default='configuration.ini',
|
||||||
@ -950,17 +915,6 @@ if __name__ == '__main__':
|
|||||||
var.bot_logger.info("bot: load playlist from previous session")
|
var.bot_logger.info("bot: load playlist from previous session")
|
||||||
var.playlist.load()
|
var.playlist.load()
|
||||||
|
|
||||||
# ============================
|
|
||||||
# Start the web interface
|
|
||||||
# ============================
|
|
||||||
if var.config.getboolean("webinterface", "enabled"):
|
|
||||||
wi_addr = var.config.get("webinterface", "listening_addr")
|
|
||||||
wi_port = var.config.getint("webinterface", "listening_port")
|
|
||||||
tt = threading.Thread(
|
|
||||||
target=start_web_interface, name="WebThread", args=(wi_addr, wi_port))
|
|
||||||
tt.daemon = True
|
|
||||||
bot_logger.info('Starting web interface on {}:{}'.format(wi_addr, wi_port))
|
|
||||||
tt.start()
|
|
||||||
|
|
||||||
# Start the main loop.
|
# Start the main loop.
|
||||||
var.bot.loop()
|
var.bot.loop()
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
flask
|
|
||||||
yt-dlp
|
yt-dlp
|
||||||
python-magic
|
python-magic
|
||||||
Pillow
|
Pillow
|
||||||
|
20
update.sh
20
update.sh
@ -2,18 +2,18 @@
|
|||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
stable)
|
stable)
|
||||||
curl -Lo /tmp/botamusique.tar.gz https://packages.azlux.fr/botamusique/sources-stable.tar.gz
|
curl -Lo /tmp/bragi.tar.gz https://packages.azlux.fr/bragi/sources-stable.tar.gz
|
||||||
tar -xzf /tmp/botamusique.tar.gz -C /tmp/
|
tar -xzf /tmp/bragi.tar.gz -C /tmp/
|
||||||
cp -r /tmp/botamusique/* .
|
cp -r /tmp/bragi/* .
|
||||||
rm -r /tmp/botamusique
|
rm -r /tmp/bragi
|
||||||
rm -r /tmp/botamusique.tar.gz
|
rm -r /tmp/bragi.tar.gz
|
||||||
;;
|
;;
|
||||||
testing)
|
testing)
|
||||||
curl -Lo /tmp/botamusique.tar.gz https://packages.azlux.fr/botamusique/sources-testing.tar.gz
|
curl -Lo /tmp/bragi.tar.gz https://packages.azlux.fr/bragi/sources-testing.tar.gz
|
||||||
tar -xzf /tmp/botamusique.tar.gz -C /tmp/
|
tar -xzf /tmp/bragi.tar.gz -C /tmp/
|
||||||
cp -r /tmp/botamusique/* .
|
cp -r /tmp/bragi/* .
|
||||||
rm -r /tmp/botamusique
|
rm -r /tmp/bragi
|
||||||
rm -r /tmp/botamusique.tar.gz
|
rm -r /tmp/bragi.tar.gz
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
;;
|
;;
|
||||||
|
68
util.py
68
util.py
@ -1,5 +1,9 @@
|
|||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
# coding=utf-8
|
# coding=utf-8
|
||||||
|
#
|
||||||
|
# Bragi - A Mumble music bot
|
||||||
|
# Forked from botamusique by azlux (https://github.com/azlux/botamusque)
|
||||||
|
#
|
||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import html
|
import html
|
||||||
@ -102,64 +106,8 @@ def get_user_ban():
|
|||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
def new_release_version(target):
|
|
||||||
if target == "testing":
|
|
||||||
r = requests.get("https://packages.azlux.fr/botamusique/testing-version")
|
|
||||||
else:
|
|
||||||
r = requests.get("https://packages.azlux.fr/botamusique/version")
|
|
||||||
v = r.text
|
|
||||||
return v.rstrip()
|
|
||||||
|
|
||||||
|
|
||||||
def fetch_changelog():
|
|
||||||
r = requests.get("https://packages.azlux.fr/botamusique/changelog")
|
|
||||||
c = r.text
|
|
||||||
return c
|
|
||||||
|
|
||||||
|
|
||||||
def check_update(current_version):
|
|
||||||
global log
|
|
||||||
log.debug("update: checking for updates...")
|
|
||||||
new_version = new_release_version(var.config.get('bot', 'target_version'))
|
|
||||||
if version.parse(new_version) > version.parse(current_version):
|
|
||||||
changelog = fetch_changelog()
|
|
||||||
log.info(f"update: new version {new_version} found, current installed version {current_version}.")
|
|
||||||
log.info(f"update: changelog: {changelog}")
|
|
||||||
changelog = changelog.replace("\n", "<br>")
|
|
||||||
return new_version, changelog
|
|
||||||
else:
|
|
||||||
log.debug("update: no new version found.")
|
|
||||||
return None, None
|
|
||||||
|
|
||||||
|
|
||||||
def update(current_version):
|
|
||||||
global log
|
|
||||||
|
|
||||||
target = var.config.get('bot', 'target_version')
|
|
||||||
new_version = new_release_version(target)
|
|
||||||
msg = ""
|
|
||||||
if target == "git":
|
|
||||||
msg = "git install, I do nothing<br/>"
|
|
||||||
|
|
||||||
elif (target == "stable" and version.parse(new_version) > version.parse(current_version)) or \
|
|
||||||
(target == "testing" and version.parse(new_version) != version.parse(current_version)):
|
|
||||||
log.info('update: new version, start updating...')
|
|
||||||
tp = sp.check_output(['/usr/bin/env', 'bash', 'update.sh', target]).decode()
|
|
||||||
log.debug(tp)
|
|
||||||
log.info('update: update pip libraries dependencies')
|
|
||||||
sp.check_output([var.config.get('bot', 'pip3_path'), 'install', '--upgrade', '-r', 'requirements.txt']).decode()
|
|
||||||
msg = "New version installed, please restart the bot.<br/>"
|
|
||||||
|
|
||||||
log.info(f'update: starting update {YT_PKG_NAME} via pip3')
|
|
||||||
tp = sp.check_output([var.config.get('bot', 'pip3_path'), 'install', '--upgrade', YT_PKG_NAME]).decode()
|
|
||||||
if f"Collecting {YT_PKG_NAME}" in tp.splitlines():
|
|
||||||
msg += "Update done: " + tp.split('Successfully installed')[1]
|
|
||||||
else:
|
|
||||||
msg += YT_PKG_NAME.capitalize() + " is up-to-date"
|
|
||||||
|
|
||||||
reload(youtube_dl)
|
|
||||||
msg += "<br/>" + YT_PKG_NAME.capitalize() + " reloaded"
|
|
||||||
return msg
|
|
||||||
|
|
||||||
|
|
||||||
def pipe_no_wait():
|
def pipe_no_wait():
|
||||||
@ -311,7 +259,7 @@ def get_url_from_input(string):
|
|||||||
else:
|
else:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
match = re.search("(http|https)://(\S*)?/(\S*)", string, flags=re.IGNORECASE)
|
match = re.search(r"(http|https)://(\S*)?/(\S*)", string, flags=re.IGNORECASE)
|
||||||
if match:
|
if match:
|
||||||
url = match[1].lower() + "://" + match[2].lower() + "/" + match[3]
|
url = match[1].lower() + "://" + match[2].lower() + "/" + match[3]
|
||||||
# https://github.com/mumble-voip/mumble/issues/4999
|
# https://github.com/mumble-voip/mumble/issues/4999
|
||||||
@ -376,7 +324,7 @@ def get_media_duration(path):
|
|||||||
|
|
||||||
|
|
||||||
def parse_time(human):
|
def parse_time(human):
|
||||||
match = re.search("(?:(\d\d):)?(?:(\d\d):)?(\d+(?:\.\d*)?)", human, flags=re.IGNORECASE)
|
match = re.search(r"(?:(\d\d):)?(?:(\d\d):)?(\d+(?:\.\d*)?)", human, flags=re.IGNORECASE)
|
||||||
if match:
|
if match:
|
||||||
if match[1] is None and match[2] is None:
|
if match[1] is None and match[2] is None:
|
||||||
return float(match[3])
|
return float(match[3])
|
||||||
@ -399,7 +347,7 @@ def format_time(seconds):
|
|||||||
def parse_file_size(human):
|
def parse_file_size(human):
|
||||||
units = {"B": 1, "KB": 1024, "MB": 1024 * 1024, "GB": 1024 * 1024 * 1024, "TB": 1024 * 1024 * 1024 * 1024,
|
units = {"B": 1, "KB": 1024, "MB": 1024 * 1024, "GB": 1024 * 1024 * 1024, "TB": 1024 * 1024 * 1024 * 1024,
|
||||||
"K": 1024, "M": 1024 * 1024, "G": 1024 * 1024 * 1024, "T": 1024 * 1024 * 1024 * 1024}
|
"K": 1024, "M": 1024 * 1024, "G": 1024 * 1024 * 1024, "T": 1024 * 1024 * 1024 * 1024}
|
||||||
match = re.search("(\d+(?:\.\d*)?)\s*([A-Za-z]+)", human, flags=re.IGNORECASE)
|
match = re.search(r"(\d+(?:\.\d*)?)\s*([A-Za-z]+)", human, flags=re.IGNORECASE)
|
||||||
if match:
|
if match:
|
||||||
num = float(match[1])
|
num = float(match[1])
|
||||||
unit = match[2].upper()
|
unit = match[2].upper()
|
||||||
@ -428,7 +376,7 @@ def get_supported_language():
|
|||||||
lang_files = os.listdir(os.path.join(root_dir, 'lang'))
|
lang_files = os.listdir(os.path.join(root_dir, 'lang'))
|
||||||
lang_list = []
|
lang_list = []
|
||||||
for lang_file in lang_files:
|
for lang_file in lang_files:
|
||||||
match = re.search("([a-z]{2}_[A-Z]{2})\.json", lang_file)
|
match = re.search(r"([a-z]{2}_[A-Z]{2})\.json", lang_file)
|
||||||
if match:
|
if match:
|
||||||
lang_list.append(match[1])
|
lang_list.append(match[1])
|
||||||
|
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
#
|
||||||
|
# Bragi - A Mumble music bot
|
||||||
|
# Forked from botamusique by azlux (https://github.com/azlux/botamusque)
|
||||||
|
#
|
||||||
|
|
||||||
from typing import Type, TYPE_CHECKING
|
from typing import Type, TYPE_CHECKING
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user