Second wave of initial code changes.

This commit is contained in:
Storm Dragon 2025-06-13 18:53:38 -04:00
parent b1e21af243
commit de270bc842
22 changed files with 120 additions and 318 deletions

View File

@ -1,12 +1,12 @@
ARG ARCH=
FROM python:3.11-slim-bullseye AS python-builder
ENV DEBIAN_FRONTEND=noninteractive
WORKDIR /botamusique
WORKDIR /bragi
RUN apt-get update \
&& apt-get install --no-install-recommends -y gcc g++ ffmpeg libjpeg-dev libmagic-dev opus-tools zlib1g-dev \
&& rm -rf /var/lib/apt/lists/*
COPY . /botamusique
COPY . /bragi
RUN python3 -m venv venv \
&& venv/bin/pip install wheel \
&& venv/bin/pip install -r requirements.txt
@ -17,9 +17,9 @@ EXPOSE 8181
RUN apt update && \
apt install --no-install-recommends -y opus-tools ffmpeg libmagic-dev curl tar && \
rm -rf /var/lib/apt/lists/*
COPY --from=python-builder /botamusique /botamusique
WORKDIR /botamusique
COPY --from=python-builder /bragi /bragi
WORKDIR /bragi
RUN chmod +x entrypoint.sh
ENTRYPOINT [ "/botamusique/entrypoint.sh" ]
ENTRYPOINT [ "/bragi/entrypoint.sh" ]
CMD ["venv/bin/python", "mumbleBot.py"]

View File

@ -3,18 +3,18 @@ ARG ARCH=
FROM ${ARCH}python:3-slim-bullseye AS source
ARG VERSION=master
ENV DEBIAN_FRONTEND=noninteractive
WORKDIR /botamusique
WORKDIR /bragi
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
ENV DEBIAN_FRONTEND=noninteractive
WORKDIR /botamusique
WORKDIR /bragi
RUN apt-get update \
&& apt-get install -y gcc ffmpeg libjpeg-dev libmagic-dev opus-tools zlib1g-dev \
&& rm -rf /var/lib/apt/lists/*
COPY --from=source /botamusique .
COPY --from=source /bragi .
RUN python3 -m venv venv \
&& venv/bin/pip install wheel \
&& 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
ENV DEBIAN_FRONTEND=noninteractive
WORKDIR /botamusique/web
COPY --from=source /botamusique/web .
WORKDIR /bragi/web
COPY --from=source /bragi/web .
RUN npm install
RUN npm run build
FROM ${ARCH}python:3-slim-bullseye AS template-builder
ENV DEBIAN_FRONTEND=noninteractive
WORKDIR /botamusique
COPY --from=python-builder /botamusique .
COPY --from=node-builder /botamusique/templates templates
RUN venv/bin/python scripts/translate_templates.py --lang-dir /botamusique/lang --template-dir /botamusique/web/templates
WORKDIR /bragi
COPY --from=python-builder /bragi .
COPY --from=node-builder /bragi/templates templates
RUN venv/bin/python scripts/translate_templates.py --lang-dir /bragi/lang --template-dir /bragi/web/templates
FROM ${ARCH}python:3-slim-bullseye
ENV DEBIAN_FRONTEND=noninteractive
EXPOSE 8181
WORKDIR /botamusique
WORKDIR /bragi
RUN apt-get update \
&& apt-get install -y ffmpeg libmagic-dev opus-tools zlib1g \
&& rm -rf /var/lib/apt/lists/*
COPY --from=python-builder /botamusique .
COPY --from=node-builder /botamusique/static static
COPY --from=template-builder /botamusique/templates templates
COPY --from=python-builder /bragi .
COPY --from=node-builder /bragi/static static
COPY --from=template-builder /bragi/templates templates
RUN chmod +x entrypoint.sh
ENTRYPOINT [ "/botamusique/entrypoint.sh" ]
CMD ["/botamusique/venv/bin/python", "/botamusique/mumbleBot.py"]
ENTRYPOINT [ "/bragi/entrypoint.sh" ]
CMD ["/bragi/venv/bin/python", "/bragi/mumbleBot.py"]

View File

@ -1,4 +1,8 @@
# coding=utf-8
#
# Bragi - A Mumble music bot
# Forked from botamusique by azlux (https://github.com/azlux/botamusque)
#
import logging
import secrets
import datetime
@ -8,7 +12,6 @@ import pymumble_py3 as pymumble
from constants import tr_cli as tr
from constants import commands
import interface
import util
import variables as var
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_tag'), cmd_remove_tag)
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('search'), cmd_search_library)
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)
# 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('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('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_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)
@ -647,17 +645,6 @@ def cmd_kill(bot, user, text, command, parameter):
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):
@ -1249,88 +1236,6 @@ def cmd_refresh_cache(bot, user, text, command, parameter):
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):

View File

@ -1,5 +1,6 @@
# ========================================================
# botamusique Default Configuration File
# Bragi Default Configuration File
# Forked from botamusique by azlux
# Version 6
# ========================================================
# WARNING:
@ -31,7 +32,6 @@ admin =
allow_other_channel_message = False
allow_private_message = True
announce_current_music = True
auto_check_update = True
autoplay_length = 5
avatar =
bandwidth = 96000
@ -59,28 +59,13 @@ refresh_cache_on_startup = True
save_music_library = True
save_playlist = True
stereo = True
target_version = git
tmp_folder = /tmp/
tmp_folder_max_size = 10
username = botamusique
username = bragi
volume = 0.8
when_nobody_in_channel = nothing
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]
ffmpeg = False
@ -102,7 +87,6 @@ user_agent =
[commands]
add_from_shortlist = shortlist, sl
add_tag = addtag
add_webinterface_user = webuseradd
change_user_password = password
clear = clear
command_symbol = !:
@ -118,7 +102,6 @@ joinme = joinme
kill = kill
last = last
list_file = listfile
list_webinterface_user = webuserlist
max_volume = maxvolume
mode = mode
pause = pause
@ -135,16 +118,13 @@ rb_play = rbplay
rb_query = rbquery
remove = rm
remove_tag = untag
remove_webinterface_user = webuserdel
repeat = repeat
requests_webinterface_access = web
rescan = rescan
search = search
skip = skip
split_username_at_space = False
stop = stop
stop_and_getout = oust
update = update
url_ban = urlban
url_ban_list = urlbanlist
url_unban = urlunban

View File

@ -1,5 +1,6 @@
# ========================================================
# botamusique example configuration file
# Bragi example configuration file
# Forked from botamusique by azlux
# Version 6
# ========================================================
# Rename this file to configuration.ini after editing.
@ -22,7 +23,7 @@ port = 64738
# 'username': The bot's username.
# 'comment': Comment displayed on the bot's profile.
# '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!"
#avatar =
@ -155,46 +156,7 @@ port = 64738
# query youtube", you should provide a value here.
#youtube_query_cookie = {"CONSENT": "paste your CONSENT cookie value here"}
# The [webinterface] section stores settings related to the web interface.
[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
# Web interface has been removed from Bragi
# The [debug] section contains settings to enable debugging messaages.
[debug]

View File

@ -1,3 +1,8 @@
#
# Bragi - A Mumble music bot
# Forked from botamusique by azlux (https://github.com/azlux/botamusque)
#
import os
import json

View File

@ -1,3 +1,8 @@
#
# Bragi - A Mumble music bot
# Forked from botamusique by azlux (https://github.com/azlux/botamusque)
#
import os
import re
import sqlite3

View File

@ -51,14 +51,14 @@ fi
if [ -n "$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
command+=( "--config" "$BAM_CONFIG_file" )
else
if [ ! -f "/botamusique/configuration.ini" ]; then
cp "/botamusique/configuration.example.ini" "/botamusique/configuration.ini"
if [ ! -f "/bragi/configuration.ini" ]; then
cp "/bragi/configuration.example.ini" "/bragi/configuration.ini"
fi
command+=( "--config" "/botamusique/configuration.ini" )
command+=( "--config" "/bragi/configuration.ini" )
fi
exec "${command[@]}"

View File

@ -36,7 +36,7 @@
"multiple_file_deleted": "Multiple items deleted from the library:",
"multiple_file_found": "Found:",
"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.",
"no_file": "File not found.",
"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.",
"removing_item": "Removed entry {item} from playlist.",
"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.",
"start_updating": "Start updating...",
"stopped": "Music stopped.",
@ -68,7 +68,7 @@
"unable_download": "Unable to download <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>.",
"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_ban": "The URL {url} is banned! Removed from playlist!",
"url_ban_list": "List of banned URL: <br>{list}",
@ -105,7 +105,7 @@
"add_url": "Add URL",
"add_youtube_or_soundcloud_url": "Add Youtube or Soundcloud URL",
"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_empty_box": "A drawing of an empty box.",
"aria_remove_this_song": "Remove this song from the current playlist",
@ -141,7 +141,7 @@
"no_tag": "No tag",
"oneshot": "One-shot",
"open_volume_controls": "Open Volume Controls",
"page_title": "botamusique Web Interface",
"page_title": "bragi Web Interface",
"pause": "Pause",
"play": "Play",
"playlist_controls": "Playlist controls",

View File

@ -0,0 +1,4 @@
#
# Bragi - A Mumble music bot
# Forked from botamusique by azlux (https://github.com/azlux/botamusque)
#

View File

@ -1,3 +1,8 @@
#
# Bragi - A Mumble music bot
# Forked from botamusique by azlux (https://github.com/azlux/botamusque)
#
import logging
import os

View File

@ -1,3 +1,8 @@
#
# Bragi - A Mumble music bot
# Forked from botamusique by azlux (https://github.com/azlux/botamusque)
#
import os
import re
from io import BytesIO

View File

@ -1,3 +1,8 @@
#
# Bragi - A Mumble music bot
# Forked from botamusique by azlux (https://github.com/azlux/botamusque)
#
import logging
item_builders = {}

View File

@ -1,3 +1,8 @@
#
# Bragi - A Mumble music bot
# Forked from botamusique by azlux (https://github.com/azlux/botamusque)
#
import json
import threading
import logging

View File

@ -1,3 +1,8 @@
#
# Bragi - A Mumble music bot
# Forked from botamusique by azlux (https://github.com/azlux/botamusque)
#
import re
import logging
import struct

View File

@ -1,3 +1,8 @@
#
# Bragi - A Mumble music bot
# Forked from botamusique by azlux (https://github.com/azlux/botamusque)
#
import threading
import logging
import os

View File

@ -1,3 +1,8 @@
#
# Bragi - A Mumble music bot
# Forked from botamusique by azlux (https://github.com/azlux/botamusque)
#
import logging
import yt_dlp as youtube_dl
from constants import tr_cli as tr

View File

@ -1,5 +1,9 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Bragi - A Mumble music bot
# Forked from botamusique by azlux (https://github.com/azlux/botamusque)
#
import re
import threading
import time
@ -36,7 +40,7 @@ class MumbleBot:
def __init__(self, args):
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)
self.cmd_handle = {}
@ -48,8 +52,6 @@ class MumbleBot:
self.channel = var.config.get("server", "channel")
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)
self.exit = False
@ -187,26 +189,7 @@ class MumbleBot:
self.redirect_ffmpeg_log = var.config.getboolean('debug', 'redirect_ffmpeg_log')
if var.config.getboolean("bot", "auto_check_update"):
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)
var.db.set("bot", "version", self.version)
# Set the CTRL+C shortcut
def ctrl_caught(self, signal, frame):
@ -753,31 +736,13 @@ class MumbleBot:
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__':
supported_languages = util.get_supported_language()
parser = argparse.ArgumentParser(
description='Bot for playing music on Mumble')
description='Bragi - Bot for playing music on Mumble')
# General arguments
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.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.
var.bot.loop()

View File

@ -1,4 +1,3 @@
flask
yt-dlp
python-magic
Pillow

View File

@ -2,18 +2,18 @@
case "$1" in
stable)
curl -Lo /tmp/botamusique.tar.gz https://packages.azlux.fr/botamusique/sources-stable.tar.gz
tar -xzf /tmp/botamusique.tar.gz -C /tmp/
cp -r /tmp/botamusique/* .
rm -r /tmp/botamusique
rm -r /tmp/botamusique.tar.gz
curl -Lo /tmp/bragi.tar.gz https://packages.azlux.fr/bragi/sources-stable.tar.gz
tar -xzf /tmp/bragi.tar.gz -C /tmp/
cp -r /tmp/bragi/* .
rm -r /tmp/bragi
rm -r /tmp/bragi.tar.gz
;;
testing)
curl -Lo /tmp/botamusique.tar.gz https://packages.azlux.fr/botamusique/sources-testing.tar.gz
tar -xzf /tmp/botamusique.tar.gz -C /tmp/
cp -r /tmp/botamusique/* .
rm -r /tmp/botamusique
rm -r /tmp/botamusique.tar.gz
curl -Lo /tmp/bragi.tar.gz https://packages.azlux.fr/bragi/sources-testing.tar.gz
tar -xzf /tmp/bragi.tar.gz -C /tmp/
cp -r /tmp/bragi/* .
rm -r /tmp/bragi
rm -r /tmp/bragi.tar.gz
;;
*)
;;

68
util.py
View File

@ -1,5 +1,9 @@
#!/usr/bin/python3
# coding=utf-8
#
# Bragi - A Mumble music bot
# Forked from botamusique by azlux (https://github.com/azlux/botamusque)
#
import hashlib
import html
@ -102,64 +106,8 @@ def get_user_ban():
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():
@ -311,7 +259,7 @@ def get_url_from_input(string):
else:
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:
url = match[1].lower() + "://" + match[2].lower() + "/" + match[3]
# https://github.com/mumble-voip/mumble/issues/4999
@ -376,7 +324,7 @@ def get_media_duration(path):
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[1] is None and match[2] is None:
return float(match[3])
@ -399,7 +347,7 @@ def format_time(seconds):
def parse_file_size(human):
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}
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:
num = float(match[1])
unit = match[2].upper()
@ -428,7 +376,7 @@ def get_supported_language():
lang_files = os.listdir(os.path.join(root_dir, 'lang'))
lang_list = []
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:
lang_list.append(match[1])

View File

@ -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
if TYPE_CHECKING: