remove submodule
This commit is contained in:
parent
ed13626f83
commit
ad6788639e
@ -19,19 +19,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
# IDK if I need this
|
|
||||||
# - name: Set docker metadata
|
|
||||||
# id: meta
|
|
||||||
# uses: docker/metadata-action@v5
|
|
||||||
# with:
|
|
||||||
# images: |
|
|
||||||
# gitea.futureporn.net/futureporn/tracker-helper:latest
|
|
||||||
# tags: |
|
|
||||||
# type=ref,event=branch
|
|
||||||
# type=ref,event=pr
|
|
||||||
# type=semver,pattern={{version}}
|
|
||||||
# type=semver,pattern={{major}}.{{minor}}
|
|
||||||
|
|
||||||
- name: Login to Gitea Docker Registry
|
- name: Login to Gitea Docker Registry
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
@ -39,31 +26,30 @@ jobs:
|
|||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
|
||||||
- name: Build futureporn/tracker-helper
|
|
||||||
uses: docker/build-push-action@v6
|
|
||||||
with:
|
|
||||||
context: ./services/tracker-helper
|
|
||||||
push: true
|
|
||||||
tags: gitea.futureporn.net/futureporn/tracker-helper:latest
|
|
||||||
labels: |
|
|
||||||
org.opencontainers.image.description=Opentracker helper service. Adds info_hash whitelisting via HTTP
|
|
||||||
org.opencontainers.image.title=tracker-helper
|
|
||||||
org.opencontainers.image.created={{commit_date 'YYYY-MM-DDTHH:mm:ss.SSS[Z]'}}
|
|
||||||
org.opencontainers.image.licenses=unlicense
|
|
||||||
org.opencontainers.image.source=https://gitea.futureporn.net/futureporn/fp
|
|
||||||
org.opencontainers.image.url=https://gitea.futureporn.net/futureporn/-/packages/container/tracker-helper
|
|
||||||
secrets: |
|
|
||||||
WL_USERNAME=${{ secrets.WL_USERNAME }}
|
|
||||||
WL_PASSWORD=${{ secrets.WL_PASSWORD }}
|
|
||||||
|
|
||||||
- name: Build futureporn/aquatic
|
- name: Build futureporn/aquatic
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: ./apps/aquatic-tracker
|
context: ./apps/aquatic
|
||||||
file: ./apps/aquatic-tracker/docker/aquatic_udp.Dockerfile
|
file: ./apps/aquatic/docker/aquatic_udp.Dockerfile
|
||||||
push: true
|
push: true
|
||||||
tags: gitea.futureporn.net/futureporn/aquatic:latest
|
tags: gitea.futureporn.net/futureporn/aquatic:latest
|
||||||
|
|
||||||
|
- name: Build futureporn/tracker
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: ./services/tracker
|
||||||
|
push: true
|
||||||
|
tags: gitea.futureporn.net/futureporn/tracker:latest
|
||||||
|
labels: |
|
||||||
|
org.opencontainers.image.description=Aquatic tracker with custom helper service, adding info_hash accesslist operations via HTTP
|
||||||
|
org.opencontainers.image.title=tracker
|
||||||
|
org.opencontainers.image.licenses=unlicense
|
||||||
|
org.opencontainers.image.source=https://gitea.futureporn.net/futureporn/fp
|
||||||
|
org.opencontainers.image.url=https://gitea.futureporn.net/futureporn/-/packages/container/tracker
|
||||||
|
secrets: |
|
||||||
|
TRACKER_HELPER_USERNAME=${{ secrets.TRACKER_HELPER_USERNAME }}
|
||||||
|
TRACKER_HELPER_PASSWORD=${{ secrets.TRACKER_HELPER_PASSWORD }}
|
||||||
|
|
||||||
- name: Build futureporn/bright
|
- name: Build futureporn/bright
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
@ -80,18 +66,3 @@ jobs:
|
|||||||
org.opencontainers.image.licenses=unlicense
|
org.opencontainers.image.licenses=unlicense
|
||||||
org.opencontainers.image.source=https://gitea.futureporn.net/futureporn/fp
|
org.opencontainers.image.source=https://gitea.futureporn.net/futureporn/fp
|
||||||
org.opencontainers.image.url=https://gitea.futureporn.net/futureporn/-/packages/container/bright
|
org.opencontainers.image.url=https://gitea.futureporn.net/futureporn/-/packages/container/bright
|
||||||
|
|
||||||
# - name: Build futureporn/opentracker
|
|
||||||
# uses: docker/build-push-action@v6
|
|
||||||
# with:
|
|
||||||
# context: ./apps/opentracker
|
|
||||||
# push: true
|
|
||||||
# tags: gitea.futureporn.net/futureporn/opentracker:latest
|
|
||||||
# labels: |
|
|
||||||
# org.opencontainers.image.description=opentracker is an open and free bittorrent tracker project.
|
|
||||||
# org.opencontainers.image.title=opentracker
|
|
||||||
# org.opencontainers.image.created={{commit_date 'YYYY-MM-DDTHH:mm:ss.SSS[Z]'}}
|
|
||||||
# org.opencontainers.image.version={{version}}
|
|
||||||
# org.opencontainers.image.licenses=beerware
|
|
||||||
# org.opencontainers.image.source=https://erdgeist.org/arts/software/opentracker
|
|
||||||
# org.opencontainers.image.url=https://gitea.futureporn.net/futureporn/-/packages/container/opentracker
|
|
||||||
|
@ -34,9 +34,9 @@ jobs:
|
|||||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
PUBLIC_S3_ENDPOINT: ${{ vars.PUBLIC_S3_ENDPOINT }}
|
PUBLIC_S3_ENDPOINT: ${{ vars.PUBLIC_S3_ENDPOINT }}
|
||||||
SITE_URL: https://futureporn.net
|
SITE_URL: https://futureporn.net
|
||||||
WL_URL: ${{ vars.WL_URL }}
|
TRACKER_HELPER_URL: ${{ vars.TRACKER_HELPER_URL }}
|
||||||
WL_USERNAME: ${{ secrets.WL_USERNAME }}
|
TRACKER_HELPER_USERNAME: ${{ secrets.TRACKER_HELPER_USERNAME }}
|
||||||
WL_PASSWORD: ${{ secrets.WL_PASSWORD }}
|
TRACKER_HELPER_PASSWORD: ${{ secrets.TRACKER_HELPER_PASSWORD }}
|
||||||
DB_NAME: ${{ vars.DB_NAME }}
|
DB_NAME: ${{ vars.DB_NAME }}
|
||||||
DB_HOST: ${{ vars.DB_HOST }}
|
DB_HOST: ${{ vars.DB_HOST }}
|
||||||
DB_PORT: ${{ vars.DB_PORT }}
|
DB_PORT: ${{ vars.DB_PORT }}
|
||||||
@ -72,29 +72,17 @@ jobs:
|
|||||||
--health-timeout 5s
|
--health-timeout 5s
|
||||||
--health-retries 5
|
--health-retries 5
|
||||||
|
|
||||||
tracker-helper:
|
tracker:
|
||||||
image: gitea.futureporn.net/futureporn/tracker-helper:latest
|
image: gitea.futureporn.net/futureporn/tracker:latest
|
||||||
ports:
|
ports:
|
||||||
- 5063:5063
|
- 5063:5063
|
||||||
env:
|
|
||||||
WL_FILE_PATH: /var/lib/aquatic/whitelist
|
|
||||||
WL_USERNAME: ${{ secrets.WL_USERNAME }}
|
|
||||||
WL_PASSWORD: ${{ secrets.WL_PASSWORD }}
|
|
||||||
WL_PORT: 5063
|
|
||||||
volumes:
|
|
||||||
- aquatic:/var/lib/aquatic
|
|
||||||
- /tmp/aquatic:/tmp/aquatic
|
|
||||||
- /tmp/test:/root/test
|
|
||||||
- /test2:/root/test2
|
|
||||||
|
|
||||||
aquatic:
|
|
||||||
image: gitea.futureporn.net/futureporn/aquatic:latest
|
|
||||||
ports:
|
|
||||||
- 3003:3003
|
- 3003:3003
|
||||||
- 9000:9000
|
- 9000:9000
|
||||||
volumes:
|
|
||||||
- aquatic:/var/lib/aquatic
|
|
||||||
env:
|
env:
|
||||||
|
TRACKER_HELPER_ACCESSLIST_PATH: /var/lib/aquatic/whitelist
|
||||||
|
TRACKER_HELPER_USERNAME: ${{ secrets.TRACKER_HELPER_USERNAME }}
|
||||||
|
TRACKER_HELPER_PASSWORD: ${{ secrets.TRACKER_HELPER_PASSWORD }}
|
||||||
|
TRACKER_HELPER_PORT: 5063
|
||||||
ACCESS_LIST_CONTENTS: ""
|
ACCESS_LIST_CONTENTS: ""
|
||||||
CONFIG_FILE_CONTENTS: |
|
CONFIG_FILE_CONTENTS: |
|
||||||
log_level = 'debug'
|
log_level = 'debug'
|
||||||
@ -105,12 +93,12 @@ jobs:
|
|||||||
address_ipv6 = "[::]:3003"
|
address_ipv6 = "[::]:3003"
|
||||||
[statistics]
|
[statistics]
|
||||||
interval = 5
|
interval = 5
|
||||||
print_to_stdout = true
|
print_to_stdout = false
|
||||||
run_prometheus_endpoint = true
|
run_prometheus_endpoint = true
|
||||||
prometheus_endpoint_address = "0.0.0.0:9000"
|
prometheus_endpoint_address = "0.0.0.0:9000"
|
||||||
[access_list]
|
[access_list]
|
||||||
mode = "allow"
|
mode = "allow"
|
||||||
path = "/var/lib/aquatic/whitelist"
|
path = "/var/lib/aquatic/accesslist"
|
||||||
[privileges]
|
[privileges]
|
||||||
# Chroot and switch group and user after binding to sockets
|
# Chroot and switch group and user after binding to sockets
|
||||||
drop_privileges = true
|
drop_privileges = true
|
||||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +0,0 @@
|
|||||||
[submodule "apps/aquatic-tracker"]
|
|
||||||
path = apps/aquatic-tracker
|
|
||||||
url = https://github.com/insanity54/aquatic
|
|
@ -1 +0,0 @@
|
|||||||
Subproject commit 96e69754510c82ad2bbb9d0a2967c8bca0696bbd
|
|
@ -32,9 +32,9 @@ config :bright,
|
|||||||
|
|
||||||
config :bright, :torrent,
|
config :bright, :torrent,
|
||||||
tracker_url: System.get_env("TRACKER_URL"),
|
tracker_url: System.get_env("TRACKER_URL"),
|
||||||
whitelist_url: System.get_env("WL_URL"),
|
tracker_helper_url: System.get_env("TRACKER_HELPER_URL"),
|
||||||
whitelist_username: System.get_env("WL_USERNAME"),
|
tracker_helper_username: System.get_env("TRACKER_HELPER_USERNAME"),
|
||||||
whitelist_password: System.get_env("WL_PASSWORD")
|
tracker_helper_password: System.get_env("TRACKER_HELPER_PASSWORD")
|
||||||
|
|
||||||
config :bright, :buckets, media: System.get_env("AWS_BUCKET")
|
config :bright, :buckets, media: System.get_env("AWS_BUCKET")
|
||||||
|
|
||||||
|
@ -26,8 +26,8 @@ defmodule Bright.ObanWorkers.CreateTorrent do
|
|||||||
cdn_url: cdn_url,
|
cdn_url: cdn_url,
|
||||||
magnet: tf.magnet
|
magnet: tf.magnet
|
||||||
}),
|
}),
|
||||||
{_, _} <- Tracker.whitelist_info_hash(torrent.info_hash_v1),
|
{_, _} <- Tracker.accesslist_info_hash(torrent.info_hash_v1),
|
||||||
{_, _} <- Tracker.whitelist_info_hash(torrent.info_hash_v2),
|
{_, _} <- Tracker.accesslist_info_hash(torrent.info_hash_v2),
|
||||||
{:ok, _updated_vod} <- Streams.update_vod(vod, %{}) do
|
{:ok, _updated_vod} <- Streams.update_vod(vod, %{}) do
|
||||||
{:ok, torrent}
|
{:ok, torrent}
|
||||||
end
|
end
|
||||||
|
@ -13,72 +13,55 @@ defmodule Bright.Tracker do
|
|||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
get the URL to our Bittorrent tracker accesslist URL, which is part of our opentracker docker container.
|
get the URL to our tracker helper accesslist URL, which is part of our tracker docker container.
|
||||||
This is where we send infohashes that end up in opentracker's adder.fifo
|
This is where we send infohashes that end up in aquatic's accesslist
|
||||||
Usually it's port 8666, path /whitelist
|
Usually it's port 5063, path /accesslist
|
||||||
"""
|
"""
|
||||||
@spec whitelist_url() :: binary()
|
@spec accesslist_url() :: binary()
|
||||||
def whitelist_url do
|
def accesslist_url do
|
||||||
url =
|
url =
|
||||||
case Application.fetch_env!(:bright, :torrent)[:whitelist_url] do
|
case Application.fetch_env!(:bright, :torrent)[:tracker_helper_accesslist_url] do
|
||||||
nil -> raise "whitelist_url missing or empty in app config"
|
nil -> raise "accesslist_url missing or empty in app config"
|
||||||
"" -> raise "whitelist_url missing or empty in app config"
|
"" -> raise "accesslist_url missing or empty in app config"
|
||||||
url -> url
|
url -> url
|
||||||
end
|
end
|
||||||
|
|
||||||
Logger.debug("whitelist_url=#{url}")
|
Logger.debug("accesslist_url=#{url}")
|
||||||
url
|
url
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec whitelist_username() :: binary()
|
@spec tracker_helper_username() :: binary()
|
||||||
def whitelist_username do
|
def tracker_helper_username do
|
||||||
case Application.fetch_env!(:bright, :torrent)[:whitelist_username] do
|
case Application.fetch_env!(:bright, :torrent)[:tracker_helper_username] do
|
||||||
nil -> raise "whitelist_username missing or empty in app config"
|
nil -> raise "tracker_helper_username missing or empty in app config"
|
||||||
"" -> raise "whitelist_username missing or empty in app config"
|
"" -> raise "tracker_helper_username missing or empty in app config"
|
||||||
username -> username
|
username -> username
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec whitelist_password() :: binary()
|
@spec tracker_helper_password() :: binary()
|
||||||
def whitelist_password do
|
def tracker_helper_password do
|
||||||
case Application.fetch_env!(:bright, :torrent)[:whitelist_password] do
|
case Application.fetch_env!(:bright, :torrent)[:tracker_helper_password] do
|
||||||
nil -> raise "whitelist_password missing or empty in app config"
|
nil -> raise "tracker_helper_password missing or empty in app config"
|
||||||
"" -> raise "whitelist_password missing or empty in app config"
|
"" -> raise "tracker_helper_password missing or empty in app config"
|
||||||
password -> password
|
password -> password
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec whitelist_feed_url() :: binary()
|
def accesslist_info_hash(info_hash) do
|
||||||
def whitelist_feed_url do
|
accesslist_url = accesslist_url()
|
||||||
case Application.fetch_env!(:bright, :torrent)[:whitelist_feed_url] do
|
username = tracker_helper_username()
|
||||||
nil -> raise "whitelist_feed_url missing or empty in app config"
|
password = tracker_helper_password()
|
||||||
"" -> raise "whitelist_feed_url missing or empty in app config"
|
|
||||||
feed_url -> feed_url
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def whitelist_info_hash(info_hash) do
|
|
||||||
whitelist_url = whitelist_url()
|
|
||||||
username = whitelist_username()
|
|
||||||
password = whitelist_password()
|
|
||||||
|
|
||||||
Logger.debug(
|
Logger.debug(
|
||||||
"Attempting to whitelist info_hash=#{info_hash}, whitelist_url=#{whitelist_url}, whitelist_username=#{username}, whitelist_password=#{password}"
|
"Attempting to accesslist info_hash=#{info_hash}, accesslist_url=#{accesslist_url}, tracker_helper_username=#{username}, tracker_helper_password=#{password}"
|
||||||
)
|
)
|
||||||
|
|
||||||
send_whitelist_request(whitelist_url, info_hash, username, password)
|
send_accesslist_request(accesslist_url, info_hash, username, password)
|
||||||
# case URI.parse(whitelist_url) do
|
|
||||||
# %URI{scheme: scheme, host: host, port: port} when host not in [nil, ""] and port != nil ->
|
|
||||||
# full_url = "#{scheme}://#{host}:#{port}"
|
|
||||||
|
|
||||||
# _ ->
|
|
||||||
# Logger.error("Invalid whitelist_url: #{whitelist_url}")
|
|
||||||
# {:error, :invalid_url}
|
|
||||||
# end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp send_whitelist_request(url, info_hash, username, password) do
|
defp send_accesslist_request(url, info_hash, username, password) do
|
||||||
Logger.debug("send_whitelist_request to url=#{url}")
|
Logger.debug("send_accesslist_request to url=#{url}")
|
||||||
|
|
||||||
headers = [
|
headers = [
|
||||||
{"Content-Type", "text/plain"},
|
{"Content-Type", "text/plain"},
|
||||||
@ -87,12 +70,12 @@ defmodule Bright.Tracker do
|
|||||||
|
|
||||||
case HTTPoison.post(url, info_hash, headers) do
|
case HTTPoison.post(url, info_hash, headers) do
|
||||||
{:ok, %HTTPoison.Response{status_code: 201, body: response_body}} ->
|
{:ok, %HTTPoison.Response{status_code: 201, body: response_body}} ->
|
||||||
Logger.info("Successfully whitelisted info_hash=#{info_hash}")
|
Logger.info("Successfully accesslisted info_hash=#{info_hash}")
|
||||||
{:ok, response_body}
|
{:ok, response_body}
|
||||||
|
|
||||||
{:ok, %HTTPoison.Response{status_code: status_code, body: error_body}} ->
|
{:ok, %HTTPoison.Response{status_code: status_code, body: error_body}} ->
|
||||||
Logger.warning(
|
Logger.warning(
|
||||||
"Whitelist failed: info_hash=#{info_hash}, status=#{status_code}, error=#{error_body}"
|
"accesslist failed: info_hash=#{info_hash}, status=#{status_code}, error=#{error_body}"
|
||||||
)
|
)
|
||||||
|
|
||||||
{:error, %{status: status_code, body: error_body}}
|
{:error, %{status: status_code, body: error_body}}
|
||||||
|
56
apps/tracker-helper/Dockerfile
Normal file
56
apps/tracker-helper/Dockerfile
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
FROM debian:stable-slim AS release
|
||||||
|
ENV PATH=/command:$PATH
|
||||||
|
|
||||||
|
RUN apt-get update -qq \
|
||||||
|
&& apt-get install -y -qq --no-install-recommends \
|
||||||
|
xz-utils \
|
||||||
|
unzip \
|
||||||
|
ca-certificates \
|
||||||
|
curl \
|
||||||
|
&& export BUN_INSTALL=/home/bun \
|
||||||
|
&& curl -fsSL https://bun.sh/install | bash -s "bun-v1.2.2" \
|
||||||
|
&& groupadd bun \
|
||||||
|
&& useradd bun \
|
||||||
|
--gid bun \
|
||||||
|
--shell /bin/sh \
|
||||||
|
--create-home \
|
||||||
|
&& apt-get clean \
|
||||||
|
&& rm -rf /var/lib/apt/lists/* \
|
||||||
|
&& chown -R bun:bun /home/bun
|
||||||
|
|
||||||
|
|
||||||
|
# copy tracker-helper app
|
||||||
|
COPY --from=gitea.futureporn.net/futureporn/tracker-helper:latest /usr/src/app/node_modules /usr/src/tracker-helper/node_modules
|
||||||
|
COPY --from=gitea.futureporn.net/futureporn/tracker-helper:latest /usr/src/app/index.ts /usr/src/tracker-helper/
|
||||||
|
COPY --from=gitea.futureporn.net/futureporn/tracker-helper:latest /usr/src/app/app.ts /usr/src/tracker-helper/
|
||||||
|
COPY --from=gitea.futureporn.net/futureporn/tracker-helper:latest /usr/src/app/package.json /usr/src/tracker-helper/
|
||||||
|
|
||||||
|
# copy aquatic app
|
||||||
|
COPY --from=gitea.futureporn.net/futureporn/aquatic:latest /usr/local/bin/aquatic_udp /usr/local/bin/aquatic_udp
|
||||||
|
|
||||||
|
# copy caddy
|
||||||
|
COPY --from=caddy:alpine /usr/bin/caddy /usr/bin/caddy
|
||||||
|
|
||||||
|
# copy our app (s6-overlay dir structure)
|
||||||
|
COPY ./root /
|
||||||
|
|
||||||
|
|
||||||
|
# 9000/tcp for aquatic_udp metrics /metrics
|
||||||
|
# and tracker-helper api /helper/*
|
||||||
|
# Caddy handles the routing for us
|
||||||
|
EXPOSE 9000/tcp
|
||||||
|
|
||||||
|
# 6969/udp for aquatic_udp
|
||||||
|
EXPOSE 6969/udp
|
||||||
|
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=5s --timeout=3s --retries=3 \
|
||||||
|
CMD /etc/tracker/healthcheck.sh
|
||||||
|
|
||||||
|
|
||||||
|
ADD https://github.com/just-containers/s6-overlay/releases/download/v3.2.0.2/s6-overlay-noarch.tar.xz /tmp
|
||||||
|
RUN tar -C / -Jxpf /tmp/s6-overlay-noarch.tar.xz
|
||||||
|
ADD https://github.com/just-containers/s6-overlay/releases/download/v3.2.0.2/s6-overlay-x86_64.tar.xz /tmp
|
||||||
|
RUN tar -C / -Jxpf /tmp/s6-overlay-x86_64.tar.xz
|
||||||
|
ENTRYPOINT ["/init"]
|
27
apps/tracker-helper/root/etc/aquatic/config.toml
Normal file
27
apps/tracker-helper/root/etc/aquatic/config.toml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
log_level = 'debug'
|
||||||
|
|
||||||
|
[network]
|
||||||
|
use_ipv4 = true
|
||||||
|
use_ipv6 = true
|
||||||
|
address_ipv4 = "0.0.0.0:3003"
|
||||||
|
address_ipv6 = "[::]:3003"
|
||||||
|
|
||||||
|
[statistics]
|
||||||
|
interval = 5
|
||||||
|
print_to_stdout = false
|
||||||
|
run_prometheus_endpoint = true
|
||||||
|
prometheus_endpoint_address = "0.0.0.0:9000"
|
||||||
|
|
||||||
|
[access_list]
|
||||||
|
mode = "allow"
|
||||||
|
path = "/var/lib/aquatic/accesslist"
|
||||||
|
|
||||||
|
[privileges]
|
||||||
|
# Chroot and switch group and user after binding to sockets
|
||||||
|
drop_privileges = true
|
||||||
|
# Chroot to this path
|
||||||
|
chroot_path = "/var/lib/aquatic"
|
||||||
|
# Group to switch to after chrooting
|
||||||
|
group = "nogroup"
|
||||||
|
# User to switch to after chrooting
|
||||||
|
user = "nobody"
|
18
apps/tracker-helper/root/etc/caddy/Caddyfile
Normal file
18
apps/tracker-helper/root/etc/caddy/Caddyfile
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
auto_https off
|
||||||
|
admin off
|
||||||
|
http_port 9000
|
||||||
|
}
|
||||||
|
|
||||||
|
:9000 {
|
||||||
|
|
||||||
|
# Route for tracker-helper service
|
||||||
|
handle_path /helper/* {
|
||||||
|
reverse_proxy localhost:5063
|
||||||
|
}
|
||||||
|
|
||||||
|
# Route for Prometheus metrics
|
||||||
|
handle_path /metrics/* {
|
||||||
|
reverse_proxy localhost:9000
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
#!/command/with-contenv sh
|
||||||
|
|
||||||
|
exec /usr/local/bin/aquatic_udp -c /etc/aquatic/config.toml
|
@ -0,0 +1 @@
|
|||||||
|
longrun
|
@ -0,0 +1,3 @@
|
|||||||
|
#!/command/with-contenv sh
|
||||||
|
|
||||||
|
/usr/bin/caddy run --config /etc/caddy/Caddyfile
|
@ -0,0 +1 @@
|
|||||||
|
longrun
|
@ -0,0 +1,7 @@
|
|||||||
|
#!/command/with-contenv sh
|
||||||
|
|
||||||
|
export PORT=5063
|
||||||
|
|
||||||
|
exec 2>&1
|
||||||
|
exec s6-setuidgid bun \
|
||||||
|
/home/bun/bin/bun run /usr/src/tracker-helper/index.ts
|
@ -0,0 +1 @@
|
|||||||
|
longrun
|
5
apps/tracker-helper/root/etc/tracker/healthcheck.sh
Executable file
5
apps/tracker-helper/root/etc/tracker/healthcheck.sh
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
pidof aquatic_udp || exit 111
|
||||||
|
curl -f http://localhost:5063/helper || exit 112
|
||||||
|
curl -f http://localhost:9000/metrics || exit 113
|
0
apps/tracker-helper/root/var/lib/aquatic/accesslist
Normal file
0
apps/tracker-helper/root/var/lib/aquatic/accesslist
Normal file
@ -107,49 +107,24 @@ accessories:
|
|||||||
- opentracker-etc:/etc/opentracker
|
- opentracker-etc:/etc/opentracker
|
||||||
- opentracker-var:/var/run/opentracker
|
- opentracker-var:/var/run/opentracker
|
||||||
|
|
||||||
# opentracker:
|
tracker:
|
||||||
# image: gitea.futureporn.net/futureporn/opentracker:latest
|
image: gitea.futureporn.net/futureporn/tracker:latest
|
||||||
# host: 45.76.57.101
|
|
||||||
# port: "127.0.0.1:6969:6969"
|
|
||||||
# env:
|
|
||||||
# clear:
|
|
||||||
# WHITELIST_FEED_URL: https://bright.futureporn.net/torrents
|
|
||||||
# secret:
|
|
||||||
# - WHITELIST_USERNAME
|
|
||||||
# - WHITELIST_PASSWORD
|
|
||||||
# proxy:
|
|
||||||
# ssl: true
|
|
||||||
# forward_headers: true
|
|
||||||
# app_port: 6969
|
|
||||||
# host: tracker.futureporn.net
|
|
||||||
# healthcheck:
|
|
||||||
# path: /stats
|
|
||||||
# volumes:
|
|
||||||
# - opentracker-etc:/etc/opentracker
|
|
||||||
# - opentracker-var:/var/run/opentracker
|
|
||||||
|
|
||||||
aquatic:
|
|
||||||
image: gitea.futureporn.net/futureporn/aquatic:latest
|
|
||||||
host: 45.76.57.101
|
host: 45.76.57.101
|
||||||
port: "127.0.0.1:3000:3000"
|
port: "0.0.0.0:5063:5063"
|
||||||
env:
|
env:
|
||||||
clear:
|
clear:
|
||||||
WHITELIST_FEED_URL: https://bright.futureporn.net/torrents
|
HELPER_ACCESSLIST_PATH: "/var/lib/aquatic/accesslist"
|
||||||
secret:
|
secret:
|
||||||
- WHITELIST_USERNAME
|
- HELPER_USERNAME
|
||||||
- WHITELIST_PASSWORD
|
- HELPER_PASSWORD
|
||||||
|
|
||||||
proxy:
|
proxy:
|
||||||
ssl: true
|
ssl: true
|
||||||
forward_headers: true
|
forward_headers: true
|
||||||
app_port: 3000
|
app_port: 5063 # note: tracker also uses port 6969/udp and 9000/tcp, but the api at 5063/tcp is what we specify here. # @todo @blocking https://github.com/basecamp/kamal-proxy/issues/48
|
||||||
host: tracker.futureporn.net
|
host: tracker.futureporn.net
|
||||||
## we can't do the healthcheck on the prometheus port because kamal only allows one port per container
|
healthcheck:
|
||||||
## @blocking https://github.com/basecamp/kamal-proxy/issues/48
|
path: /health
|
||||||
# healthcheck:
|
|
||||||
# path: /stats
|
|
||||||
volumes:
|
|
||||||
- opentracker-etc:/etc/opentracker
|
|
||||||
- opentracker-var:/var/run/opentracker
|
|
||||||
|
|
||||||
qbittorrent:
|
qbittorrent:
|
||||||
image: lscr.io/linuxserver/qbittorrent:latest
|
image: lscr.io/linuxserver/qbittorrent:latest
|
||||||
|
@ -9,38 +9,6 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- aquatic
|
- aquatic
|
||||||
|
|
||||||
# opentracker:
|
|
||||||
# build:
|
|
||||||
# context: ./apps/opentracker
|
|
||||||
# container_name: opentracker
|
|
||||||
# environment:
|
|
||||||
# - WHITELIST_FEED_URL=http://bright:4000/torrents
|
|
||||||
# env_file:
|
|
||||||
# - .kamal/secrets.development
|
|
||||||
# ports:
|
|
||||||
# - "6969:6969/tcp"
|
|
||||||
# - "6969:6969/udp"
|
|
||||||
# volumes:
|
|
||||||
# - opentracker-etc:/etc/opentracker
|
|
||||||
|
|
||||||
# qbittorrent:
|
|
||||||
# build:
|
|
||||||
# context: .
|
|
||||||
# dockerfile: dockerfiles/qbittorrent.dockerfile
|
|
||||||
# environment:
|
|
||||||
# - PUID=1000
|
|
||||||
# - PGID=1000
|
|
||||||
# - UMASK=002
|
|
||||||
# - TZ=Etc/UTC
|
|
||||||
# - WEBUI_PORT=8181
|
|
||||||
# - WEBUI_PASSWORD=passwordpassword
|
|
||||||
# volumes:
|
|
||||||
# - cache:/root/.cache/futureporn
|
|
||||||
# container_name: qbittorrent
|
|
||||||
# ports:
|
|
||||||
# - "8181:8181/tcp"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# bright:
|
# bright:
|
||||||
# container_name: bright
|
# container_name: bright
|
||||||
|
@ -1,158 +0,0 @@
|
|||||||
import {
|
|
||||||
describe
|
|
||||||
, expect
|
|
||||||
, it
|
|
||||||
, beforeEach
|
|
||||||
} from 'bun:test'
|
|
||||||
import {
|
|
||||||
Elysia
|
|
||||||
} from 'elysia'
|
|
||||||
import {
|
|
||||||
treaty
|
|
||||||
} from '@elysiajs/eden'
|
|
||||||
import app from '../app.ts'
|
|
||||||
import Docker from 'dockerode'
|
|
||||||
|
|
||||||
|
|
||||||
if (!process.env.WL_FILE_PATH) throw new Error("WL_FILE_PATH is missing in env");
|
|
||||||
if (!process.env.WL_USERNAME) throw new Error("WL_USERNAME is missing in env.");
|
|
||||||
if (!process.env.WL_PASSWORD) throw new Error("WL_PASSWORD is missing in env.");
|
|
||||||
|
|
||||||
const whitelistFilePath = process.env.WL_FILE_PATH!
|
|
||||||
const fixture = "3aa5ad5e62eaffd148cff3dbe93ff2e1e9cbcf01"
|
|
||||||
|
|
||||||
|
|
||||||
const username = process.env.WL_USERNAME!
|
|
||||||
const password = process.env.WL_PASSWORD!
|
|
||||||
const opts = {
|
|
||||||
headers: {
|
|
||||||
authorization: "Basic " + btoa(username + ':' + password)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const api = treaty(app)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
describe
|
|
||||||
('tracker-helper', () => {
|
|
||||||
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
let whitelistFilePath = process.env.WL_FILE_PATH!
|
|
||||||
console.log(`Asserting existance of whitelist at ${whitelistFilePath}`)
|
|
||||||
// create whitelist file if it doesn't exist
|
|
||||||
const assertWhitelistExists = async function assertWhitelistExists(whitelistFilePath: string) {
|
|
||||||
const wlFile = Bun.file(whitelistFilePath);
|
|
||||||
const exists = await wlFile.exists()
|
|
||||||
if (!exists) {
|
|
||||||
console.log(`creating whitelist file at ${whitelistFilePath}`)
|
|
||||||
await wlFile.write("")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const clearWhitelist = async function clearWhitelist(whitelistFilePath: string) {
|
|
||||||
const wlFile = Bun.file(whitelistFilePath);
|
|
||||||
await wlFile.write("")
|
|
||||||
}
|
|
||||||
assertWhitelistExists(whitelistFilePath)
|
|
||||||
clearWhitelist(whitelistFilePath)
|
|
||||||
});
|
|
||||||
|
|
||||||
it('return a health response', async () => {
|
|
||||||
const { data, status } = await api.health.get()
|
|
||||||
expect(status).toBe(200)
|
|
||||||
expect(data).toBe("OK")
|
|
||||||
})
|
|
||||||
|
|
||||||
it('return a version', async () => {
|
|
||||||
const { data, status } = await api.version.get(opts)
|
|
||||||
expect(status).toBe(200)
|
|
||||||
expect(data).toContain("version")
|
|
||||||
})
|
|
||||||
|
|
||||||
it('return a whitelist', async () => {
|
|
||||||
const seedWhitelist = async function clearWhitelist(p: string, f: string) {
|
|
||||||
const wlFile = Bun.file(p);
|
|
||||||
await wlFile.write(f)
|
|
||||||
}
|
|
||||||
await seedWhitelist(whitelistFilePath, fixture)
|
|
||||||
const { data, status } = await api.whitelist.get(opts)
|
|
||||||
expect(status).toBe(200)
|
|
||||||
expect(data).toContain("3aa5ad5e62eaffd148cff3dbe93ff2e1e9cbcf01")
|
|
||||||
})
|
|
||||||
|
|
||||||
it('expects the whitelist to already exist', async () => {
|
|
||||||
const whitelist = Bun.file(whitelistFilePath)
|
|
||||||
const whitelistExists = await whitelist.exists()
|
|
||||||
expect(whitelistExists).toBe(true)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('appends a new info_hash to the whitelist file', async () => {
|
|
||||||
|
|
||||||
|
|
||||||
// make an api call which is supposed to add an entry to the whitelist
|
|
||||||
const { data, status } = await api.whitelist.post(fixture, opts)
|
|
||||||
|
|
||||||
// assert that the entry has been added to the whitelist
|
|
||||||
|
|
||||||
|
|
||||||
const w = Bun.file(whitelistFilePath)
|
|
||||||
const whitelistAfter = await w.text()
|
|
||||||
console.log('whitelistAfter as follows')
|
|
||||||
console.log(whitelistAfter)
|
|
||||||
|
|
||||||
expect(status).toBe(201)
|
|
||||||
expect(data).toMatch(fixture)
|
|
||||||
expect(whitelistAfter).toMatch(fixture)
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
// it('sends a SIGHUP to opentracker', async () => {
|
|
||||||
|
|
||||||
// const { data, status } = await api.whitelist.post(fixture, opts)
|
|
||||||
// const containerId = "act-ci-Tests-Checks-6e6f12196682961041a41a25b9d0dcf00e4d0f8e58f-7cb37eebfe9e1670328d58ad1f7c7bdf0fa078298ca6dd299e67d0141a4b9579"
|
|
||||||
// // await docker.getContainer(containerId).kill({ signal: 'SIGHUP' })
|
|
||||||
// let container = await docker.getContainer(containerId)
|
|
||||||
// container.inspect
|
|
||||||
|
|
||||||
// })
|
|
||||||
|
|
||||||
|
|
||||||
// // This is skipped because I couldn't figure out opentracker's whitelist add/delete via FIFO functionality.
|
|
||||||
// // I got as far as writing to the FIFO, and seeing opentracker acknowledge the line in it's logs.
|
|
||||||
// // Despite this, requests from qbittorrent to opentracker responded with,
|
|
||||||
// // "Requested download is not authorized for use with this tracker"
|
|
||||||
// // About a week on this problem, and I give up! Using the whitelist reloading strat instead.
|
|
||||||
// it.skip('writes a new info_hash to a fifo', async () => {
|
|
||||||
// const fifoFilePath = process.env.WL_FIFO_PATH!
|
|
||||||
// const fifo = Bun.file(fifoFilePath)
|
|
||||||
// const fifoExists = await fifo.exists();
|
|
||||||
|
|
||||||
|
|
||||||
// // create fifo if it doesn't exist
|
|
||||||
// if (!fifoExists) {
|
|
||||||
// await Bun.spawn(["mkfifo", fifoFilePath]).exited;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Start a process to read from the FIFO
|
|
||||||
// const reader = Bun.spawn(["cat", fifoFilePath], { stdout: "pipe" });
|
|
||||||
|
|
||||||
// const { data, status } = await api.whitelist.post("3aa5ad5e62eaffd148cff3dbe93ff2e1e9cbcf01", opts)
|
|
||||||
|
|
||||||
// const text = await new Response(reader.stdout).text();
|
|
||||||
|
|
||||||
// expect(text).toBe("3aa5ad5e62eaffd148cff3dbe93ff2e1e9cbcf01\n")
|
|
||||||
// expect(status).toBe(200)
|
|
||||||
// expect(data).toBe("3aa5ad5e62eaffd148cff3dbe93ff2e1e9cbcf01")
|
|
||||||
// })
|
|
||||||
|
|
||||||
it('returns 401 when username/password is missing from GET /whitelist ', async () => {
|
|
||||||
const { status } = await api.whitelist.get()
|
|
||||||
expect(status).toBe(401)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('returns 401 when username/password is missing from POST /whitelist ', async () => {
|
|
||||||
const { status } = await api.whitelist.post()
|
|
||||||
expect(status).toBe(401)
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
4
services/tracker-helper/test/fixtures/taco
vendored
Normal file
4
services/tracker-helper/test/fixtures/taco
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
b22ea43e4c0a7f73fc706b5faf1c35bb078d3722
|
||||||
|
3aa5ad5e62eaffd148cff3dbe93ff2e1e9cbcf01
|
||||||
|
3aa5ad5e62eaffd148cff3dbe93ff2e1e9cbcf01
|
||||||
|
3aa5ad5e62eaffd148cff3dbe93ff2e1e9cbcf01
|
@ -28,8 +28,8 @@ COPY . .
|
|||||||
|
|
||||||
# [optional] tests & build
|
# [optional] tests & build
|
||||||
ENV NODE_ENV=test WL_FILE_PATH=/tmp/whitelist
|
ENV NODE_ENV=test WL_FILE_PATH=/tmp/whitelist
|
||||||
RUN --mount=type=secret,id=WL_USERNAME,env=WL_USERNAME,required=true \
|
RUN --mount=type=secret,id=TRACKER_HELPER_USERNAME,env=TRACKER_HELPER_USERNAME,required=true \
|
||||||
--mount=type=secret,id=WL_PASSWORD,env=WL_PASSWORD,required=true \
|
--mount=type=secret,id=TRACKER_HELPER_PASSWORD,env=TRACKER_HELPER_PASSWORD,required=true \
|
||||||
bun test
|
bun test
|
||||||
|
|
||||||
# copy production dependencies and source code into final image
|
# copy production dependencies and source code into final image
|
@ -4,12 +4,12 @@ import { basicAuth } from '@eelkevdbos/elysia-basic-auth'
|
|||||||
import net from 'net'
|
import net from 'net'
|
||||||
import { appendFile } from "node:fs/promises";
|
import { appendFile } from "node:fs/promises";
|
||||||
|
|
||||||
if (!process.env.WL_USERNAME) throw new Error('WL_USERNAME missing in env');
|
if (!process.env.TRACKER_HELPER_USERNAME) throw new Error('TRACKER_HELPER_USERNAME missing in env');
|
||||||
if (!process.env.WL_PASSWORD) throw new Error('WL_PASSWORD missing in env');
|
if (!process.env.TRACKER_HELPER_PASSWORD) throw new Error('TRACKER_HELPER_PASSWORD missing in env');
|
||||||
|
|
||||||
const whitelistFilePath = process.env.WL_FILE_PATH || "/etc/opentracker/whitelist"
|
const accesslistFilePath = process.env.TRACKER_HELPER_ACCESSLIST_PATH || "/var/lib/aquatic/accesslist"
|
||||||
const username = process.env.WL_USERNAME!
|
const username = process.env.TRACKER_HELPER_USERNAME!
|
||||||
const password = process.env.WL_PASSWORD!
|
const password = process.env.TRACKER_HELPER_PASSWORD!
|
||||||
|
|
||||||
interface DockerContainer {
|
interface DockerContainer {
|
||||||
Id: string;
|
Id: string;
|
||||||
@ -18,7 +18,7 @@ interface DockerContainer {
|
|||||||
|
|
||||||
const authOpts = {
|
const authOpts = {
|
||||||
scope: [
|
scope: [
|
||||||
"/whitelist",
|
"/accesslist",
|
||||||
"/version"
|
"/version"
|
||||||
],
|
],
|
||||||
credentials: [
|
credentials: [
|
||||||
@ -32,8 +32,8 @@ const authOpts = {
|
|||||||
const startupChecks = async function startupChecks() {
|
const startupChecks = async function startupChecks() {
|
||||||
|
|
||||||
|
|
||||||
if (!process.env.WL_FILE_PATH) {
|
if (!process.env.TRACKER_HELPER_ACCESSLIST_PATH) {
|
||||||
console.warn(`WL_FILE_PATH is missing in env. Using default ${whitelistFilePath}`)
|
console.warn(`TRACKER_HELPER_ACCESSLIST_PATH is missing in env. Using default ${accesslistFilePath}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -41,9 +41,9 @@ const startupChecks = async function startupChecks() {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
const getWhitelist = async function getWhitelist(ctx: Context) {
|
const getAccesslist = async function getAccesslist(ctx: Context) {
|
||||||
const wl = Bun.file(whitelistFilePath); // relative to cwd
|
const wl = Bun.file(accesslistFilePath); // relative to cwd
|
||||||
console.debug(`read from whitelist file at ${whitelistFilePath}. size=${wl.size}, type=${wl.type}`)
|
console.debug(`read from accesslist file at ${accesslistFilePath}. size=${wl.size}, type=${wl.type}`)
|
||||||
return wl.text()
|
return wl.text()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,11 +127,11 @@ const maybeKillContainer = async function maybeKillContainer(signal: string = "S
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const postWhitelist = async function postWhitelist(ctx: Context) {
|
const postAccesslist = async function postAccesslist(ctx: Context) {
|
||||||
let body = ctx.body
|
let body = ctx.body
|
||||||
|
|
||||||
console.debug('appending to whitelist at ' + whitelistFilePath)
|
console.debug('appending to accesslist at ' + accesslistFilePath)
|
||||||
await appendFile(whitelistFilePath, body + "\n");
|
await appendFile(accesslistFilePath, body + "\n");
|
||||||
|
|
||||||
await maybeKillContainer("SIGUSR1")
|
await maybeKillContainer("SIGUSR1")
|
||||||
|
|
||||||
@ -148,8 +148,8 @@ const app = new Elysia()
|
|||||||
.use(basicAuth(authOpts))
|
.use(basicAuth(authOpts))
|
||||||
.get('/health', () => 'OK')
|
.get('/health', () => 'OK')
|
||||||
.get('/version', () => `version ${version}`)
|
.get('/version', () => `version ${version}`)
|
||||||
.get('/whitelist', getWhitelist)
|
.get('/accesslist', getAccesslist)
|
||||||
.post('/whitelist', postWhitelist, {
|
.post('/accesslist', postAccesslist, {
|
||||||
body: t.String()
|
body: t.String()
|
||||||
})
|
})
|
||||||
|
|
156
services/tracker/test/app.test.ts
Normal file
156
services/tracker/test/app.test.ts
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
import {
|
||||||
|
describe
|
||||||
|
, expect
|
||||||
|
, it
|
||||||
|
, beforeEach
|
||||||
|
} from 'bun:test'
|
||||||
|
import {
|
||||||
|
Elysia
|
||||||
|
} from 'elysia'
|
||||||
|
import {
|
||||||
|
treaty
|
||||||
|
} from '@elysiajs/eden'
|
||||||
|
import app from '../app.ts'
|
||||||
|
import Docker from 'dockerode'
|
||||||
|
import { mkdir } from "node:fs/promises";
|
||||||
|
import path from 'node:path'
|
||||||
|
|
||||||
|
|
||||||
|
if (!process.env.TRACKER_HELPER_USERNAME) throw new Error("TRACKER_HELPER_USERNAME is missing in env.");
|
||||||
|
if (!process.env.TRACKER_HELPER_PASSWORD) throw new Error("TRACKER_HELPER_PASSWORD is missing in env.");
|
||||||
|
|
||||||
|
const accesslistFilePath = process.env.TRACKER_HELPER_ACCESSLIST_PATH || "/var/lib/aquatic/accesslist"
|
||||||
|
const fixture = "3aa5ad5e62eaffd148cff3dbe93ff2e1e9cbcf01" // ubuntustudio-22.04.5-dvd-amd64.iso
|
||||||
|
const fixture2 = "b22ea43e4c0a7f73fc706b5faf1c35bb078d3722" // Solus-GNOME-Release-2025-01-26.iso
|
||||||
|
|
||||||
|
const username = process.env.TRACKER_HELPER_USERNAME!
|
||||||
|
const password = process.env.TRACKER_HELPER_PASSWORD!
|
||||||
|
const opts = {
|
||||||
|
headers: {
|
||||||
|
authorization: "Basic " + btoa(username + ':' + password)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const api = treaty(app)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
describe
|
||||||
|
('tracker-helper', () => {
|
||||||
|
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
console.log(`Asserting existence of accesslist at ${accesslistFilePath}`);
|
||||||
|
|
||||||
|
const assertAccesslistExists = async function (accesslistFilePath: string) {
|
||||||
|
const wlFile = Bun.file(accesslistFilePath);
|
||||||
|
const exists = await wlFile.exists();
|
||||||
|
|
||||||
|
if (!exists) {
|
||||||
|
console.log(`Creating accesslist file at ${accesslistFilePath}`);
|
||||||
|
|
||||||
|
// Ensure the parent directory exists
|
||||||
|
await mkdir(path.dirname(accesslistFilePath), { recursive: true });
|
||||||
|
|
||||||
|
await wlFile.write(`${fixture2}\n${fixture}\n`);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
await assertAccesslistExists(accesslistFilePath);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('return a health response', async () => {
|
||||||
|
const { data, status } = await api.health.get()
|
||||||
|
expect(status).toBe(200)
|
||||||
|
expect(data).toBe("OK")
|
||||||
|
})
|
||||||
|
|
||||||
|
it('return a version', async () => {
|
||||||
|
const { data, status } = await api.version.get(opts)
|
||||||
|
expect(status).toBe(200)
|
||||||
|
expect(data).toContain("version")
|
||||||
|
})
|
||||||
|
|
||||||
|
it('return a accesslist', async () => {
|
||||||
|
const { data, status } = await api.accesslist.get(opts)
|
||||||
|
expect(status).toBe(200)
|
||||||
|
expect(data).toContain(fixture)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('expects the accesslist to already exist', async () => {
|
||||||
|
const accesslist = Bun.file(accesslistFilePath)
|
||||||
|
const accesslistExists = await accesslist.exists()
|
||||||
|
expect(accesslistExists).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('appends a new info_hash to the accesslist file', async () => {
|
||||||
|
|
||||||
|
|
||||||
|
// make an api call which is supposed to add an entry to the accesslist
|
||||||
|
const { data, status } = await api.accesslist.post(fixture, opts)
|
||||||
|
|
||||||
|
// assert that the entry has been added to the accesslist
|
||||||
|
|
||||||
|
|
||||||
|
const w = Bun.file(accesslistFilePath)
|
||||||
|
const accesslistAfter = await w.text()
|
||||||
|
console.log('accesslistAfter as follows')
|
||||||
|
console.log(accesslistAfter)
|
||||||
|
|
||||||
|
expect(status).toBe(201)
|
||||||
|
expect(data).toMatch(fixture)
|
||||||
|
expect(accesslistAfter).toMatch(fixture)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
// it('sends a SIGHUP to opentracker', async () => {
|
||||||
|
|
||||||
|
// const { data, status } = await api.accesslist.post(fixture, opts)
|
||||||
|
// const containerId = "act-ci-Tests-Checks-6e6f12196682961041a41a25b9d0dcf00e4d0f8e58f-7cb37eebfe9e1670328d58ad1f7c7bdf0fa078298ca6dd299e67d0141a4b9579"
|
||||||
|
// // await docker.getContainer(containerId).kill({ signal: 'SIGHUP' })
|
||||||
|
// let container = await docker.getContainer(containerId)
|
||||||
|
// container.inspect
|
||||||
|
|
||||||
|
// })
|
||||||
|
|
||||||
|
|
||||||
|
// // This is skipped because I couldn't figure out opentracker's accesslist add/delete via FIFO functionality.
|
||||||
|
// // I got as far as writing to the FIFO, and seeing opentracker acknowledge the line in it's logs.
|
||||||
|
// // Despite this, requests from qbittorrent to opentracker responded with,
|
||||||
|
// // "Requested download is not authorized for use with this tracker"
|
||||||
|
// // About a week on this problem, and I give up! Using the accesslist reloading strat instead.
|
||||||
|
// it.skip('writes a new info_hash to a fifo', async () => {
|
||||||
|
// const fifoFilePath = process.env.TRACKER_HELPER_FIFO_PATH!
|
||||||
|
// const fifo = Bun.file(fifoFilePath)
|
||||||
|
// const fifoExists = await fifo.exists();
|
||||||
|
|
||||||
|
|
||||||
|
// // create fifo if it doesn't exist
|
||||||
|
// if (!fifoExists) {
|
||||||
|
// await Bun.spawn(["mkfifo", fifoFilePath]).exited;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Start a process to read from the FIFO
|
||||||
|
// const reader = Bun.spawn(["cat", fifoFilePath], { stdout: "pipe" });
|
||||||
|
|
||||||
|
// const { data, status } = await api.accesslist.post("3aa5ad5e62eaffd148cff3dbe93ff2e1e9cbcf01", opts)
|
||||||
|
|
||||||
|
// const text = await new Response(reader.stdout).text();
|
||||||
|
|
||||||
|
// expect(text).toBe("3aa5ad5e62eaffd148cff3dbe93ff2e1e9cbcf01\n")
|
||||||
|
// expect(status).toBe(200)
|
||||||
|
// expect(data).toBe("3aa5ad5e62eaffd148cff3dbe93ff2e1e9cbcf01")
|
||||||
|
// })
|
||||||
|
|
||||||
|
it('returns 401 when username/password is missing from GET /accesslist ', async () => {
|
||||||
|
const { status } = await api.accesslist.get()
|
||||||
|
expect(status).toBe(401)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('returns 401 when username/password is missing from POST /accesslist ', async () => {
|
||||||
|
const { status } = await api.accesslist.post()
|
||||||
|
expect(status).toBe(401)
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
Loading…
x
Reference in New Issue
Block a user