From a5e9c3089b6ee9d7c75f34a7b7cf7e7c24a0fde8 Mon Sep 17 00:00:00 2001 From: nin0dev Date: Sat, 22 Jun 2024 14:52:41 -0400 Subject: [PATCH 1/7] Added videobundler --- videobundler/.env.example | 4 +++ videobundler/README.md | 25 +++++++++++++++ videobundler/main.py | 64 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 videobundler/.env.example create mode 100644 videobundler/README.md create mode 100644 videobundler/main.py diff --git a/videobundler/.env.example b/videobundler/.env.example new file mode 100644 index 0000000..e226afe --- /dev/null +++ b/videobundler/.env.example @@ -0,0 +1,4 @@ +TIME_BEFORE_DELETE=30 +PORT=45872 +# DO NOT PUT A / AT THE END OF THE URL +PROXY_URL=https://eu-proxy.poketube.fun \ No newline at end of file diff --git a/videobundler/README.md b/videobundler/README.md new file mode 100644 index 0000000..c1ea44a --- /dev/null +++ b/videobundler/README.md @@ -0,0 +1,25 @@ +# poke-videobundler + +Takes 2 input streams, downloads them, and spits out a combined file. + +## Installation + +1. Make sure `ffmpeg`, `wget`, and Python 3 are all installed. +2. Download the program files to your computer - `main.py` and `.env.example`. +3. Run `python3 -m pip install flask python-dotenv waitress`. + +## Configuration + +1. Run `mv .env.example .env`, **even if you don't want to configure anything**. +2. Edit and fill in the values if needed. + +## Usage + +1. `python3 main.py`. +2. If everything went well, you shouldn't see any output at launch. +3. You will now be able to call the server at the configured port. + +## Endpoints + +- `/`: Will return `{success:true}` if alive. +- `/get_merged_video?id=VIDEO_ID&audio_itag=AUDIO_ITAG&video_itag=VIDEO_ITAG`: Returns a merged video. ID is the youtube video ID, and itags are self explanatory. diff --git a/videobundler/main.py b/videobundler/main.py new file mode 100644 index 0000000..a8d662f --- /dev/null +++ b/videobundler/main.py @@ -0,0 +1,64 @@ +from datetime import datetime +from dotenv import load_dotenv +from flask import Flask, request, Response, send_file +from threading import Thread +from time import sleep + +import io +import json +import os +import random +import string +import subprocess +import uuid + +load_dotenv() + +app = Flask(__name__) + +def autodelete(job_id: str): + sleep(os.getenv("TIME_BEFORE_DELETE")) + os.remove(f"{job_id}.mp4") + os.remove(f"{job_id}.m4a") + os.remove(f"output.{job_id}.mp4") + +def get_random_string(length): + # choose from all lowercase letter + letters = string.ascii_lowercase + result_str = "".join(random.choice(letters) for i in range(length)) + return result_str + +@app.route("/") +def ping(): + return json.loads(""" + { + "success": true + } + """) + +@app.route("/get_merged_video") +def get_merged_video(): + pwd = os.getcwd() + video_id = request.args.get("id") + job_id = get_random_string(10) + audio_itag = request.args.get("audio_itag") + video_itag = request.args.get("video_itag") + # Download both audio and video + subprocess.run(["wget", f"-O{job_id}.m4a", f"{os.getenv("PROXY_URL")}/latest_version?id={video_id}&itag={audio_itag}&local=true"], check=True) + subprocess.run(["wget", f"-O{job_id}.mp4", f"{os.getenv("PROXY_URL")}/latest_version?id={video_id}&itag={video_itag}&local=true"], check=True) + # Merge both files + subprocess.run(f"ffmpeg -i {pwd}/{job_id}.m4a -i {pwd}/{job_id}.mp4 -c copy {pwd}/output.{job_id}.mp4", shell=True, check=True) + thread = Thread(target=autodelete, args = (job_id, )) + thread.start() + with open(f"output.{job_id}.mp4", "rb") as bytes: + return send_file( + io.BytesIO(bytes.read()), + mimetype="video/mp4", + download_name=f"output.{job_id}.mp4", + as_attachment=True + ) + + +if __name__ == "__main__": + from waitress import serve + serve(app, host="0.0.0.0", port=os.getenv("PORT")) \ No newline at end of file From 7fbd295c876b1f7de29ae354e8b31e7dcc1e7844 Mon Sep 17 00:00:00 2001 From: nin0dev Date: Sat, 22 Jun 2024 15:26:47 -0400 Subject: [PATCH 2/7] Fixed f string error --- videobundler/main.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/videobundler/main.py b/videobundler/main.py index a8d662f..96a2232 100644 --- a/videobundler/main.py +++ b/videobundler/main.py @@ -44,8 +44,8 @@ def get_merged_video(): audio_itag = request.args.get("audio_itag") video_itag = request.args.get("video_itag") # Download both audio and video - subprocess.run(["wget", f"-O{job_id}.m4a", f"{os.getenv("PROXY_URL")}/latest_version?id={video_id}&itag={audio_itag}&local=true"], check=True) - subprocess.run(["wget", f"-O{job_id}.mp4", f"{os.getenv("PROXY_URL")}/latest_version?id={video_id}&itag={video_itag}&local=true"], check=True) + subprocess.run(["wget", f"-O{job_id}.m4a", f"{os.getenv('PROXY_URL')}/latest_version?id={video_id}&itag={audio_itag}&local=true"], check=True) + subprocess.run(["wget", f"-O{job_id}.mp4", f"{os.getenv('PROXY_URL')}/latest_version?id={video_id}&itag={video_itag}&local=true"], check=True) # Merge both files subprocess.run(f"ffmpeg -i {pwd}/{job_id}.m4a -i {pwd}/{job_id}.mp4 -c copy {pwd}/output.{job_id}.mp4", shell=True, check=True) thread = Thread(target=autodelete, args = (job_id, )) @@ -61,4 +61,4 @@ def get_merged_video(): if __name__ == "__main__": from waitress import serve - serve(app, host="0.0.0.0", port=os.getenv("PORT")) \ No newline at end of file + serve(app, host="0.0.0.0", port=os.getenv("PORT")) From b7e6d55fccccbf22d524b59a8b637df5ccfb68e1 Mon Sep 17 00:00:00 2001 From: ashley Date: Sat, 22 Jun 2024 21:12:05 +0000 Subject: [PATCH 3/7] o7 --- src/libpoketube/init/pages-api.js | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/libpoketube/init/pages-api.js b/src/libpoketube/init/pages-api.js index 735de0a..b7b8ad0 100644 --- a/src/libpoketube/init/pages-api.js +++ b/src/libpoketube/init/pages-api.js @@ -181,17 +181,6 @@ app.use("/sb/i/:v/:imagePath/:img", async function (req, res) { } catch {} }); - app.get("/feeds/videos.xml", async (req, res) => { - const id = req.query.channel_id; - - let url = `https://youtube.com/feeds/videos.xml?channel_id=${id}`; - - let f = await modules.fetch(url, { - method: req.method, - }); - - f.body.pipe(res); - }); app.get("/api/redirect", async (req, res) => { const red_url = atob(req.query.u); From bbff542938d171e0f69eb8c7d6f93caa3d334bd6 Mon Sep 17 00:00:00 2001 From: nin0dev Date: Sat, 22 Jun 2024 18:02:30 -0400 Subject: [PATCH 4/7] Added concurrency --- videobundler/.env.example | 1 + videobundler/README.md | 4 +- videobundler/main.py | 130 +++++++++++++++++++++++++++----------- 3 files changed, 98 insertions(+), 37 deletions(-) diff --git a/videobundler/.env.example b/videobundler/.env.example index e226afe..9a37701 100644 --- a/videobundler/.env.example +++ b/videobundler/.env.example @@ -1,4 +1,5 @@ TIME_BEFORE_DELETE=30 +INACTIVE_TIME_BEFORE_DELETE=3600 PORT=45872 # DO NOT PUT A / AT THE END OF THE URL PROXY_URL=https://eu-proxy.poketube.fun \ No newline at end of file diff --git a/videobundler/README.md b/videobundler/README.md index c1ea44a..3b31744 100644 --- a/videobundler/README.md +++ b/videobundler/README.md @@ -22,4 +22,6 @@ Takes 2 input streams, downloads them, and spits out a combined file. ## Endpoints - `/`: Will return `{success:true}` if alive. -- `/get_merged_video?id=VIDEO_ID&audio_itag=AUDIO_ITAG&video_itag=VIDEO_ITAG`: Returns a merged video. ID is the youtube video ID, and itags are self explanatory. +- `/merge?id=VIDEO_ID&audio_itag=AUDIO_ITAG&video_itag=VIDEO_ITAG`: Starts the merging process. ID is the youtube video ID, and itags are self explanatory. As a response, you will get a job ID that you will be able to use in future requests to query the video or its status. When this process is finished, the inactive autodelete counter will start, which will allow you to fetch the video until the countdown is over. +- `/get?id=JOB_ID`: Queries a merged video and sends it to you. If the video is successfully and fully merged you will get a 200 response with a video. However, if it isn't finished, you will get a `success: false` 404 response. If the video indeed exists and is sent to you, the get autodelete counter will start, which will allow you to fetch it until this countdown is over. +- `/check?id=JOB_ID`: Queries a merged video's status. If the video is successfully and fully merged you will get a 200 response with `success:true`. However, if it isn't finished, you will get a `success: false` 404 response. Useful if you want to poll the status without triggering the get autodelete counter. \ No newline at end of file diff --git a/videobundler/main.py b/videobundler/main.py index 96a2232..44c2105 100644 --- a/videobundler/main.py +++ b/videobundler/main.py @@ -17,48 +17,106 @@ load_dotenv() app = Flask(__name__) def autodelete(job_id: str): - sleep(os.getenv("TIME_BEFORE_DELETE")) - os.remove(f"{job_id}.mp4") - os.remove(f"{job_id}.m4a") - os.remove(f"output.{job_id}.mp4") + f = open(f"pendingDelete.{job_id}", "a") + f.write(":3") + f.close() + sleep(int(os.getenv("TIME_BEFORE_DELETE"))) + try: + os.remove(f"done.{job_id}") + os.remove(f"{job_id}.mp4") + os.remove(f"{job_id}.m4a") + os.remove(f"output.{job_id}.mp4") + os.remove(f"pendingDelete.{job_id}") + except Exception: + _ = 0 + +def inactive_autodelete(job_id: str): + pwd = os.getcwd() + sleep(int(os.getenv("INACTIVE_TIME_BEFORE_DELETE"))) + if not os.path.isfile(f"{pwd}/done.{job_id}"): + return + try: + os.remove(f"done.{job_id}") + os.remove(f"{job_id}.mp4") + os.remove(f"{job_id}.m4a") + os.remove(f"output.{job_id}.mp4") + os.remove(f"pendingDelete.{job_id}") + except Exception: + _ = 0 def get_random_string(length): - # choose from all lowercase letter - letters = string.ascii_lowercase - result_str = "".join(random.choice(letters) for i in range(length)) - return result_str + # choose from all lowercase letter + letters = string.ascii_lowercase + result_str = "".join(random.choice(letters) for i in range(length)) + return result_str + +def merge_video(job_id: str, video_id: str, audio_itag: str, video_itag: str): + pwd = os.getcwd() + # Download both audio and video + subprocess.run(["wget", f"-O{job_id}.m4a", f"{os.getenv("PROXY_URL")}/latest_version?id={video_id}&itag={audio_itag}&local=true"], check=True) + subprocess.run(["wget", f"-O{job_id}.mp4", f"{os.getenv("PROXY_URL")}/latest_version?id={video_id}&itag={video_itag}&local=true"], check=True) + # Merge both files + subprocess.run(f"ffmpeg -i {pwd}/{job_id}.m4a -i {pwd}/{job_id}.mp4 -c copy {pwd}/output.{job_id}.mp4", shell=True, check=True) + f = open(f"done.{job_id}", "a") + f.write(":3") + f.close() + thread = Thread(target=inactive_autodelete, args = (job_id, )) + thread.start() @app.route("/") def ping(): - return json.loads(""" - { - "success": true - } - """) + return json.loads(""" + { + "success": true + } + """) -@app.route("/get_merged_video") -def get_merged_video(): - pwd = os.getcwd() - video_id = request.args.get("id") - job_id = get_random_string(10) - audio_itag = request.args.get("audio_itag") - video_itag = request.args.get("video_itag") - # Download both audio and video - subprocess.run(["wget", f"-O{job_id}.m4a", f"{os.getenv('PROXY_URL')}/latest_version?id={video_id}&itag={audio_itag}&local=true"], check=True) - subprocess.run(["wget", f"-O{job_id}.mp4", f"{os.getenv('PROXY_URL')}/latest_version?id={video_id}&itag={video_itag}&local=true"], check=True) - # Merge both files - subprocess.run(f"ffmpeg -i {pwd}/{job_id}.m4a -i {pwd}/{job_id}.mp4 -c copy {pwd}/output.{job_id}.mp4", shell=True, check=True) - thread = Thread(target=autodelete, args = (job_id, )) - thread.start() - with open(f"output.{job_id}.mp4", "rb") as bytes: - return send_file( - io.BytesIO(bytes.read()), - mimetype="video/mp4", - download_name=f"output.{job_id}.mp4", - as_attachment=True - ) +@app.route("/merge") +def merge(): + job_id = get_random_string(10) + thread = Thread(target=merge_video, args = (job_id, request.args.get("id"), request.args.get("audio_itag"), request.args.get("video_itag"))) + thread.start() + return json.loads('{"success":true,"job_id":"' + job_id + '"}') + +@app.route("/get") +def get(): + pwd = os.getcwd() + job_id = request.args.get("job_id") + if os.path.isfile(f"{pwd}/done.{job_id}"): + if not os.path.isfile(f"{pwd}/pendingDelete.{job_id}"): + thread = Thread(target=autodelete, args = (job_id, )) + thread.start() + with open(f"output.{job_id}.mp4", "rb") as bytes: + return send_file( + io.BytesIO(bytes.read()), + mimetype="video/mp4", + download_name=f"output.{job_id}.mp4", + as_attachment=True + ) + return json.loads('{"success":false}'), 404 + +@app.route("/check") +def check(): + pwd = os.getcwd() + job_id = request.args.get("job_id") + if os.path.isfile(f"{pwd}/done.{job_id}"): + return json.loads('{"success":true}') + return json.loads('{"success":false}'), 404 if __name__ == "__main__": - from waitress import serve - serve(app, host="0.0.0.0", port=os.getenv("PORT")) + from waitress import serve + serve(app, host="0.0.0.0", port=os.getenv("PORT")) + +#with open(f"output.{job_id}.mp4", "rb") as bytes: + #return send_file( + # io.BytesIO(bytes.read()), + # mimetype="video/mp4", + # download_name=f"output.{job_id}.mp4", + # as_attachment=True + # ) +# +# +# +# +# From 0fdbeea5d5089ec4e284ebbdf7237a5edfec563e Mon Sep 17 00:00:00 2001 From: Korbs Date: Sun, 23 Jun 2024 04:17:34 -0400 Subject: [PATCH 5/7] Add suggestions to search bar (Landing) --- html/partials/header.ejs | 8 ++-- html/partials/search.ejs | 88 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 5 deletions(-) create mode 100644 html/partials/search.ejs diff --git a/html/partials/header.ejs b/html/partials/header.ejs index 3d18e4c..07e1c9e 100644 --- a/html/partials/header.ejs +++ b/html/partials/header.ejs @@ -31,10 +31,7 @@
-
- - -
+ <%- include('./search.ejs') %>
@@ -122,4 +119,5 @@ color: white; gap: 6px; } - \ No newline at end of file + + \ No newline at end of file diff --git a/html/partials/search.ejs b/html/partials/search.ejs new file mode 100644 index 0000000..7677967 --- /dev/null +++ b/html/partials/search.ejs @@ -0,0 +1,88 @@ +
+ + +
+
+ + + \ No newline at end of file From 70243b5b76d5d0281f5459b9cfddd636c8cd1ef0 Mon Sep 17 00:00:00 2001 From: nin0dev Date: Sun, 23 Jun 2024 12:21:01 -0400 Subject: [PATCH 6/7] Updated videobundler to add concurrency and caching --- videobundler/README.md | 5 +- videobundler/main.py | 159 ++++++++++++++--------------------------- 2 files changed, 56 insertions(+), 108 deletions(-) diff --git a/videobundler/README.md b/videobundler/README.md index 3b31744..54d24ca 100644 --- a/videobundler/README.md +++ b/videobundler/README.md @@ -22,6 +22,5 @@ Takes 2 input streams, downloads them, and spits out a combined file. ## Endpoints - `/`: Will return `{success:true}` if alive. -- `/merge?id=VIDEO_ID&audio_itag=AUDIO_ITAG&video_itag=VIDEO_ITAG`: Starts the merging process. ID is the youtube video ID, and itags are self explanatory. As a response, you will get a job ID that you will be able to use in future requests to query the video or its status. When this process is finished, the inactive autodelete counter will start, which will allow you to fetch the video until the countdown is over. -- `/get?id=JOB_ID`: Queries a merged video and sends it to you. If the video is successfully and fully merged you will get a 200 response with a video. However, if it isn't finished, you will get a `success: false` 404 response. If the video indeed exists and is sent to you, the get autodelete counter will start, which will allow you to fetch it until this countdown is over. -- `/check?id=JOB_ID`: Queries a merged video's status. If the video is successfully and fully merged you will get a 200 response with `success:true`. However, if it isn't finished, you will get a `success: false` 404 response. Useful if you want to poll the status without triggering the get autodelete counter. \ No newline at end of file +- `/[ANYTHING]?id=VIDEO_ID&audio_itag=AUDIO_ITAG&video_itag=VIDEO_ITAG`: Starts the merging process. ID is the youtube video ID, and itags are self explanatory. As a response, you will get a job ID that you will be able to use in future requests to query the video or its status. When this process is finished, the inactive autodelete counter will start, which will allow you to fetch the video until the countdown is over. +> Replace `[ANYTHING]` with absolutely anything, however it has to be unique to the request. Preferably use an UUID diff --git a/videobundler/main.py b/videobundler/main.py index 44c2105..236c1c1 100644 --- a/videobundler/main.py +++ b/videobundler/main.py @@ -1,48 +1,13 @@ -from datetime import datetime -from dotenv import load_dotenv -from flask import Flask, request, Response, send_file -from threading import Thread -from time import sleep - -import io -import json +import asyncio +import aiohttp +from aiohttp import web +import string import os import random -import string import subprocess -import uuid -load_dotenv() - -app = Flask(__name__) - -def autodelete(job_id: str): - f = open(f"pendingDelete.{job_id}", "a") - f.write(":3") - f.close() - sleep(int(os.getenv("TIME_BEFORE_DELETE"))) - try: - os.remove(f"done.{job_id}") - os.remove(f"{job_id}.mp4") - os.remove(f"{job_id}.m4a") - os.remove(f"output.{job_id}.mp4") - os.remove(f"pendingDelete.{job_id}") - except Exception: - _ = 0 - -def inactive_autodelete(job_id: str): - pwd = os.getcwd() - sleep(int(os.getenv("INACTIVE_TIME_BEFORE_DELETE"))) - if not os.path.isfile(f"{pwd}/done.{job_id}"): - return - try: - os.remove(f"done.{job_id}") - os.remove(f"{job_id}.mp4") - os.remove(f"{job_id}.m4a") - os.remove(f"output.{job_id}.mp4") - os.remove(f"pendingDelete.{job_id}") - except Exception: - _ = 0 +app = web.Application() +app.router._frozen = False def get_random_string(length): # choose from all lowercase letter @@ -50,73 +15,57 @@ def get_random_string(length): result_str = "".join(random.choice(letters) for i in range(length)) return result_str -def merge_video(job_id: str, video_id: str, audio_itag: str, video_itag: str): - pwd = os.getcwd() - # Download both audio and video - subprocess.run(["wget", f"-O{job_id}.m4a", f"{os.getenv("PROXY_URL")}/latest_version?id={video_id}&itag={audio_itag}&local=true"], check=True) - subprocess.run(["wget", f"-O{job_id}.mp4", f"{os.getenv("PROXY_URL")}/latest_version?id={video_id}&itag={video_itag}&local=true"], check=True) - # Merge both files - subprocess.run(f"ffmpeg -i {pwd}/{job_id}.m4a -i {pwd}/{job_id}.mp4 -c copy {pwd}/output.{job_id}.mp4", shell=True, check=True) +async def merge(request): + # register params + try: + job_id = request.rel_url.query["id"] + video_id: str = request.rel_url.query["id"] + audio_itag: str = request.rel_url.query["audio_itag"] + video_itag: str = request.rel_url.query["video_itag"] + except: + # no one gives a fuck + _ = 0 + # validate + if " " in video_id or len(video_id) > 11: + print(f"Video {video_id} flagged as invalid, dropping request") + return + if not audio_itag.isdigit(): + print(f"Audio itag {audio_itag} flagged as invalid, dropping request") + return + if not video_itag.isdigit(): + print(f"Video itag {video_itag} flagged as invalid, dropping request") + return + if os.path.isfile(f"done.{job_id}"): + return web.FileResponse( + path=f"output.{job_id}.mp4" + ) + proc_audio = await asyncio.create_subprocess_shell( + f"wget -O{job_id}.m4a \"https://eu-proxy.poketube.fun/latest_version?id={video_id}&itag={audio_itag}&local=true\"", + ) + proc_video = await asyncio.create_subprocess_shell( + f"wget -O{job_id}.mp4 \"https://eu-proxy.poketube.fun/latest_version?id={video_id}&itag={video_itag}&local=true\"" + ) + await asyncio.gather(proc_audio.wait(), proc_video.wait()) + proc_ffmpeg = await asyncio.create_subprocess_shell( + f"ffmpeg -i {job_id}.m4a -i {job_id}.mp4 -c copy output.{job_id}.mp4" + ) + await proc_ffmpeg.wait() f = open(f"done.{job_id}", "a") f.write(":3") f.close() - thread = Thread(target=inactive_autodelete, args = (job_id, )) - thread.start() + return web.FileResponse( + path=f"output.{job_id}.mp4" + ) -@app.route("/") -def ping(): - return json.loads(""" - { - "success": true - } - """) +async def ping(request): + return web.Response(body='{"success": true}', content_type="application/json") -@app.route("/merge") -def merge(): - job_id = get_random_string(10) - thread = Thread(target=merge_video, args = (job_id, request.args.get("id"), request.args.get("audio_itag"), request.args.get("video_itag"))) - thread.start() - return json.loads('{"success":true,"job_id":"' + job_id + '"}') +async def init_app(): + app.router.add_get("/{id:.+}", merge) + app.router.add_get("/", ping) + return app -@app.route("/get") -def get(): - pwd = os.getcwd() - job_id = request.args.get("job_id") - if os.path.isfile(f"{pwd}/done.{job_id}"): - if not os.path.isfile(f"{pwd}/pendingDelete.{job_id}"): - thread = Thread(target=autodelete, args = (job_id, )) - thread.start() - with open(f"output.{job_id}.mp4", "rb") as bytes: - return send_file( - io.BytesIO(bytes.read()), - mimetype="video/mp4", - download_name=f"output.{job_id}.mp4", - as_attachment=True - ) - return json.loads('{"success":false}'), 404 - -@app.route("/check") -def check(): - pwd = os.getcwd() - job_id = request.args.get("job_id") - if os.path.isfile(f"{pwd}/done.{job_id}"): - return json.loads('{"success":true}') - return json.loads('{"success":false}'), 404 - - -if __name__ == "__main__": - from waitress import serve - serve(app, host="0.0.0.0", port=os.getenv("PORT")) - -#with open(f"output.{job_id}.mp4", "rb") as bytes: - #return send_file( - # io.BytesIO(bytes.read()), - # mimetype="video/mp4", - # download_name=f"output.{job_id}.mp4", - # as_attachment=True - # ) -# -# -# -# -# +if __name__ == '__main__': + loop = asyncio.get_event_loop() + app = loop.run_until_complete(init_app()) + web.run_app(app, port=3030) \ No newline at end of file From 4d31a08fef38a7132cc875568547f8fd976cf512 Mon Sep 17 00:00:00 2001 From: Korbs Date: Mon, 24 Jun 2024 02:50:05 +0000 Subject: [PATCH 7/7] Rename to "Poke", use PokeTube org's package, and note about ARM64/v7 --- docker-compose.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 8bf2b04..0f5fd87 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,8 +1,8 @@ # To run, please do either docker compose up -d (for docker's own version) or docker-compose up -d (for your OSes package managers verison) services: - poketube: - image: codeberg.org/korbs/poke:amd64 - # image: codeberg.org/korbs/poke:arm64 # Use this if you're using a Raspberry Pi or an arm architecture + poke: + image: codeberg.org/poketube/poke:amd64 + # image: codeberg.org/poketube/poke:arm64 # Works with ARM64/v8, not ARM64/v7 restart: unless-stopped volumes: - ./config.json:/poketube/config.json