試著把 aniGamerPlus 改成home assistant add-ons版
先放上成果 - Home Assistant Add-ons版的巴哈姆特動畫瘋自動下載工具 Home assistant addons 本質上是由「Supervisor」服務管理的預先配置 Docker 容器 所以要先能建構 image 來測試一下 在Terminal中
cd /addons/local git clone https://github.com/miyouzi/aniGamerPlus.git cd aniGamerPlus sed -i 's/python:slim/python:3.9-slim/g' Dockerfile
建立檔案 /addons/local/anigamerplus/config.yaml
name: "aniGamerPlus"
version: 0.0.2
slug: "anigamerplus"
description: "巴哈姆特動畫瘋自動下載工具"
url: "https://github.com/lolimanko/hassio-addons/tree/master/anigamerplus"
arch:
- aarch64
- amd64
init: false
ports:
5000/tcp:
5001/tcp:
ports_description:
5000/tcp: Web 控制臺
5001/tcp: SSL Web 控制臺
map:
- type: addon_config
read_only: false
path: /app/configs
- type: media
read_only: False
- type: share
read_only: false
- type: ssl
read_only: false
ingress: true
ingress_port: 5000
panel_icon: mdi:television
options:
cookie:
cookie_overwrite: false
ssl: false
certfile: fullchain.pem
keyfile: privkey.pem
schema:
cookie: str
cookie_overwrite: bool
ssl: bool
certfile: str
keyfile: str
沒問題就開始進行下一步 修改設定檔存放位址 /addon_config/local_anigamerplus 對應到容器內 /config
sed -i "s/db_path = os.path.join(working_dir, 'aniGamer.db')/db_path = '\/config\/aniGamer.db'/g" aniGamerPlus.py sed -i "s/logs_dir = os.path.join(Config.get_working_dir(), 'logs')/logs_dir = '\/config\/logs'/g" ColorPrint.py sed -i "s/config_path = os.path.join(working_dir, 'config.json')/config_path = '\/config\/config.json'/g" Config.py sed -i "s/sn_list_path = os.path.join(working_dir, 'sn_list.txt')/sn_list_path = '\/config\/sn_list.txt'/g" Config.py sed -i "s/cookie_path = os.path.join(working_dir, 'cookie.txt')/cookie_path = '\/config\/cookie.txt'/g" Config.py sed -i "s/logs_dir = os.path.join(working_dir, 'logs')/logs_dir = '\/config\/logs'/g" Config.py sed -i "s/web_log_path = os.path.join(Config.get_working_dir(), 'logs', 'web.log')/web_log_path = '\/config\/logs\/web.log'/g" Dashboard/Server.py
sed -i "s/\.\.\///g" Dashboard/templates/index.html sed -i "s/\.\.\///g" Dashboard/templates/login.html sed -i "s/\.\.\///g" Dashboard/templates/monitor.html sed -i "s/\.\.\///g" Dashboard/templates/register.html sed -i "s/url: '\/uploadConfig',/url: 'uploadConfig',/g" Dashboard/static/js/aniGamerPlus.js sed -i "s/url: '\/manualTask',/url: 'manualTask',/g" Dashboard/static/js/aniGamerPlus.js sed -i "s/url: '\/sn_list',/url: 'sn_list',/g" Dashboard/static/js/aniGamerPlus.js sed -i "s/ws+'\/\/'+window.location.host+'\///g" Dashboard/static/js/monitor.js
然後為了直接從設定中修改cookie 還要在docker中安裝bashio 這是能讓docker和Supervisor溝通的函式庫 雖然大部份時間都只用他讀取設定的功能
ARG BUILD_FROM=python:3.9-slim
# hadolint ignore=DL3006
FROM ${BUILD_FROM}
ENV \
LANG="C.UTF-8" \
DEBIAN_FRONTEND="noninteractive" \
CURL_CA_BUNDLE="/etc/ssl/certs/ca-certificates.crt" \
S6_BEHAVIOUR_IF_STAGE2_FAILS=2 \
S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0 \
S6_CMD_WAIT_FOR_SERVICES=1 \
S6_SERVICES_READYTIME=50
# Set shell
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
# Base system
WORKDIR /usr/src
ARG TARGETARCH
ARG BASHIO_VERSION=0.17.5
ARG TEMPIO_VERSION=2024.11.2
ARG S6_OVERLAY_VERSION=3.2.2.0
RUN \
set -x \
&& if [ -z "${TARGETARCH}" ]; then \
echo "TARGETARCH is not set, please use Docker BuildKit for the build." && exit 1; \
fi \
&& case "${TARGETARCH}" in \
amd64) TEMPIO_ARCH="amd64"; S6_ARCH="x86_64" ;; \
arm64) TEMPIO_ARCH="aarch64"; S6_ARCH="aarch64" ;; \
*) echo "Unsupported TARGETARCH: ${TARGETARCH}" && exit 1 ;; \
esac \
&& apt-get update && apt-get install -y --no-install-recommends \
bash \
jq \
tzdata \
curl \
ca-certificates \
xz-utils \
&& mkdir -p /usr/share/man/man1 \
\
&& curl -L -f -s "https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-${S6_ARCH}.tar.xz" \
| tar Jxvf - -C / \
&& curl -L -f -s "https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-noarch.tar.xz" \
| tar Jxvf - -C / \
&& curl -L -f -s "https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-symlinks-arch.tar.xz" \
| tar Jxvf - -C / \
&& curl -L -f -s "https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-symlinks-noarch.tar.xz" \
| tar Jxvf - -C / \
&& mkdir -p /etc/fix-attrs.d \
&& mkdir -p /etc/services.d \
\
&& curl -L -f -s -o /usr/bin/tempio \
"https://github.com/home-assistant/tempio/releases/download/${TEMPIO_VERSION}/tempio_${TEMPIO_ARCH}" \
&& chmod a+x /usr/bin/tempio \
\
&& mkdir -p /usr/src/bashio \
&& curl -L -f -s "https://github.com/hassio-addons/bashio/archive/v${BASHIO_VERSION}.tar.gz" \
| tar -xzf - --strip 1 -C /usr/src/bashio \
&& mv /usr/src/bashio/lib /usr/lib/bashio \
&& ln -s /usr/lib/bashio/bashio /usr/bin/bashio \
\
&& rm -rf '/var/lib/apt/lists/*' && rm -rf '/usr/src/*'
# S6-Overlay
RUN apt update && \
apt install -y g++ gcc make libevent-dev libffi-dev libxml2-dev libxslt-dev zlib1g-dev ffmpeg && \
rm -rf '/var/lib/apt/lists/*'
WORKDIR /
COPY . .
RUN pip3 install --no-cache-dir -r requirements.txt
COPY run.sh /
RUN chmod a+x /run.sh
CMD [ "/run.sh" ]
ENTRYPOINT ["/init"]
LABEL \
io.hass.type="base" \
io.hass.base.name="debian"
新增run.sh
#!/usr/bin/with-contenv bashio
cookie=$(bashio::config 'cookie')
cookie_overwrite=$(bashio::config 'cookie_overwrite')
ssl=$(bashio::config 'ssl')
certfile=$(bashio::config 'certfile')
keyfile=$(bashio::config 'keyfile')
if [ -f "/config/cookie.txt" ]; then
echo "cookie exist."
if [ $cookie_overwrite == true ]; then
echo $cookie > '/config/cookie.txt'
echo "cookie overwrited ."
fi
else
echo $cookie > '/config/cookie.txt'
echo "cookie create."
fi
exec python3 -u aniGamerPlus.py --bashio $ssl $certfile $keyfile
最後是SSL部分 ingress 無法使用SSL 直接新增在Server.py修改run()新增run_ssl()
def run():
settings = Config.read_settings() # 读取配置
if settings['dashboard']['BasicAuth']:
# BasicAuth 配置
app.config['BASIC_AUTH_USERNAME'] = settings['dashboard']['username'] # BasicAuth user
app.config['BASIC_AUTH_PASSWORD'] = settings['dashboard']['password'] # BasicAuth password
app.config['BASIC_AUTH_FORCE'] = True # 全站验证
basic_auth = BasicAuth(app)
port = settings['dashboard']['port']
host = settings['dashboard']['host']
server = WSGIServer((host, 5000), app, handler_class=WebSocketHandler)
server.serve_forever()
def run_ssl():
settings = Config.read_settings() # 读取配置
if settings['dashboard']['BasicAuth']:
# BasicAuth 配置
app.config['BASIC_AUTH_USERNAME'] = settings['dashboard']['username'] # BasicAuth user
app.config['BASIC_AUTH_PASSWORD'] = settings['dashboard']['password'] # BasicAuth password
app.config['BASIC_AUTH_FORCE'] = True # 全站验证
basic_auth = BasicAuth(app)
port = settings['dashboard']['port']
host = settings['dashboard']['host']
server = WSGIServer((host, 5001), app, handler_class=WebSocketHandler, certfile='/ssl/'+sys.argv[3], keyfile='/ssl/'+sys.argv[4])
wrap_socket = server.wrap_socket
wrap_socket_and_handle = server.wrap_socket_and_handle
# 处理一些浏览器(比如Chrome)尝试 SSL v3 访问时报错
def my_wrap_socket(sock, **_kwargs):
try:
# print('my_wrap_socket')
return wrap_socket(sock, **_kwargs)
except ssl.SSLError:
# print('my_wrap_socket ssl.SSLError')
pass
# 此方法依赖上面的返回值, 因此当尝试访问 SSL v3 时, 这个也会出错
def my_wrap_socket_and_handle(client_socket, address):
try:
# print('my_wrap_socket_and_handle')
return wrap_socket_and_handle(client_socket, address)
except AttributeError:
# print('my_wrap_socket_and_handle AttributeError')
pass
server.wrap_socket = my_wrap_socket
server.wrap_socket_and_handle = my_wrap_socket_and_handle
server.serve_forever()
aniGamerPlus.py中
if len(sys.argv) > 1:
改為:
if sys.argv[1] == '--bashio':
err_print(0,'bashio輸入模式', '', no_sn=True, display_time=False, status=2)
elif len(sys.argv) > 1 :
以及
def run_dashboard():
# 检测端口是否占用
if not port_is_available(settings['dashboard']['port']):
err_print(0, 'Web控制面板啓動失敗', 'Port已被占用! 請到配置文件更換', status=1, no_sn=True)
return
from Dashboard.Server import run as dashboard
server = threading.Thread(target=dashboard)
server.daemon = True
server.start()
if settings['dashboard']['SSL']:
dashboard_address = 'https://'
else:
dashboard_address = 'http://'
if settings['dashboard']['host'] == '0.0.0.0':
host = Config.get_local_ip()
dashboard_address = '【開放外部訪問】訪問地址: ' + dashboard_address
else:
host = settings['dashboard']['host']
dashboard_address = '訪問地址: ' + dashboard_address
dashboard_address = dashboard_address + host + ':' + str(settings['dashboard']['port'])
err_print(0, 'Web控制面板已啓動', dashboard_address, no_sn=True, status=2)
改為
def run_dashboard():
# 检测端口是否占用
if not port_is_available(settings['dashboard']['port']):
err_print(0, 'Web控制面板啓動失敗', 'Port已被占用! 請到配置文件更換', status=1, no_sn=True)
return
#dashboard_address = ''
if settings['dashboard']['host'] == '0.0.0.0':
host = Config.get_local_ip()
else:
host = settings['dashboard']['host']
from Dashboard.Server import run as dashboard
server = threading.Thread(target=dashboard)
server.daemon = True
server.start()
err_print(0, 'Web控制面板已啓動', no_sn=True, status=2)
#if settings['dashboard']['SSL']:
if sys.argv[2] == 'true' :
from Dashboard.Server import run_ssl as dashboard_SSL
Server_SSL = threading.Thread(target=dashboard_SSL)
Server_SSL.daemon = True
Server_SSL.start()
err_print(0, 'SSL Web控制面板已啓動', no_sn=True, status=2)