Merge branch 'pr/878' into 440-test-build
This commit is contained in:
commit
2a23c627df
|
@ -0,0 +1,102 @@
|
|||
name: Build Containers
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
workflow_dispatch: []
|
||||
|
||||
jobs:
|
||||
build-client:
|
||||
runs-on: [ubuntu-latest]
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2.3.4
|
||||
-
|
||||
name: Docker meta
|
||||
id: docker_meta
|
||||
uses: crazy-max/ghaction-docker-meta@v2
|
||||
with:
|
||||
images: |
|
||||
ghcr.io/hydrusnetwork/hydrus
|
||||
tags: |
|
||||
type=ref,event=tag
|
||||
labels: |
|
||||
org.opencontainers.image.title=Hydrus Network
|
||||
org.opencontainers.image.description=A personal booru-style media tagger that can import files and tags from your hard drive and popular websites.
|
||||
org.opencontainers.image.vendor=hydrusnetwork
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
with:
|
||||
buildkitd-flags: "--debug"
|
||||
-
|
||||
name: Login to GHCR
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ secrets.GHCR_USERNAME }}
|
||||
password: ${{ secrets.GHCR_TOKEN }}
|
||||
-
|
||||
name: Build
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
file: ./static/build_files/docker/client/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64,linux/ppc64le,linux/386,linux/arm/v7
|
||||
tags: ${{ steps.docker_meta.outputs.tags }}
|
||||
labels: ${{ steps.docker_meta.outputs.labels }}
|
||||
|
||||
build-server:
|
||||
runs-on: [ubuntu-latest]
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2.3.4
|
||||
-
|
||||
name: Docker meta
|
||||
id: docker_meta
|
||||
uses: crazy-max/ghaction-docker-meta@v2
|
||||
with:
|
||||
images: |
|
||||
ghcr.io/hydrusnetwork/hydrus
|
||||
tags: |
|
||||
type=ref,event=tag,prefix=server-
|
||||
type=raw,enable=true,prefix=,suffix=,value=server
|
||||
flavor: |
|
||||
latest=false
|
||||
labels: |
|
||||
org.opencontainers.image.title=Hydrus Network Server
|
||||
org.opencontainers.image.description=A personal booru-style media tagger that can import files and tags from your hard drive and popular websites.
|
||||
org.opencontainers.image.vendor=hydrusnetwork
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
with:
|
||||
buildkitd-flags: "--debug"
|
||||
-
|
||||
name: Login to GHCR
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ secrets.GHCR_USERNAME }}
|
||||
password: ${{ secrets.GHCR_TOKEN }}
|
||||
-
|
||||
name: Build
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
file: ./static/build_files/docker/server/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64,linux/ppc64le,linux/386,linux/arm/v7
|
||||
tags: ${{ steps.docker_meta.outputs.tags }}
|
||||
labels: ${{ steps.docker_meta.outputs.labels }}
|
|
@ -0,0 +1,270 @@
|
|||
name: Release
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
workflow_dispatch: []
|
||||
|
||||
jobs:
|
||||
build-macos:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Setup FFMPEG
|
||||
uses: FedericoCarboni/setup-ffmpeg@v1
|
||||
id: setup_ffmpeg
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
-
|
||||
name: Setup Rust Tollchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
-
|
||||
name: Cargo Cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cargo
|
||||
key: ${{ runner.os }}-cargo-${{ hashFiles('Cargo.toml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cargo-${{ hashFiles('Cargo.toml') }}
|
||||
${{ runner.os }}-cargo
|
||||
-
|
||||
name: Cargo Artifacts Cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: target
|
||||
key: ${{ runner.os }}-cargo-target-${{ hashFiles('Cargo.toml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cargo-target-${{ hashFiles('Cargo.toml') }}
|
||||
${{ runner.os }}-cargo-target
|
||||
-
|
||||
name: Install PyOxidizer
|
||||
uses: actions-rs/cargo@v1.0.3
|
||||
with:
|
||||
command: install
|
||||
args: pyoxidizer
|
||||
-
|
||||
name: Build Hydrus
|
||||
run: |
|
||||
cd $GITHUB_WORKSPACE
|
||||
cp ${{ steps.setup_ffmpeg.outputs.ffmpeg-path }} bin/
|
||||
cp static/build_files/macos/pyoxidizer.bzl pyoxidizer.bzl
|
||||
cp static/build_files/linux/requirements.txt requirements.txt
|
||||
basename $(rustc --print sysroot) | sed -e "s/^stable-//" > triple.txt
|
||||
pyoxidizer build --release
|
||||
cd build/$(head -n 1 triple.txt)/release
|
||||
mkdir -p "Hydrus Network.app/Contents/MacOS"
|
||||
mkdir -p "Hydrus Network.app/Contents/Resources"
|
||||
mkdir -p "Hydrus Network.app/Contents/Frameworks"
|
||||
mv install/static/icon.icns "Hydrus Network.app/Contents/Resources/icon.icns"
|
||||
cp install/static/build_files/macos/Info.plist "Hydrus Network.app/Contents/Info.plist"
|
||||
cp install/static/build_files/macos/ReadMeFirst.rtf ./ReadMeFirst.rtf
|
||||
cp install/static/build_files/macos/running_from_app "install/running_from_app"
|
||||
ln -s /Applications ./Applications
|
||||
mv install/* "Hydrus Network.app/Contents/MacOS/"
|
||||
rm -rf install
|
||||
cd $GITHUB_WORKSPACE
|
||||
temp_dmg="$(mktemp).dmg"
|
||||
hdiutil create "$temp_dmg" -ov -volname "HydrusNetwork" -fs HFS+ -srcfolder "$GITHUB_WORKSPACE/build/$(head -n 1 triple.txt)/release"
|
||||
hdiutil convert "$temp_dmg" -format UDZO -o HydrusNetwork.dmg
|
||||
-
|
||||
name: Upload a Build Artifact
|
||||
uses: actions/upload-artifact@v2.2.1
|
||||
with:
|
||||
name: MacOS-DMG
|
||||
path: HydrusNetwork.dmg
|
||||
if-no-files-found: error
|
||||
retention-days: 2
|
||||
|
||||
build-ubuntu:
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: hydrus
|
||||
-
|
||||
name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.8
|
||||
architecture: x64
|
||||
#- name: Cache Qt
|
||||
# id: cache-qt
|
||||
# uses: actions/cache@v1
|
||||
# with:
|
||||
# path: Qt
|
||||
# key: ${{ runner.os }}-QtCache
|
||||
#-
|
||||
# name: Install Qt
|
||||
# uses: jurplel/install-qt-action@v2
|
||||
# with:
|
||||
# install-deps: true
|
||||
# setup-python: 'false'
|
||||
# modules: qtcharts qtwidgets qtgui qtcore
|
||||
# cached: ${{ steps.cache-qt.outputs.cache-hit }}
|
||||
-
|
||||
name: APT Install
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libmpv1
|
||||
-
|
||||
name: Pip Installer
|
||||
uses: BSFishy/pip-action@v1
|
||||
with:
|
||||
packages: pyinstaller
|
||||
requirements: hydrus/static/build_files/linux/requirements.txt
|
||||
-
|
||||
name: Build Hydrus
|
||||
run: |
|
||||
cp hydrus/static/build_files/linux/client.spec client.spec
|
||||
cp hydrus/static/build_files/linux/server.spec server.spec
|
||||
pyinstaller server.spec
|
||||
pyinstaller client.spec
|
||||
-
|
||||
name: Remove Chonk
|
||||
run: |
|
||||
find dist/client/ -type f -name "*.pyc" -delete
|
||||
while read line; do find dist/client/ -type f -name "${line}" -delete ; done < hydrus/static/build_files/linux/files_to_delete.txt
|
||||
-
|
||||
name: Upload a Build Artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Ubuntu-Extract
|
||||
path: dist/client
|
||||
if-no-files-found: error
|
||||
retention-days: 2
|
||||
|
||||
build-windows:
|
||||
runs-on: [windows-latest]
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: hydrus
|
||||
-
|
||||
name: Setup FFMPEG
|
||||
uses: FedericoCarboni/setup-ffmpeg@v1
|
||||
id: setup_ffmpeg
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
-
|
||||
name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.8
|
||||
architecture: x64
|
||||
-
|
||||
name: Cache Qt
|
||||
id: cache_qt
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ../Qt
|
||||
key: ${{ runner.os }}-QtCache
|
||||
-
|
||||
name: Install Qt
|
||||
uses: jurplel/install-qt-action@v2
|
||||
with:
|
||||
install-deps: true
|
||||
setup-python: 'false'
|
||||
modules: qtcharts qtwidgets qtgui qtcore
|
||||
cached: ${{ steps.cache_qt.outputs.cache-hit }}
|
||||
-
|
||||
name: PIP Install Packages
|
||||
uses: BSFishy/pip-action@v1
|
||||
with:
|
||||
packages: pyinstaller
|
||||
requirements: hydrus\static\build_files\windows\requirements.txt
|
||||
-
|
||||
name: Download mpv-dev
|
||||
uses: carlosperate/download-file-action@v1.0.3
|
||||
id: download_mpv
|
||||
with:
|
||||
file-url: 'https://sourceforge.net/projects/mpv-player-windows/files/libmpv/mpv-dev-x86_64-20210228-git-d1be8bb.7z'
|
||||
file-name: 'mpv-dev-x86_64.7z'
|
||||
location: '.'
|
||||
-
|
||||
name: Process mpv-dev
|
||||
run: |
|
||||
7z x ${{ steps.download_mpv.outputs.file-path }}
|
||||
move mpv-1.dll hydrus\
|
||||
-
|
||||
name: Build Hydrus
|
||||
run: |
|
||||
move ${{ steps.setup_ffmpeg.outputs.ffmpeg-path }} hydrus\bin\
|
||||
move hydrus\static\build_files\windows\sqlite3.dll hydrus\
|
||||
move hydrus\static\build_files\windows\client-win.spec client-win.spec
|
||||
move hydrus\static\build_files\windows\server-win.spec server-win.spec
|
||||
pyinstaller server-win.spec
|
||||
pyinstaller client-win.spec
|
||||
dir -r
|
||||
-
|
||||
name: InnoSetup
|
||||
run: |
|
||||
move hydrus\static\build_files\windows\InnoSetup.iss InnoSetup.iss
|
||||
ISCC.exe InnoSetup.iss
|
||||
-
|
||||
name: Upload a Build Artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Windows-Install
|
||||
path: dist\HydrusInstaller.exe
|
||||
if-no-files-found: error
|
||||
retention-days: 2
|
||||
-
|
||||
name: Upload a Build Artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Windows-Extract
|
||||
path: dist\Hydrus Network
|
||||
if-no-files-found: error
|
||||
retention-days: 2
|
||||
|
||||
create-release:
|
||||
name: Create Release Entry
|
||||
runs-on: ubuntu-20.04
|
||||
needs: [build-windows, build-ubuntu, build-macos]
|
||||
steps:
|
||||
-
|
||||
name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Get All Artifacts
|
||||
uses: actions/download-artifact@v2
|
||||
-
|
||||
name: Extract version metadata
|
||||
id: meta
|
||||
run: |
|
||||
echo "::set-output name=version::${GITHUB_REF##*/}"
|
||||
echo "::set-output name=version_short::${GITHUB_REF##*/v}"
|
||||
-
|
||||
name: Rename Files
|
||||
run: |
|
||||
mkdir ubuntu windows
|
||||
mv MacOS-DMG/HydrusNetwork.dmg Hydrus.Network.${{ steps.meta.outputs.version_short }}.-.macOS.-.App.dmg
|
||||
mv Windows-Install/HydrusInstaller.exe Hydrus.Network.${{ steps.meta.outputs.version_short }}.-.Windows.-.Installer.exe
|
||||
mv Windows-Extract "windows/Hydrus Network"
|
||||
mv Ubuntu-Extract "ubuntu/Hydrus Network"
|
||||
-
|
||||
name: Compress Directories
|
||||
run: |
|
||||
zip -9 -r Hydrus.Network.${{ steps.meta.outputs.version_short }}.-.Windows.-.Extract.only.zip "windows/Hydrus Network"
|
||||
tar -czvf Hydrus.Network.${{ steps.meta.outputs.version_short }}.-.Linux.-.Executable.tar.gz "ubuntu/Hydrus Network"
|
||||
-
|
||||
name: Release new
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
files: |
|
||||
Hydrus.Network.${{ steps.meta.outputs.version_short }}.-.Windows.-.Installer.exe
|
||||
Hydrus.Network.${{ steps.meta.outputs.version_short }}.-.Windows.-.Extract.only.zip
|
||||
Hydrus.Network.${{ steps.meta.outputs.version_short }}.-.Linux.-.Executable.tar.gz
|
||||
Hydrus.Network.${{ steps.meta.outputs.version_short }}.-.macOS.-.App.dmg
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@ -0,0 +1,50 @@
|
|||
FROM ghcr.io/suika/opencv-video-minimal:4.5-py3.8
|
||||
|
||||
ARG UID
|
||||
ARG GID
|
||||
|
||||
HEALTHCHECK --interval=20s --timeout=10s --retries=3 --start-period=30s CMD ! supervisorctl status | grep -v RUNNING
|
||||
ENTRYPOINT ["/bin/sh", "/opt/hydrus/static/build_files/docker/client/entrypoint.sh"]
|
||||
LABEL git="https://github.com/hydrusnetwork/hydrus"
|
||||
|
||||
RUN apk --no-cache add jq fvwm x11vnc xvfb supervisor py3-beautifulsoup4 py3-psutil py3-pysocks py3-requests py3-twisted py3-yaml qt5-qtcharts py3-lz4 ffmpeg py3-pillow py3-numpy py3-numpy py3-qt5 py3-openssl openssl mpv mpv-libs nodejs patch \
|
||||
&& apk add --no-cache -X http://dl-cdn.alpinelinux.org/alpine/edge/community font-noto font-noto-emoji \
|
||||
&& apk add --no-cache -X http://dl-cdn.alpinelinux.org/alpine/edge/community font-noto-cjk
|
||||
RUN pip install qtpy Send2Trash html5lib twisted python-mpv cloudscrape cloudscraper pyparsing
|
||||
|
||||
RUN set -xe \
|
||||
&& mkdir -p /opt/hydrus \
|
||||
&& addgroup -g 1000 hydrus \
|
||||
&& adduser -h /opt/hydrus -u 1000 -H -S -G hydrus hydrus
|
||||
|
||||
RUN mkdir -p /opt/noVNC/utils/websockify \
|
||||
&& wget $(wget https://api.github.com/repos/novnc/noVNC/releases/latest -qO- | jq -r '.tarball_url') -qO- | tar xzf - --strip-components=1 -C /opt/noVNC \
|
||||
&& wget $(wget https://api.github.com/repos/novnc/websockify/releases/latest -qO- | jq -r '.tarball_url') -qO- | tar xzf - --strip-components=1 -C /opt/noVNC/utils/websockify \
|
||||
&& sed -i -- "s/ps -p/ps -o pid | grep/g" /opt/noVNC/utils/launch.sh \
|
||||
&& chown hydrus:hydrus -R /opt/noVNC
|
||||
|
||||
COPY --chown=hydrus . /opt/hydrus
|
||||
COPY --chown=hydrus --from=suika/swftools:2013-04-09-1007 /swftools/swfrender /opt/hydrus/bin/swfrender_linux
|
||||
|
||||
RUN mv /opt/hydrus/static/build_files/docker/client/supervisord.conf /etc/supervisord.conf && \
|
||||
mv /opt/hydrus/static/build_files/docker/client/novnc/index.html /opt/noVNC/index.html && \
|
||||
mv /opt/hydrus/static/build_files/docker/client/novnc/icon.png /opt/noVNC/app/images/icons/icon.png
|
||||
|
||||
RUN ln -fs /usr/bin/python3 /usr/bin/python && ln -fs /usr/bin/pip3 /usr/bin/pip
|
||||
|
||||
VOLUME /opt/hydrus/db
|
||||
|
||||
ENV QT_SCALE_FACTOR=1.1 \
|
||||
VNC_PORT=5900 \
|
||||
NOVNC_PORT=5800 \
|
||||
SUPERVISOR_PORT=9001 \
|
||||
XVFBRES=1680x1050x24 \
|
||||
UID=${UID:-1000} \
|
||||
GID=${GID:-1000} \
|
||||
DB_DIR=/opt/hydrus/db \
|
||||
XVFB_EXTRA="" \
|
||||
VNC_EXTRA="" \
|
||||
NOVNC_EXTRA="" \
|
||||
HYDRUS_EXTRA=""
|
||||
|
||||
EXPOSE 5800 5900
|
|
@ -0,0 +1,26 @@
|
|||
#!/bin/sh
|
||||
|
||||
USER_ID=${UID}
|
||||
GROUP_ID=${GID}
|
||||
|
||||
echo "Starting Hydrus with UID/GID : $USER_ID/$GROUP_ID"
|
||||
|
||||
cd /opt/hydrus/
|
||||
|
||||
if [ -f "/opt/hydrus/static/build_files/docker/client/patch.patch" ]; then
|
||||
echo "Patching Hydrus"
|
||||
patch -f -p1 -i /opt/hydrus/static/build_files/docker/client/patch.patch
|
||||
fi
|
||||
|
||||
if [ -f "/opt/hydrus/static/build_files/docker/client/requests.patch" ]; then
|
||||
cd /usr/lib/python3.8/site-packages/requests
|
||||
echo "Patching Requests"
|
||||
patch -f -p2 -i /opt/hydrus/static/build_files/docker/client/requests.patch
|
||||
cd /opt/hydrus/
|
||||
fi
|
||||
|
||||
#if [ $USER_ID != 0 ] && [ $GROUP_ID != 0 ]; then
|
||||
# find /opt/hydrus/ -not -path "/opt/hydrus/db/*" -exec chown hydrus:hydrus "{}" \;
|
||||
#fi
|
||||
|
||||
exec supervisord -c /etc/supervisord.conf
|
Binary file not shown.
After Width: | Height: | Size: 43 KiB |
|
@ -0,0 +1,328 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" class="noVNC_loading">
|
||||
<head>
|
||||
|
||||
<!--
|
||||
noVNC example: simple example using default UI
|
||||
Copyright (C) 2019 The noVNC Authors
|
||||
noVNC is licensed under the MPL 2.0 (see LICENSE.txt)
|
||||
This file is licensed under the 2-Clause BSD license (see LICENSE.txt).
|
||||
|
||||
Connect parameters are provided in query string:
|
||||
http://example.com/?host=HOST&port=PORT&encrypt=1
|
||||
or the fragment:
|
||||
http://example.com/#host=HOST&port=PORT&encrypt=1
|
||||
-->
|
||||
<title>Hydrus</title>
|
||||
|
||||
<meta charset="utf-8">
|
||||
|
||||
<!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame
|
||||
Remove this if you use the .htaccess -->
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
|
||||
<!-- Icons (see app/images/icons/Makefile for what the sizes are for) -->
|
||||
<link rel="icon" sizes="16x16" type="image/png" href="app/images/icons/icon.png">
|
||||
<link rel="icon" sizes="24x24" type="image/png" href="app/images/icons/icon.png">
|
||||
<link rel="icon" sizes="32x32" type="image/png" href="app/images/icons/icon.png">
|
||||
<link rel="icon" sizes="48x48" type="image/png" href="app/images/icons/icon.png">
|
||||
<link rel="icon" sizes="60x60" type="image/png" href="app/images/icons/icon.png">
|
||||
<link rel="icon" sizes="64x64" type="image/png" href="app/images/icons/icon.png">
|
||||
<link rel="icon" sizes="72x72" type="image/png" href="app/images/icons/icon.png">
|
||||
<link rel="icon" sizes="76x76" type="image/png" href="app/images/icons/icon.png">
|
||||
<link rel="icon" sizes="96x96" type="image/png" href="app/images/icons/icon.png">
|
||||
<link rel="icon" sizes="120x120" type="image/png" href="app/images/icons/icon.png">
|
||||
<link rel="icon" sizes="144x144" type="image/png" href="app/images/icons/icon.png">
|
||||
<link rel="icon" sizes="152x152" type="image/png" href="app/images/icons/icon.png">
|
||||
<link rel="icon" sizes="192x192" type="image/png" href="app/images/icons/icon.png">
|
||||
<!-- Firefox currently mishandles SVG, see #1419039
|
||||
<link rel="icon" sizes="any" type="image/png" href="app/images/icons/icon.png">
|
||||
-->
|
||||
<!-- Repeated last so that legacy handling will pick this -->
|
||||
<link rel="icon" sizes="16x16" type="image/png" href="app/images/icons/icon.png">
|
||||
|
||||
<!-- Apple iOS Safari settings -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||
<!-- Home Screen Icons (favourites and bookmarks use the normal icons) -->
|
||||
<link rel="apple-touch-icon" sizes="60x60" type="image/png" href="app/images/icons/icon.png">
|
||||
<link rel="apple-touch-icon" sizes="76x76" type="image/png" href="app/images/icons/icon.png">
|
||||
<link rel="apple-touch-icon" sizes="120x120" type="image/png" href="app/images/icons/icon.png">
|
||||
<link rel="apple-touch-icon" sizes="152x152" type="image/png" href="app/images/icons/icon.png">
|
||||
|
||||
<!-- Stylesheets -->
|
||||
<link rel="stylesheet" href="app/styles/base.css">
|
||||
|
||||
<!-- this is included as a normal file in order to catch script-loading errors as well -->
|
||||
<script src="app/error-handler.js"></script>
|
||||
|
||||
<!-- begin scripts -->
|
||||
<!-- promise polyfills promises for IE11 -->
|
||||
<script src="vendor/promise.js"></script>
|
||||
<!-- ES2015/ES6 modules polyfill -->
|
||||
<script nomodule src="vendor/browser-es-module-loader/dist/browser-es-module-loader.js"></script>
|
||||
<!-- actual script modules -->
|
||||
<script type="module" crossorigin="anonymous" src="app/ui.js"></script>
|
||||
<!-- end scripts -->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="noVNC_fallback_error" class="noVNC_center">
|
||||
<div>
|
||||
<div>noVNC encountered an error:</div>
|
||||
<br>
|
||||
<div id="noVNC_fallback_errormsg"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- noVNC Control Bar -->
|
||||
<div id="noVNC_control_bar_anchor" class="noVNC_vcenter">
|
||||
|
||||
<div id="noVNC_control_bar">
|
||||
<div id="noVNC_control_bar_handle" title="Hide/Show the control bar"><div></div></div>
|
||||
|
||||
<div class="noVNC_scroll">
|
||||
|
||||
<h1 class="noVNC_logo" translate="no"><span>no</span><br>VNC</h1>
|
||||
|
||||
<!-- Drag/Pan the viewport -->
|
||||
<input type="image" alt="Drag" src="app/images/drag.svg"
|
||||
id="noVNC_view_drag_button" class="noVNC_button noVNC_hidden"
|
||||
title="Move/Drag Viewport">
|
||||
|
||||
<!--noVNC Touch Device only buttons-->
|
||||
<div id="noVNC_mobile_buttons">
|
||||
<input type="image" alt="Keyboard" src="app/images/keyboard.svg"
|
||||
id="noVNC_keyboard_button" class="noVNC_button" title="Show Keyboard">
|
||||
</div>
|
||||
|
||||
<!-- Extra manual keys -->
|
||||
<input type="image" alt="Extra keys" src="app/images/toggleextrakeys.svg"
|
||||
id="noVNC_toggle_extra_keys_button" class="noVNC_button"
|
||||
title="Show Extra Keys">
|
||||
<div class="noVNC_vcenter">
|
||||
<div id="noVNC_modifiers" class="noVNC_panel">
|
||||
<input type="image" alt="Ctrl" src="app/images/ctrl.svg"
|
||||
id="noVNC_toggle_ctrl_button" class="noVNC_button"
|
||||
title="Toggle Ctrl">
|
||||
<input type="image" alt="Alt" src="app/images/alt.svg"
|
||||
id="noVNC_toggle_alt_button" class="noVNC_button"
|
||||
title="Toggle Alt">
|
||||
<input type="image" alt="Windows" src="app/images/windows.svg"
|
||||
id="noVNC_toggle_windows_button" class="noVNC_button"
|
||||
title="Toggle Windows">
|
||||
<input type="image" alt="Tab" src="app/images/tab.svg"
|
||||
id="noVNC_send_tab_button" class="noVNC_button"
|
||||
title="Send Tab">
|
||||
<input type="image" alt="Esc" src="app/images/esc.svg"
|
||||
id="noVNC_send_esc_button" class="noVNC_button"
|
||||
title="Send Escape">
|
||||
<input type="image" alt="Ctrl+Alt+Del" src="app/images/ctrlaltdel.svg"
|
||||
id="noVNC_send_ctrl_alt_del_button" class="noVNC_button"
|
||||
title="Send Ctrl-Alt-Del">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Shutdown/Reboot -->
|
||||
<input type="image" alt="Shutdown/Reboot" src="app/images/power.svg"
|
||||
id="noVNC_power_button" class="noVNC_button"
|
||||
title="Shutdown/Reboot...">
|
||||
<div class="noVNC_vcenter">
|
||||
<div id="noVNC_power" class="noVNC_panel">
|
||||
<div class="noVNC_heading">
|
||||
<img alt="" src="app/images/power.svg"> Power
|
||||
</div>
|
||||
<input type="button" id="noVNC_shutdown_button" value="Shutdown">
|
||||
<input type="button" id="noVNC_reboot_button" value="Reboot">
|
||||
<input type="button" id="noVNC_reset_button" value="Reset">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Clipboard -->
|
||||
<input type="image" alt="Clipboard" src="app/images/clipboard.svg"
|
||||
id="noVNC_clipboard_button" class="noVNC_button"
|
||||
title="Clipboard">
|
||||
<div class="noVNC_vcenter">
|
||||
<div id="noVNC_clipboard" class="noVNC_panel">
|
||||
<div class="noVNC_heading">
|
||||
<img alt="" src="app/images/clipboard.svg"> Clipboard
|
||||
</div>
|
||||
<textarea id="noVNC_clipboard_text" rows=5></textarea>
|
||||
<br>
|
||||
<input id="noVNC_clipboard_clear_button" type="button"
|
||||
value="Clear" class="noVNC_submit">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Toggle fullscreen -->
|
||||
<input type="image" alt="Fullscreen" src="app/images/fullscreen.svg"
|
||||
id="noVNC_fullscreen_button" class="noVNC_button noVNC_hidden"
|
||||
title="Fullscreen">
|
||||
|
||||
<!-- Settings -->
|
||||
<input type="image" alt="Settings" src="app/images/settings.svg"
|
||||
id="noVNC_settings_button" class="noVNC_button"
|
||||
title="Settings">
|
||||
<div class="noVNC_vcenter">
|
||||
<div id="noVNC_settings" class="noVNC_panel">
|
||||
<ul>
|
||||
<li class="noVNC_heading">
|
||||
<img alt="" src="app/images/settings.svg"> Settings
|
||||
</li>
|
||||
<li>
|
||||
<label><input id="noVNC_setting_shared" type="checkbox"> Shared Mode</label>
|
||||
</li>
|
||||
<li>
|
||||
<label><input id="noVNC_setting_view_only" type="checkbox"> View Only</label>
|
||||
</li>
|
||||
<li><hr></li>
|
||||
<li>
|
||||
<label><input id="noVNC_setting_view_clip" type="checkbox"> Clip to Window</label>
|
||||
</li>
|
||||
<li>
|
||||
<label for="noVNC_setting_resize">Scaling Mode:</label>
|
||||
<select id="noVNC_setting_resize" name="vncResize">
|
||||
<option value="off">None</option>
|
||||
<option value="scale">Local Scaling</option>
|
||||
<option value="remote">Remote Resizing</option>
|
||||
</select>
|
||||
</li>
|
||||
<li><hr></li>
|
||||
<li>
|
||||
<div class="noVNC_expander">Advanced</div>
|
||||
<div><ul>
|
||||
<li>
|
||||
<label for="noVNC_setting_quality">Quality:</label>
|
||||
<input id="noVNC_setting_quality" type="range" min="0" max="9" value="6">
|
||||
</li>
|
||||
<li>
|
||||
<label for="noVNC_setting_compression">Compression level:</label>
|
||||
<input id="noVNC_setting_compression" type="range" min="0" max="9" value="2">
|
||||
</li>
|
||||
<li><hr></li>
|
||||
<li>
|
||||
<label for="noVNC_setting_repeaterID">Repeater ID:</label>
|
||||
<input id="noVNC_setting_repeaterID" type="text" value="">
|
||||
</li>
|
||||
<li>
|
||||
<div class="noVNC_expander">WebSocket</div>
|
||||
<div><ul>
|
||||
<li>
|
||||
<label><input id="noVNC_setting_encrypt" type="checkbox"> Encrypt</label>
|
||||
</li>
|
||||
<li>
|
||||
<label for="noVNC_setting_host">Host:</label>
|
||||
<input id="noVNC_setting_host">
|
||||
</li>
|
||||
<li>
|
||||
<label for="noVNC_setting_port">Port:</label>
|
||||
<input id="noVNC_setting_port" type="number">
|
||||
</li>
|
||||
<li>
|
||||
<label for="noVNC_setting_path">Path:</label>
|
||||
<input id="noVNC_setting_path" type="text" value="websockify">
|
||||
</li>
|
||||
</ul></div>
|
||||
</li>
|
||||
<li><hr></li>
|
||||
<li>
|
||||
<label><input id="noVNC_setting_reconnect" type="checkbox"> Automatic Reconnect</label>
|
||||
</li>
|
||||
<li>
|
||||
<label for="noVNC_setting_reconnect_delay">Reconnect Delay (ms):</label>
|
||||
<input id="noVNC_setting_reconnect_delay" type="number">
|
||||
</li>
|
||||
<li><hr></li>
|
||||
<li>
|
||||
<label><input id="noVNC_setting_show_dot" type="checkbox"> Show Dot when No Cursor</label>
|
||||
</li>
|
||||
<li><hr></li>
|
||||
<!-- Logging selection dropdown -->
|
||||
<li>
|
||||
<label>Logging:
|
||||
<select id="noVNC_setting_logging" name="vncLogging">
|
||||
</select>
|
||||
</label>
|
||||
</li>
|
||||
</ul></div>
|
||||
</li>
|
||||
<li class="noVNC_version_separator"><hr></li>
|
||||
<li class="noVNC_version_wrapper">
|
||||
<span>Version:</span>
|
||||
<span class="noVNC_version"></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Connection Controls -->
|
||||
<input type="image" alt="Disconnect" src="app/images/disconnect.svg"
|
||||
id="noVNC_disconnect_button" class="noVNC_button"
|
||||
title="Disconnect">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="noVNC_control_bar_hint"></div>
|
||||
|
||||
</div> <!-- End of noVNC_control_bar -->
|
||||
|
||||
<!-- Status Dialog -->
|
||||
<div id="noVNC_status"></div>
|
||||
|
||||
<!-- Connect button -->
|
||||
<div class="noVNC_center">
|
||||
<div id="noVNC_connect_dlg">
|
||||
<div class="noVNC_logo" translate="no"><span>no</span>VNC</div>
|
||||
<div id="noVNC_connect_button"><div>
|
||||
<img alt="" src="app/images/connect.svg"> Connect
|
||||
</div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Password Dialog -->
|
||||
<div class="noVNC_center noVNC_connect_layer">
|
||||
<div id="noVNC_credentials_dlg" class="noVNC_panel"><form>
|
||||
<ul>
|
||||
<li id="noVNC_username_block">
|
||||
<label>Username:</label>
|
||||
<input id="noVNC_username_input">
|
||||
</li>
|
||||
<li id="noVNC_password_block">
|
||||
<label>Password:</label>
|
||||
<input id="noVNC_password_input" type="password">
|
||||
</li>
|
||||
<li>
|
||||
<input id="noVNC_credentials_button" type="submit" value="Send Credentials" class="noVNC_submit">
|
||||
</li>
|
||||
</ul>
|
||||
</form></div>
|
||||
</div>
|
||||
|
||||
<!-- Transition Screens -->
|
||||
<div id="noVNC_transition">
|
||||
<div id="noVNC_transition_text"></div>
|
||||
<div>
|
||||
<input type="button" id="noVNC_cancel_reconnect_button" value="Cancel" class="noVNC_submit">
|
||||
</div>
|
||||
<div class="noVNC_spinner"></div>
|
||||
</div>
|
||||
|
||||
<!-- This is where the RFB elements will attach -->
|
||||
<div id="noVNC_container">
|
||||
<!-- Note that Google Chrome on Android doesn't respect any of these,
|
||||
html attributes which attempt to disable text suggestions on the
|
||||
on-screen keyboard. Let's hope Chrome implements the ime-mode
|
||||
style for example -->
|
||||
<textarea id="noVNC_keyboardinput" autocapitalize="off"
|
||||
autocomplete="off" spellcheck="false" tabindex="-1"></textarea>
|
||||
</div>
|
||||
|
||||
<audio id="noVNC_bell">
|
||||
<source src="app/sounds/bell.oga" type="audio/ogg">
|
||||
<source src="app/sounds/bell.mp3" type="audio/mpeg">
|
||||
</audio>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,189 @@
|
|||
From 063f2ae0e67111467fc21a2498e426e42f8fae4b Mon Sep 17 00:00:00 2001
|
||||
From: suika <2320837+Suika@users.noreply.github.com>
|
||||
Date: Thu, 24 Sep 2020 15:49:53 +0200
|
||||
Subject: [PATCH 1/4] Bypass proxy if no_proxy or no are set, merge proxy and
|
||||
self.proxy
|
||||
|
||||
Check if the proxy should be bypassed in case no_proxy or no match the host of the url.
|
||||
Also, since proxy can be defined in the session and the reuquest itself, both of them were never merged. Now they self.proxies will be updated by proxies.
|
||||
---
|
||||
requests/sessions.py | 22 +++++++++++++++++++++-
|
||||
1 file changed, 21 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/requests/sessions.py b/requests/sessions.py
|
||||
index fdf7e9fe35..bdaf515a65 100644
|
||||
--- a/requests/sessions.py
|
||||
+++ b/requests/sessions.py
|
||||
@@ -529,6 +529,14 @@ def request(self, method, url,
|
||||
|
||||
proxies = proxies or {}
|
||||
|
||||
+ # Update self.proxy with proxy and assing the result to proxies
|
||||
+ if isinstance(proxies,dict):
|
||||
+ slef_proxies_tmp = self.proxies.copy()
|
||||
+ slef_proxies_tmp.update(proxies)
|
||||
+ proxies = slef_proxies_tmp.copy()
|
||||
+ else:
|
||||
+ proxies = self.proxies.copy()
|
||||
+
|
||||
settings = self.merge_environment_settings(
|
||||
prep.url, proxies, stream, verify, cert
|
||||
)
|
||||
@@ -705,6 +713,7 @@ def merge_environment_settings(self, url, proxies, stream, verify, cert):
|
||||
:rtype: dict
|
||||
"""
|
||||
# Gather clues from the surrounding environment.
|
||||
+ bypass_proxy = False
|
||||
if self.trust_env:
|
||||
# Set environment's proxies.
|
||||
no_proxy = proxies.get('no_proxy') if proxies is not None else None
|
||||
@@ -712,6 +721,14 @@ def merge_environment_settings(self, url, proxies, stream, verify, cert):
|
||||
for (k, v) in env_proxies.items():
|
||||
proxies.setdefault(k, v)
|
||||
|
||||
+ # Check for no_proxy and no since they could be loaded from environment
|
||||
+ no_proxy = proxies.get('no_proxy') if proxies is not None else None
|
||||
+ no = proxies.get('no') if proxies is not None else None
|
||||
+ if any([no_proxy,no]):
|
||||
+ no_proxy = ','.join(filter(None, (no_proxy, no)))
|
||||
+ if should_bypass_proxies(url, no_proxy):
|
||||
+ bypass_proxy = True
|
||||
+
|
||||
# Look for requests environment configuration and be compatible
|
||||
# with cURL.
|
||||
if verify is True or verify is None:
|
||||
@@ -719,7 +736,10 @@ def merge_environment_settings(self, url, proxies, stream, verify, cert):
|
||||
os.environ.get('CURL_CA_BUNDLE'))
|
||||
|
||||
# Merge all the kwargs.
|
||||
- proxies = merge_setting(proxies, self.proxies)
|
||||
+ if bypass_proxy:
|
||||
+ proxies = {}
|
||||
+ else:
|
||||
+ proxies = merge_setting(proxies, self.proxies)
|
||||
stream = merge_setting(stream, self.stream)
|
||||
verify = merge_setting(verify, self.verify)
|
||||
cert = merge_setting(cert, self.cert)
|
||||
|
||||
From a3afa6b55d7596ab6a06207a32a5c96436a66e8c Mon Sep 17 00:00:00 2001
|
||||
From: suika <2320837+Suika@users.noreply.github.com>
|
||||
Date: Thu, 24 Sep 2020 16:00:30 +0200
|
||||
Subject: [PATCH 2/4] Rename bypass_proxy to bypass_proxies
|
||||
|
||||
Make it match the variable being returned
|
||||
---
|
||||
requests/sessions.py | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/requests/sessions.py b/requests/sessions.py
|
||||
index bdaf515a65..2db637dd6e 100644
|
||||
--- a/requests/sessions.py
|
||||
+++ b/requests/sessions.py
|
||||
@@ -713,7 +713,7 @@ def merge_environment_settings(self, url, proxies, stream, verify, cert):
|
||||
:rtype: dict
|
||||
"""
|
||||
# Gather clues from the surrounding environment.
|
||||
- bypass_proxy = False
|
||||
+ bypass_proxies = False
|
||||
if self.trust_env:
|
||||
# Set environment's proxies.
|
||||
no_proxy = proxies.get('no_proxy') if proxies is not None else None
|
||||
@@ -727,7 +727,7 @@ def merge_environment_settings(self, url, proxies, stream, verify, cert):
|
||||
if any([no_proxy,no]):
|
||||
no_proxy = ','.join(filter(None, (no_proxy, no)))
|
||||
if should_bypass_proxies(url, no_proxy):
|
||||
- bypass_proxy = True
|
||||
+ bypass_proxies = True
|
||||
|
||||
# Look for requests environment configuration and be compatible
|
||||
# with cURL.
|
||||
@@ -736,7 +736,7 @@ def merge_environment_settings(self, url, proxies, stream, verify, cert):
|
||||
os.environ.get('CURL_CA_BUNDLE'))
|
||||
|
||||
# Merge all the kwargs.
|
||||
- if bypass_proxy:
|
||||
+ if bypass_proxies:
|
||||
proxies = {}
|
||||
else:
|
||||
proxies = merge_setting(proxies, self.proxies)
|
||||
|
||||
From 78682f9e21933bc6defca8f236b6c0bde5ac045f Mon Sep 17 00:00:00 2001
|
||||
From: suika <2320837+Suika@users.noreply.github.com>
|
||||
Date: Thu, 24 Sep 2020 16:12:39 +0200
|
||||
Subject: [PATCH 3/4] Move no_proxy check outside trust_env
|
||||
|
||||
It makes more sense to have the check be outside the trust_env. Since it has to be always executed. Because proxy configuration can be performed on the Sessions class.
|
||||
---
|
||||
requests/sessions.py | 16 ++++++++--------
|
||||
1 file changed, 8 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/requests/sessions.py b/requests/sessions.py
|
||||
index 2db637dd6e..178ca7e9a7 100644
|
||||
--- a/requests/sessions.py
|
||||
+++ b/requests/sessions.py
|
||||
@@ -721,20 +721,20 @@ def merge_environment_settings(self, url, proxies, stream, verify, cert):
|
||||
for (k, v) in env_proxies.items():
|
||||
proxies.setdefault(k, v)
|
||||
|
||||
- # Check for no_proxy and no since they could be loaded from environment
|
||||
- no_proxy = proxies.get('no_proxy') if proxies is not None else None
|
||||
- no = proxies.get('no') if proxies is not None else None
|
||||
- if any([no_proxy,no]):
|
||||
- no_proxy = ','.join(filter(None, (no_proxy, no)))
|
||||
- if should_bypass_proxies(url, no_proxy):
|
||||
- bypass_proxies = True
|
||||
-
|
||||
# Look for requests environment configuration and be compatible
|
||||
# with cURL.
|
||||
if verify is True or verify is None:
|
||||
verify = (os.environ.get('REQUESTS_CA_BUNDLE') or
|
||||
os.environ.get('CURL_CA_BUNDLE'))
|
||||
|
||||
+ # Check for no_proxy and no since they could be loaded from environment
|
||||
+ no_proxy = proxies.get('no_proxy') if proxies is not None else None
|
||||
+ no = proxies.get('no') if proxies is not None else None
|
||||
+ if any([no_proxy, no]):
|
||||
+ no_proxy = ','.join(filter(None, (no_proxy, no)))
|
||||
+ if should_bypass_proxies(url, no_proxy):
|
||||
+ bypass_proxy = True
|
||||
+
|
||||
# Merge all the kwargs.
|
||||
if bypass_proxies:
|
||||
proxies = {}
|
||||
|
||||
From 0f6bd04349dc1bb2c0808f4de8583eace7c5aaa3 Mon Sep 17 00:00:00 2001
|
||||
From: suika <2320837+Suika@users.noreply.github.com>
|
||||
Date: Thu, 24 Sep 2020 16:34:20 +0200
|
||||
Subject: [PATCH 4/4] Remove bypass_proxies var and only use
|
||||
should_bypass_proxies
|
||||
|
||||
That logic was left from previous tires fixing no_proxy and since it's quite compact now, it can be removed and should_bypass_proxies should be used instead of setting a var.
|
||||
---
|
||||
requests/sessions.py | 5 +----
|
||||
1 file changed, 1 insertion(+), 4 deletions(-)
|
||||
|
||||
diff --git a/requests/sessions.py b/requests/sessions.py
|
||||
index 178ca7e9a7..4ac01315cb 100644
|
||||
--- a/requests/sessions.py
|
||||
+++ b/requests/sessions.py
|
||||
@@ -713,7 +713,6 @@ def merge_environment_settings(self, url, proxies, stream, verify, cert):
|
||||
:rtype: dict
|
||||
"""
|
||||
# Gather clues from the surrounding environment.
|
||||
- bypass_proxies = False
|
||||
if self.trust_env:
|
||||
# Set environment's proxies.
|
||||
no_proxy = proxies.get('no_proxy') if proxies is not None else None
|
||||
@@ -732,11 +731,9 @@ def merge_environment_settings(self, url, proxies, stream, verify, cert):
|
||||
no = proxies.get('no') if proxies is not None else None
|
||||
if any([no_proxy, no]):
|
||||
no_proxy = ','.join(filter(None, (no_proxy, no)))
|
||||
- if should_bypass_proxies(url, no_proxy):
|
||||
- bypass_proxy = True
|
||||
|
||||
# Merge all the kwargs.
|
||||
- if bypass_proxies:
|
||||
+ if should_bypass_proxies(url, no_proxy):
|
||||
proxies = {}
|
||||
else:
|
||||
proxies = merge_setting(proxies, self.proxies)
|
|
@ -0,0 +1,58 @@
|
|||
[unix_http_server]
|
||||
file=/run/supervisor.sock
|
||||
|
||||
[inet_http_server]
|
||||
port=127.0.0.1:%(ENV_SUPERVISOR_PORT)s
|
||||
|
||||
[rpcinterface:supervisor]
|
||||
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
|
||||
|
||||
[supervisorctl]
|
||||
serverurl=unix:///run/supervisor.sock
|
||||
|
||||
[supervisord]
|
||||
nodaemon=true
|
||||
[program:xvfb]
|
||||
command=Xvfb :89 -ac -listen tcp -screen 0 %(ENV_XVFBRES)s %(ENV_XVFB_EXTRA)s
|
||||
startretries=89
|
||||
autostart=true
|
||||
autorestart=true
|
||||
|
||||
[program:fvwm]
|
||||
command=fvwm -d :89
|
||||
startretries=89
|
||||
autostart=true
|
||||
autorestart=true
|
||||
|
||||
[program:vnc]
|
||||
command=x11vnc -display :89 -forever -noxrecord -noxfixes -noxdamage -rfbport %(ENV_VNC_PORT)s %(ENV_VNC_EXTRA)s
|
||||
startretries=89
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stderr_logfile=/dev/stderr
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile_maxbytes=0
|
||||
|
||||
[program:novnc]
|
||||
command=sh /opt/noVNC/utils/launch.sh --vnc localhost:%(ENV_VNC_PORT)s --listen %(ENV_NOVNC_PORT)s %(ENV_NOVNC_EXTRA)s
|
||||
startretries=89
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stderr_logfile=/dev/stderr
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile_maxbytes=0
|
||||
|
||||
[program:hydrus]
|
||||
environment=DISPLAY=":89",HOME=/opt/hydrus
|
||||
user=hydrus
|
||||
directory=/opt/hydrus
|
||||
command=python3 /opt/hydrus/client.py --db_dir %(ENV_DB_DIR)s %(ENV_HYDRUS_EXTRA)s
|
||||
startretries=89
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stderr_logfile=/dev/stderr
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile_maxbytes=0
|
|
@ -0,0 +1,102 @@
|
|||
name: Build Containers
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
workflow_dispatch: []
|
||||
|
||||
jobs:
|
||||
build-client:
|
||||
runs-on: [ubuntu-latest]
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2.3.4
|
||||
-
|
||||
name: Docker meta
|
||||
id: docker_meta
|
||||
uses: crazy-max/ghaction-docker-meta@v2
|
||||
with:
|
||||
images: |
|
||||
ghcr.io/hydrusnetwork/hydrus
|
||||
tags: |
|
||||
type=ref,event=tag
|
||||
labels: |
|
||||
org.opencontainers.image.title=Hydrus Network
|
||||
org.opencontainers.image.description=A personal booru-style media tagger that can import files and tags from your hard drive and popular websites.
|
||||
org.opencontainers.image.vendor=hydrusnetwork
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
with:
|
||||
buildkitd-flags: "--debug"
|
||||
-
|
||||
name: Login to GHCR
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ secrets.GHCR_USERNAME }}
|
||||
password: ${{ secrets.GHCR_TOKEN }}
|
||||
-
|
||||
name: Build
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
file: ./static/build_files/docker/client/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64,linux/ppc64le,linux/386,linux/arm/v7
|
||||
tags: ${{ steps.docker_meta.outputs.tags }}
|
||||
labels: ${{ steps.docker_meta.outputs.labels }}
|
||||
|
||||
build-server:
|
||||
runs-on: [ubuntu-latest]
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2.3.4
|
||||
-
|
||||
name: Docker meta
|
||||
id: docker_meta
|
||||
uses: crazy-max/ghaction-docker-meta@v2
|
||||
with:
|
||||
images: |
|
||||
ghcr.io/hydrusnetwork/hydrus
|
||||
tags: |
|
||||
type=ref,event=tag,prefix=server-
|
||||
type=raw,enable=true,prefix=,suffix=,value=server
|
||||
flavor: |
|
||||
latest=false
|
||||
labels: |
|
||||
org.opencontainers.image.title=Hydrus Network Server
|
||||
org.opencontainers.image.description=A personal booru-style media tagger that can import files and tags from your hard drive and popular websites.
|
||||
org.opencontainers.image.vendor=hydrusnetwork
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
with:
|
||||
buildkitd-flags: "--debug"
|
||||
-
|
||||
name: Login to GHCR
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ secrets.GHCR_USERNAME }}
|
||||
password: ${{ secrets.GHCR_TOKEN }}
|
||||
-
|
||||
name: Build
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
file: ./static/build_files/docker/server/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64,linux/ppc64le,linux/386,linux/arm/v7
|
||||
tags: ${{ steps.docker_meta.outputs.tags }}
|
||||
labels: ${{ steps.docker_meta.outputs.labels }}
|
|
@ -0,0 +1,29 @@
|
|||
FROM suika/opencv-video-minimal:4.2-py3.7.5
|
||||
|
||||
ARG UID
|
||||
ARG GID
|
||||
|
||||
RUN apk --no-cache add py3-beautifulsoup4 py3-psutil py3-pysocks py3-requests py3-twisted py3-yaml py3-lz4 ffmpeg py3-pillow py3-numpy py3-openssl py3-service_identity openssl su-exec
|
||||
RUN pip install Send2Trash html5lib twisted cloudscrape
|
||||
|
||||
RUN set -xe \
|
||||
&& mkdir -p /opt/hydrus \
|
||||
&& addgroup -g 1000 hydrus \
|
||||
&& adduser -h /opt/hydrus -u 1000 -H -S -G hydrus hydrus
|
||||
|
||||
COPY --chown=hydrus . /opt/hydrus
|
||||
COPY --chown=hydrus --from=suika/swftools:2013-04-09-1007 /swftools/swfrender /opt/hydrus/bin/swfrender_linux
|
||||
|
||||
VOLUME /opt/hydrus/db
|
||||
|
||||
ENV UID=${UID:-1000} \
|
||||
GID=${GID:-1000} \
|
||||
MGMT_PORT=45870
|
||||
|
||||
EXPOSE ${MGMT_PORT}
|
||||
|
||||
ENTRYPOINT ["/bin/sh", "/opt/hydrus/static/build_files/docker/server/entrypoint.sh"]
|
||||
|
||||
HEALTHCHECK --interval=1m --timeout=10s --retries=3 --start-period=10s \
|
||||
CMD wget --quiet --tries=1 --no-check-certificate --spider \
|
||||
https://localhost:${MGMT_PORT} || exit 1
|
|
@ -0,0 +1,16 @@
|
|||
#!/bin/sh
|
||||
|
||||
USER_ID=${UID}
|
||||
GROUP_ID=${GID}
|
||||
|
||||
echo "Starting Hydrus with UID/GID : $USER_ID/$GROUP_ID"
|
||||
|
||||
stop() {
|
||||
python3 /opt/hydrus/server.py stop -d="/opt/hydrus/db"
|
||||
}
|
||||
|
||||
trap "stop" SIGTERM
|
||||
|
||||
su-exec ${USER_ID}:${GROUP_ID} python3 /opt/hydrus/server.py -d="/opt/hydrus/db" --no_daemons &
|
||||
|
||||
wait $!
|
|
@ -0,0 +1,55 @@
|
|||
# -*- mode: python -*-
|
||||
|
||||
import cloudscraper
|
||||
import os
|
||||
cloudscraper_dir = os.path.dirname( cloudscraper.__file__ )
|
||||
|
||||
block_cipher = None
|
||||
|
||||
|
||||
a = Analysis(['hydrus/client.py'],
|
||||
pathex=['.'],
|
||||
binaries=[],
|
||||
datas=[
|
||||
('hydrus/bin', 'bin'),
|
||||
('hydrus/help', 'help'),
|
||||
('hydrus/static', 'static'),
|
||||
('hydrus/client.pyw', '.'),
|
||||
('hydrus/client.py', '.'),
|
||||
('hydrus/server.py', '.'),
|
||||
('dist/server/server', '.'),
|
||||
('hydrus/license.txt', '.'),
|
||||
('hydrus/Readme.txt', '.'),
|
||||
('hydrus/help my client will not boot.txt', '.'),
|
||||
('hydrus/db', 'db'),
|
||||
('hydrus/hydrus', 'hydrus'),
|
||||
(cloudscraper_dir, 'cloudscraper')
|
||||
],
|
||||
hiddenimports=['hydrus/server.py'],
|
||||
hookspath=[],
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
win_no_prefer_redirects=False,
|
||||
win_private_assemblies=False,
|
||||
cipher=block_cipher,
|
||||
noarchive=False)
|
||||
pyz = PYZ(a.pure, a.zipped_data,
|
||||
cipher=block_cipher)
|
||||
exe = EXE(pyz,
|
||||
a.scripts,
|
||||
[],
|
||||
exclude_binaries=True,
|
||||
name='client',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
console=False )
|
||||
coll = COLLECT(exe,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
strip=False,
|
||||
upx=True,
|
||||
upx_exclude=[],
|
||||
name='client')
|
|
@ -0,0 +1,97 @@
|
|||
ld-linux.so.2
|
||||
ld-linux-x86-64.so.2
|
||||
libanl.so.1
|
||||
libasound.so.2
|
||||
libBrokenLocale.so.1
|
||||
libcidn.so.1
|
||||
libcom_err.so.2
|
||||
libc.so.6
|
||||
libdl.so.2
|
||||
libdrm.so.2
|
||||
libEGL.so.1
|
||||
libexpat.so.1
|
||||
libfontconfig.so.1
|
||||
libfreetype.so.6
|
||||
libfribidi.so.0
|
||||
libgbm.so.1
|
||||
libgcc_s.so.1
|
||||
libgdk_pixbuf-2.0.so.0
|
||||
libgio-2.0.so.0
|
||||
libglapi.so.0
|
||||
libGLdispatch.so.0
|
||||
libglib-2.0.so.0
|
||||
libGL.so.1
|
||||
libGLX.so.0
|
||||
libgobject-2.0.so.0
|
||||
libharfbuzz.so.0
|
||||
libICE.so.6
|
||||
libjack.so.0
|
||||
libm.so.6
|
||||
libmvec.so.1
|
||||
libnss_compat.so.2
|
||||
libnss_db.so.2
|
||||
libnss_dns.so.2
|
||||
libnss_files.so.2
|
||||
libnss_hesiod.so.2
|
||||
libnss_nisplus.so.2
|
||||
libnss_nis.so.2
|
||||
libp11-kit.so.0
|
||||
libpango-1.0.so.0
|
||||
libpangocairo-1.0.so.0
|
||||
libpangoft2-1.0.so.0
|
||||
libpthread.so.0
|
||||
libresolv.so.2
|
||||
librt.so.1
|
||||
libSM.so.6
|
||||
libstdc++.so.6
|
||||
libthai.so.0
|
||||
libthread_db.so.1
|
||||
libusb-1.0.so.0
|
||||
libutil.so.1
|
||||
libuuid.so.1
|
||||
libX11.so.6
|
||||
libxcb-dri2.so.0
|
||||
libxcb-dri3.so.0
|
||||
libxcb.so.1
|
||||
libz.so.1
|
||||
libQt53DAnimation.so*
|
||||
libQt53DCore.so*
|
||||
libQt53DExtras.so*
|
||||
libQt53DInput.so*
|
||||
libQt53DLogic.so*
|
||||
libQt53DQuick.so*
|
||||
libQt53DQuickAnimation.so*
|
||||
libQt53DQuickExtras.so*
|
||||
libQt53DQuickInput.so*
|
||||
libQt53DQuickRender.so*
|
||||
libQt53DQuickScene2D.so*
|
||||
libQt53DRender.so*
|
||||
libQt5Bluetooth.so*
|
||||
libQt5Bodymovin.so*
|
||||
libQt5Concurrent.so*
|
||||
libQt5DataVisualization.so*
|
||||
libQt5EglFSDeviceIntegration.so*
|
||||
libQt5Gamepad.so*
|
||||
libQt5Location.so*
|
||||
libQt5Multimedia.so*
|
||||
libQt5MultimediaQuick.so*
|
||||
libQt5Nfc.so*
|
||||
libQt5Positioning.so*
|
||||
libQt5PositioningQuick.so*
|
||||
libQt5Purchasing.so*
|
||||
libQt5QuickControls2.so*
|
||||
libQt5QuickParticles.so*
|
||||
libQt5QuickShapes.so*
|
||||
libQt5QuickTemplates2.so*
|
||||
libQt5QuickTest.so*
|
||||
libQt5RemoteObjects.so*
|
||||
libQt5Scxml.so*
|
||||
libQt5Sensors.so*
|
||||
libQt5Sql.so*
|
||||
libQt5Test.so*
|
||||
libQt5WaylandClient.so*
|
||||
libQt5WaylandCompositor.so*
|
||||
libQt5WebChannel.so*
|
||||
libQt5WebEngine.so*
|
||||
libQt5WebEngineCore.so*
|
||||
libQt5WebView.so*
|
|
@ -0,0 +1,66 @@
|
|||
name: Release
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
build-ubuntu:
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: hydrus
|
||||
-
|
||||
name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.8
|
||||
architecture: x64
|
||||
#- name: Cache Qt
|
||||
# id: cache-qt
|
||||
# uses: actions/cache@v1
|
||||
# with:
|
||||
# path: Qt
|
||||
# key: ${{ runner.os }}-QtCache
|
||||
#-
|
||||
# name: Install Qt
|
||||
# uses: jurplel/install-qt-action@v2
|
||||
# with:
|
||||
# install-deps: true
|
||||
# setup-python: 'false'
|
||||
# modules: qtcharts qtwidgets qtgui qtcore
|
||||
# cached: ${{ steps.cache-qt.outputs.cache-hit }}
|
||||
-
|
||||
name: APT Install
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libmpv1
|
||||
-
|
||||
name: Pip Installer
|
||||
uses: BSFishy/pip-action@v1
|
||||
with:
|
||||
packages: pyinstaller
|
||||
requirements: hydrus/static/build_files/linux/requirements.txt
|
||||
-
|
||||
name: Build Hydrus
|
||||
run: |
|
||||
cp hydrus/static/build_files/linux/client.spec client.spec
|
||||
cp hydrus/static/build_files/linux/server.spec server.spec
|
||||
pyinstaller server.spec
|
||||
pyinstaller client.spec
|
||||
-
|
||||
name: Remove Chonk
|
||||
run: |
|
||||
find dist/client/ -type f -name "*.pyc" -delete
|
||||
while read line; do find dist/client/ -type f -name "${line}" -delete ; done < hydrus/static/build_files/linux/files_to_delete.txt
|
||||
-
|
||||
name: Upload a Build Artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Ubuntu-Extract
|
||||
path: dist/client
|
||||
if-no-files-found: error
|
||||
retention-days: 2
|
|
@ -0,0 +1,23 @@
|
|||
beautifulsoup4>=4.0.0
|
||||
chardet>=3.0.4
|
||||
cloudscraper>=1.2.33
|
||||
html5lib>=1.0.1
|
||||
lxml>=4.5.0
|
||||
lz4>=3.0.0
|
||||
nose>=1.3.0
|
||||
numpy>=1.16.0
|
||||
opencv-python-headless>=4.0.0
|
||||
Pillow>=6.0.0
|
||||
psutil>=5.0.0
|
||||
pylzma>=0.5.0
|
||||
pyOpenSSL>=19.1.0
|
||||
PySide2>=5.15.0
|
||||
PySocks>=1.7.0
|
||||
python-mpv==0.4.5
|
||||
PyYAML>=5.0.0
|
||||
QtPy>=1.9.0
|
||||
requests==2.23.0
|
||||
Send2Trash>=1.5.0
|
||||
service-identity>=18.1.0
|
||||
six>=1.14.0
|
||||
Twisted>=20.3.0
|
|
@ -0,0 +1,36 @@
|
|||
# -*- mode: python -*-
|
||||
|
||||
block_cipher = None
|
||||
|
||||
|
||||
a = Analysis(['hydrus/server.py'],
|
||||
pathex=['.'],
|
||||
binaries=[],
|
||||
datas=[],
|
||||
hiddenimports=[],
|
||||
hookspath=[],
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
win_no_prefer_redirects=False,
|
||||
win_private_assemblies=False,
|
||||
cipher=block_cipher,
|
||||
noarchive=False)
|
||||
pyz = PYZ(a.pure, a.zipped_data,
|
||||
cipher=block_cipher)
|
||||
exe = EXE(pyz,
|
||||
a.scripts,
|
||||
[],
|
||||
exclude_binaries=True,
|
||||
name='server',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
console=True )
|
||||
coll = COLLECT(exe,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
strip=False,
|
||||
upx=True,
|
||||
name='server')
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>client</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>MacOS/client</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>icon.icns</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>client</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>client</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.0.0</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<string>True</string></dict>
|
||||
</plist>
|
|
@ -0,0 +1,80 @@
|
|||
name: Release
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
build-macos:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Setup FFMPEG
|
||||
uses: FedericoCarboni/setup-ffmpeg@v1
|
||||
id: setup_ffmpeg
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
-
|
||||
name: Setup Rust Tollchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
-
|
||||
name: Cargo Cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cargo
|
||||
key: ${{ runner.os }}-cargo-${{ hashFiles('Cargo.toml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cargo-${{ hashFiles('Cargo.toml') }}
|
||||
${{ runner.os }}-cargo
|
||||
-
|
||||
name: Cargo Artifacts Cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: target
|
||||
key: ${{ runner.os }}-cargo-target-${{ hashFiles('Cargo.toml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cargo-target-${{ hashFiles('Cargo.toml') }}
|
||||
${{ runner.os }}-cargo-target
|
||||
-
|
||||
name: Install PyOxidizer
|
||||
uses: actions-rs/cargo@v1.0.3
|
||||
with:
|
||||
command: install
|
||||
args: pyoxidizer
|
||||
-
|
||||
name: Build Hydrus
|
||||
run: |
|
||||
cd $GITHUB_WORKSPACE
|
||||
cp ${{ steps.setup_ffmpeg.outputs.ffmpeg-path }} bin/
|
||||
cp static/build_files/macos/pyoxidizer.bzl pyoxidizer.bzl
|
||||
cp static/build_files/linux/requirements.txt requirements.txt
|
||||
basename $(rustc --print sysroot) | sed -e "s/^stable-//" > triple.txt
|
||||
pyoxidizer build --release
|
||||
cd build/$(head -n 1 triple.txt)/release
|
||||
mkdir -p "Hydrus Network.app/Contents/MacOS"
|
||||
mkdir -p "Hydrus Network.app/Contents/Resources"
|
||||
mkdir -p "Hydrus Network.app/Contents/Frameworks"
|
||||
mv install/static/icon.icns "Hydrus Network.app/Contents/Resources/icon.icns"
|
||||
cp install/static/build_files/macos/Info.plist "Hydrus Network.app/Contents/Info.plist"
|
||||
cp install/static/build_files/macos/ReadMeFirst.rtf ./ReadMeFirst.rtf
|
||||
cp install/static/build_files/macos/running_from_app "install/running_from_app"
|
||||
ln -s /Applications ./Applications
|
||||
mv install/* "Hydrus Network.app/Contents/MacOS/"
|
||||
rm -rf install
|
||||
cd $GITHUB_WORKSPACE
|
||||
temp_dmg="$(mktemp).dmg"
|
||||
hdiutil create "$temp_dmg" -ov -volname "HydrusNetwork" -fs HFS+ -srcfolder "$GITHUB_WORKSPACE/build/$(head -n 1 triple.txt)/release"
|
||||
hdiutil convert "$temp_dmg" -format UDZO -o HydrusNetwork.dmg
|
||||
-
|
||||
name: Upload a Build Artifact
|
||||
uses: actions/upload-artifact@v2.2.1
|
||||
with:
|
||||
name: MacOS-DMG
|
||||
path: HydrusNetwork.dmg
|
||||
if-no-files-found: error
|
||||
retention-days: 2
|
|
@ -0,0 +1,63 @@
|
|||
def make_dist():
|
||||
return default_python_distribution()
|
||||
|
||||
def make_packaging_policy(dist):
|
||||
policy = dist.make_python_packaging_policy()
|
||||
policy.set_resource_handling_mode("files")
|
||||
policy.resources_location = "filesystem-relative:lib"
|
||||
policy.allow_files = True
|
||||
policy.bytecode_optimize_level_zero = True
|
||||
|
||||
return policy
|
||||
|
||||
def make_client(dist, policy):
|
||||
python_config = dist.make_python_interpreter_config()
|
||||
python_config.module_search_paths = ["$ORIGIN", "$ORIGIN/lib"]
|
||||
python_config.filesystem_importer = True
|
||||
python_config.sys_frozen = True
|
||||
python_config.run_command = "import os; import sys; exec(open(os.path.join(os.path.split(sys.executable)[0], 'client.py')).read())"
|
||||
|
||||
client = dist.to_python_executable(
|
||||
name="client",
|
||||
packaging_policy=policy,
|
||||
config=python_config,
|
||||
)
|
||||
|
||||
client.add_python_resources(client.pip_install(["--prefer-binary", "-r", "requirements.txt"]))
|
||||
|
||||
return client
|
||||
|
||||
def make_embedded_resources(client):
|
||||
return client.to_embedded_resources()
|
||||
|
||||
def make_install(client, resources):
|
||||
files = FileManifest()
|
||||
files.add_python_resource(".", client)
|
||||
|
||||
static_resources = glob(["./*.py", "./*.md", "./*txt", "./bin/**/*", "./static/**/*", "./help/**/*"], strip_prefix="{}/".format(CWD))
|
||||
files.add_manifest(static_resources)
|
||||
|
||||
hydrus_source = glob(["./hydrus/**/*.py"], strip_prefix="{}/".format(CWD))
|
||||
files.add_manifest(hydrus_source)
|
||||
|
||||
return files
|
||||
|
||||
print(BUILD_TARGET_TRIPLE)
|
||||
print(CWD)
|
||||
|
||||
# Tell PyOxidizer about the build targets defined above.
|
||||
register_target("dist", make_dist)
|
||||
register_target("policy", make_packaging_policy, depends=["dist"])
|
||||
register_target("client", make_client, depends=["dist", "policy"])
|
||||
register_target("resources", make_embedded_resources, depends=["client"], default_build_script=True)
|
||||
register_target("install", make_install, depends=["client", "resources"], default=True)
|
||||
|
||||
resolve_targets()
|
||||
|
||||
# END OF COMMON USER-ADJUSTED SETTINGS.
|
||||
#
|
||||
# Everything below this is typically managed by PyOxidizer and doesn't need
|
||||
# to be updated by people.
|
||||
|
||||
PYOXIDIZER_VERSION = "0.10.3"
|
||||
PYOXIDIZER_COMMIT = "UNKNOWN"
|
|
@ -0,0 +1,23 @@
|
|||
beautifulsoup4>=4.0.0
|
||||
chardet>=3.0.4
|
||||
cloudscraper>=1.2.33
|
||||
html5lib>=1.0.1
|
||||
lxml>=4.5.0
|
||||
lz4>=3.0.0
|
||||
nose>=1.3.0
|
||||
numpy>=1.16.0
|
||||
opencv-python-headless>=4.0.0
|
||||
Pillow>=6.0.0
|
||||
psutil>=5.0.0
|
||||
pylzma>=0.5.0
|
||||
pyOpenSSL>=19.1.0
|
||||
PySide2>=5.15.0
|
||||
PySocks>=1.7.0
|
||||
python-mpv>=0.4.5
|
||||
PyYAML>=5.0.0
|
||||
QtPy>=1.9.0
|
||||
requests==2.23.0
|
||||
Send2Trash>=1.5.0
|
||||
service-identity>=18.1.0
|
||||
six>=1.14.0
|
||||
Twisted>=20.3.0
|
|
@ -0,0 +1,69 @@
|
|||
[Icons]
|
||||
Name: {group}\hydrus client; Filename: {app}\client.exe; WorkingDir: {app}; Tasks: programgroupicons
|
||||
Name: {group}\hydrus server; Filename: {app}\server.exe; WorkingDir: {app}; Tasks: programgroupicons
|
||||
Name: {group}\help; Filename: {app}\help\index.html; WorkingDir: {app}; Tasks: programgroupicons
|
||||
Name: {group}\uninstall hydrus network; Filename: {uninstallexe}; WorkingDir: {app}; Tasks: programgroupicons; IconFilename: {app}\static\cross.ico
|
||||
Name: {userdesktop}\hydrus client; Filename: {app}\client.exe; WorkingDir: {app}; Tasks: desktopicons
|
||||
Name: {userdesktop}\hydrus server; Filename: {app}\server.exe; WorkingDir: {app}; Tasks: desktopicons
|
||||
[Setup]
|
||||
InternalCompressLevel=ultra64
|
||||
OutputDir=dist
|
||||
OutputBaseFilename=HydrusInstaller
|
||||
Compression=lzma/ultra64
|
||||
AppName=Hydrus Network
|
||||
AppVerName=Hydrus Network
|
||||
DefaultDirName={sd}\Hydrus Network
|
||||
DefaultGroupName=Hydrus Network
|
||||
DisableProgramGroupPage=yes
|
||||
DisableReadyPage=yes
|
||||
DisableDirPage=no
|
||||
ShowLanguageDialog=no
|
||||
SetupIconFile=hydrus\static\hydrus.ico
|
||||
Uninstallable=IsComponentSelected('install')
|
||||
UninstallDisplayIcon={app}\static\hydrus.ico
|
||||
[Tasks]
|
||||
Name: desktopicons; Description: Create desktop icons; Flags: unchecked; Components: install
|
||||
Name: programgroupicons; Description: Create program group icons; Components: install
|
||||
[Messages]
|
||||
SelectDirBrowseLabel=To continue, click Next. If you would like to select a different folder, click Browse. Databases will be created beneath the install dir, so make sure the hard drive has enough spare space for your purposes and your user has permission to write there! If you install to program files, you'll need to run the programs as administrator!
|
||||
[Components]
|
||||
Name: install; Description: Install; Types: install; Flags: fixed
|
||||
[Types]
|
||||
Name: install; Description: Install
|
||||
Name: extract; Description: Extract only
|
||||
[Run]
|
||||
Filename: {app}\help\index.html; Description: Open help/getting started guide (highly recommended for new users); Flags: postinstall unchecked shellexec
|
||||
Filename: {app}\client.exe; Description: Open the client; Flags: postinstall nowait unchecked
|
||||
[Files]
|
||||
Source: dist\Hydrus Network\* ; DestDir: {app}; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||
[InstallDelete]
|
||||
Name: {app}\Crypto; Type: filesandordirs; Components: install
|
||||
Name: {app}\tcl; Type: filesandordirs; Components: install
|
||||
Name: {app}\tk; Type: filesandordirs; Components: install
|
||||
Name: {app}\wx; Type: filesandordirs; Components: install
|
||||
Name: {app}\lz4-3.0.2-py3.7.egg-info; Type: filesandordirs; Components: install
|
||||
Name: {app}\lz4-2.1.6-py3.6.egg-info; Type: filesandordirs; Components: install
|
||||
Name: {app}\cryptography-2.9-py3.7.egg-info; Type: filesandordirs; Components: install
|
||||
Name: {app}\cryptography-2.4.2-py3.6.egg-info; Type: filesandordirs; Components: install
|
||||
Name: {app}\lib2to3; Type: filesandordirs; Components: install
|
||||
Name: {app}\mpl-data; Type: filesandordirs; Components: install
|
||||
Name: {app}\matplotlib; Type: filesandordirs; Components: install
|
||||
Name: {app}\cryptography; Type: filesandordirs; Components: install
|
||||
Name: {app}\opencv_ffmpeg344_64.dll; Type: files; Components: install
|
||||
Name: {app}\opencv_ffmpeg400_64.dll; Type: files; Components: install
|
||||
Name: {app}\opencv_ffmpeg410_64.dll; Type: files; Components: install
|
||||
Name: {app}\opencv_videoio_ffmpeg411_64.dll; Type: files; Components: install
|
||||
Name: {app}\opencv_videoio_ffmpeg412_64.dll; Type: files; Components: install
|
||||
Name: {app}\opencv_videoio_ffmpeg420_64.dll; Type: files; Components: install
|
||||
Name: {app}\opencv_videoio_ffmpeg440_64.dll; Type: files; Components: install
|
||||
Name: {app}\wxmsw30u_core_vc140_x64.dll; Type: files; Components: install
|
||||
Name: {app}\wxmsw30u_adv_vc140_x64.dll; Type: files; Components: install
|
||||
Name: {app}\wxbase30u_vc140_x64.dll; Type: files; Components: install
|
||||
Name: {app}\wxbase30u_net_vc140_x64.dll; Type: files; Components: install
|
||||
Name: {app}\tk86t.dll; Type: files; Components: install
|
||||
Name: {app}\tcl86t.dll; Type: files; Components: install
|
||||
Name: {app}\_tkinter.pyd; Type: files; Components: install
|
||||
Name: {app}\_yaml.cp36-win_amd64.pyd; Type: files; Components: install
|
||||
Name: {app}\_yaml.cp37-win_amd64.pyd; Type: files; Components: install
|
||||
Name: {app}\_cffi_backend.cp36-win_amd64.pyd; Type: files; Components: install
|
||||
Name: {app}\_distutils_findvs.pyd; Type: files; Components: install
|
|
@ -0,0 +1,62 @@
|
|||
# -*- mode: python ; coding: utf-8 -*-
|
||||
|
||||
import cloudscraper
|
||||
import cv2
|
||||
import os
|
||||
import glob
|
||||
cloudscraper_dir = os.path.dirname( cloudscraper.__file__ )
|
||||
cv2_ffmpeg_dll = glob.glob(os.path.dirname( cv2.__file__ )+"/*.dll")[0]
|
||||
|
||||
block_cipher = None
|
||||
|
||||
|
||||
a = Analysis(['hydrus\\client.pyw'],
|
||||
pathex=['.'],
|
||||
binaries=[],
|
||||
datas=[
|
||||
('hydrus\\bin', 'bin'),
|
||||
('hydrus\\help', 'help'),
|
||||
('hydrus\\static', 'static'),
|
||||
('hydrus\\client.pyw', '.'),
|
||||
('hydrus\\client.py', '.'),
|
||||
('hydrus\\server.py', '.'),
|
||||
('dist\\server\\server.exe*', '.'),
|
||||
('hydrus\\license.txt', '.'),
|
||||
('hydrus\\Readme.txt', '.'),
|
||||
('hydrus\\help my client will not boot.txt', '.'),
|
||||
('hydrus\\db', 'db'),
|
||||
('hydrus\\hydrus', 'hydrus'),
|
||||
('hydrus\\sqlite3.dll', '.'),
|
||||
('hydrus\\mpv-1.dll', '.'),
|
||||
(cloudscraper_dir, 'cloudscraper'),
|
||||
(cv2_ffmpeg_dll, '.')
|
||||
],
|
||||
hiddenimports=['hydrus\\server.py', 'cloudscraper'],
|
||||
hookspath=[],
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
win_no_prefer_redirects=False,
|
||||
win_private_assemblies=False,
|
||||
cipher=block_cipher,
|
||||
noarchive=False)
|
||||
pyz = PYZ(a.pure, a.zipped_data,
|
||||
cipher=block_cipher)
|
||||
exe = EXE(pyz,
|
||||
a.scripts,
|
||||
[],
|
||||
exclude_binaries=True,
|
||||
name='client',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
console=False,
|
||||
icon='hydrus\\static\\hydrus.ico' )
|
||||
coll = COLLECT(exe,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
strip=False,
|
||||
upx=False,
|
||||
upx_exclude=[],
|
||||
name='Hydrus Network')
|
|
@ -0,0 +1,27 @@
|
|||
PyWin32
|
||||
pypiwin32
|
||||
pywin32-ctypes
|
||||
pefile
|
||||
beautifulsoup4>=4.0.0
|
||||
chardet>=3.0.4
|
||||
cloudscraper>=1.2.33
|
||||
html5lib>=1.0.1
|
||||
lxml>=4.5.0
|
||||
lz4>=3.0.0
|
||||
nose>=1.3.0
|
||||
numpy>=1.16.0
|
||||
opencv-python-headless>=4.0.0
|
||||
Pillow>=6.0.0
|
||||
psutil>=5.0.0
|
||||
pylzma>=0.5.0
|
||||
pyOpenSSL>=19.1.0
|
||||
PySide2>=5.15.0
|
||||
PySocks>=1.7.0
|
||||
python-mpv>=0.4.5
|
||||
PyYAML>=5.0.0
|
||||
QtPy>=1.9.0
|
||||
requests==2.23.0
|
||||
Send2Trash>=1.5.0
|
||||
service-identity>=18.1.0
|
||||
six>=1.14.0
|
||||
Twisted>=20.3.0
|
|
@ -0,0 +1,38 @@
|
|||
# -*- mode: python ; coding: utf-8 -*-
|
||||
|
||||
block_cipher = None
|
||||
|
||||
|
||||
a = Analysis(['hydrus\\server.py'],
|
||||
pathex=['.'],
|
||||
binaries=[],
|
||||
datas=[],
|
||||
hiddenimports=[],
|
||||
hookspath=[],
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
win_no_prefer_redirects=False,
|
||||
win_private_assemblies=False,
|
||||
cipher=block_cipher,
|
||||
noarchive=False)
|
||||
pyz = PYZ(a.pure, a.zipped_data,
|
||||
cipher=block_cipher)
|
||||
exe = EXE(pyz,
|
||||
a.scripts,
|
||||
[],
|
||||
exclude_binaries=True,
|
||||
name='server',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=False,
|
||||
console=False,
|
||||
icon='hydrus\\static\\hydrus.ico' )
|
||||
coll = COLLECT(exe,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
strip=False,
|
||||
upx=False,
|
||||
upx_exclude=[],
|
||||
name='server')
|
Binary file not shown.
|
@ -0,0 +1,92 @@
|
|||
name: Release
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
build-windows:
|
||||
runs-on: [windows-latest]
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: hydrus
|
||||
-
|
||||
name: Setup FFMPEG
|
||||
uses: FedericoCarboni/setup-ffmpeg@v1
|
||||
id: setup_ffmpeg
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
-
|
||||
name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.8
|
||||
architecture: x64
|
||||
-
|
||||
name: Cache Qt
|
||||
id: cache_qt
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ../Qt
|
||||
key: ${{ runner.os }}-QtCache
|
||||
-
|
||||
name: Install Qt
|
||||
uses: jurplel/install-qt-action@v2
|
||||
with:
|
||||
install-deps: true
|
||||
setup-python: 'false'
|
||||
modules: qtcharts qtwidgets qtgui qtcore
|
||||
cached: ${{ steps.cache_qt.outputs.cache-hit }}
|
||||
-
|
||||
name: PIP Install Packages
|
||||
uses: BSFishy/pip-action@v1
|
||||
with:
|
||||
packages: pyinstaller
|
||||
requirements: hydrus\static\build_files\windows\requirements.txt
|
||||
-
|
||||
name: Download mpv-dev
|
||||
uses: carlosperate/download-file-action@v1.0.3
|
||||
id: download_mpv
|
||||
with:
|
||||
file-url: 'https://sourceforge.net/projects/mpv-player-windows/files/libmpv/mpv-dev-x86_64-20210228-git-d1be8bb.7z'
|
||||
file-name: 'mpv-dev-x86_64.7z'
|
||||
location: '.'
|
||||
-
|
||||
name: Process mpv-dev
|
||||
run: |
|
||||
7z x ${{ steps.download_mpv.outputs.file-path }}
|
||||
move mpv-1.dll hydrus\
|
||||
-
|
||||
name: Build Hydrus
|
||||
run: |
|
||||
move ${{ steps.setup_ffmpeg.outputs.ffmpeg-path }} hydrus\bin\
|
||||
move hydrus\static\build_files\windows\sqlite3.dll hydrus\
|
||||
move hydrus\static\build_files\windows\client-win.spec client-win.spec
|
||||
move hydrus\static\build_files\windows\server-win.spec server-win.spec
|
||||
pyinstaller server-win.spec
|
||||
pyinstaller client-win.spec
|
||||
dir -r
|
||||
-
|
||||
name: InnoSetup
|
||||
run: |
|
||||
move hydrus\static\build_files\windows\InnoSetup.iss InnoSetup.iss
|
||||
ISCC.exe InnoSetup.iss
|
||||
-
|
||||
name: Upload a Build Artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Windows-Install
|
||||
path: dist\HydrusInstaller.exe
|
||||
if-no-files-found: error
|
||||
retention-days: 2
|
||||
-
|
||||
name: Upload a Build Artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Windows-Extract
|
||||
path: dist\Hydrus Network
|
||||
if-no-files-found: error
|
||||
retention-days: 2
|
Loading…
Reference in New Issue