Compare commits
22 Commits
7c69d73083
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| de798246b9 | |||
| 1b9fb93cf6 | |||
| 667f2a88ba | |||
| ee4be382b9 | |||
| 12137b1fa8 | |||
| 18d640ab1f | |||
| fab6ba9216 | |||
| 36d3505746 | |||
| 5551ad78b9 | |||
| 204decf1dc | |||
| f3d454988a | |||
| e2ac4ec983 | |||
| e1fd6fbeb7 | |||
| 61b7d4c2ca | |||
| 4b36be3819 | |||
| f668f59f70 | |||
| 91a9c69cba | |||
| 2b00bec445 | |||
| 54c6740dfe | |||
| 5ef8692a3a | |||
| e5e1987bd1 | |||
| ff3b2765a7 |
33
.build.yaml
33
.build.yaml
@@ -1,33 +0,0 @@
|
||||
image: debian/bookworm
|
||||
|
||||
secrets:
|
||||
- a19cbc4c-b6a1-414e-bf1c-1e06abc684eb
|
||||
|
||||
tasks:
|
||||
- print-env: |
|
||||
echo "$JOB_ID"
|
||||
echo "$JOB_URL"
|
||||
echo "$BUILD_SUBMITTER"
|
||||
echo "$BUILD_REASON"
|
||||
echo "$GIT_REF"
|
||||
- setup-env: |
|
||||
sudo timedatectl set-timezone America/Denver
|
||||
echo "SLUG=ghcr.io/cwpearson/ytdlp-site" >> ~/.buildenv
|
||||
echo "DATE=$(date +"%Y%m%d_%H%M")" >> ~/.buildenv
|
||||
- prerequisites: |
|
||||
bash ytdlp-site/.ci/debian_setup_docker.sh
|
||||
- build: |
|
||||
cd ytdlp-site
|
||||
docker build . --file Dockerfile --build-arg GIT_SHA=$(git rev-parse HEAD) --tag "$SLUG:$DATE" --tag "$SLUG:latest"
|
||||
- deploy: |
|
||||
if [ "$GIT_REF" != "refs/heads/master" ]; then exit 0; fi
|
||||
set +x
|
||||
cat ~/.ghcr_token | docker login ghcr.io -u cwpearson --password-stdin
|
||||
set -x
|
||||
docker push "$SLUG:latest"
|
||||
docker push "$SLUG:$DATE"
|
||||
|
||||
triggers:
|
||||
- action: email
|
||||
condition: failure
|
||||
to: Carl Pearson <srht@carlpearson.net>
|
||||
@@ -1,3 +1,5 @@
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Add Docker's official GPG key:
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y ca-certificates curl
|
||||
|
||||
19
.ci/ubuntu_setup_docker.sh
Normal file
19
.ci/ubuntu_setup_docker.sh
Normal file
@@ -0,0 +1,19 @@
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Add Docker's official GPG key:
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y ca-certificates curl
|
||||
sudo install -m 0755 -d /etc/apt/keyrings
|
||||
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
|
||||
sudo chmod a+r /etc/apt/keyrings/docker.asc
|
||||
|
||||
# Add the repository to Apt sources:
|
||||
echo \
|
||||
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
|
||||
$(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
|
||||
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
sudo apt-get update
|
||||
|
||||
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||
|
||||
sudo usermod -aG docker $(whoami)
|
||||
56
.gitea/workflows/build-deploy.yml
Normal file
56
.gitea/workflows/build-deploy.yml
Normal file
@@ -0,0 +1,56 @@
|
||||
name: Build and Deploy ytdlp-site
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
# Runs every 2 days at 2:30 AM UTC
|
||||
- cron: '30 2 */2 * *'
|
||||
env:
|
||||
SLUG: git.carlpearson.net/cwpearson/ytdlp-site
|
||||
TZ: America/Denver
|
||||
|
||||
jobs:
|
||||
build-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Print environment info
|
||||
run: |
|
||||
echo "Job ID: ${{ github.run_id }}"
|
||||
echo "Job URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
||||
echo "Build Submitter: ${{ github.actor }}"
|
||||
echo "Build Reason: ${{ github.event_name }}"
|
||||
echo "Git Ref: ${{ github.ref }}"
|
||||
|
||||
- name: Setup environment
|
||||
run: |
|
||||
echo "DATE=$(date +"%Y%m%d_%H%M")" >> $GITHUB_ENV
|
||||
echo "GIT_SHA=$(git rev-parse HEAD)" >> $GITHUB_ENV
|
||||
|
||||
- name: Install docker
|
||||
run: |
|
||||
bash .ci/ubuntu_setup_docker.sh
|
||||
|
||||
- name: Build Docker image
|
||||
run: |
|
||||
docker build . \
|
||||
--file Dockerfile \
|
||||
--build-arg GIT_SHA=${{ env.GIT_SHA }} \
|
||||
--tag ${{ env.SLUG }}:${{ env.DATE }} \
|
||||
--tag ${{ env.SLUG }}:latest
|
||||
|
||||
- name: Deploy to Container Registry
|
||||
if: gitea.ref == 'refs/heads/master' && (gitea.event_name == 'push' || gitea.event_name == 'schedule')
|
||||
run: |
|
||||
echo "${{ secrets.GIT_PASSWORD }}" | docker login git.carlpearson.net -u "${{ secrets.GIT_USERNAME }}" --password-stdin
|
||||
docker push ${{ env.SLUG }}:latest
|
||||
docker push ${{ env.SLUG }}:${{ env.DATE }}
|
||||
20
Dockerfile
20
Dockerfile
@@ -1,11 +1,15 @@
|
||||
FROM golang:1.23.3-bookworm AS builder
|
||||
FROM golang:1.25.1-trixie AS builder
|
||||
ARG GIT_SHA="<not provided>"
|
||||
|
||||
|
||||
# install yt-dlp
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends --no-install-suggests wget
|
||||
RUN wget -q -d https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux -O /usr/local/bin/yt-dlp \
|
||||
&& chmod +x /usr/local/bin/yt-dlp
|
||||
|
||||
# install deno
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends --no-install-suggests curl unzip
|
||||
RUN curl -fsSL https://deno.land/install.sh | sh
|
||||
|
||||
ADD *.go /src/.
|
||||
ADD config /src/config
|
||||
ADD database /src/database
|
||||
@@ -13,24 +17,30 @@ ADD ffmpeg /src/ffmpeg
|
||||
ADD handlers /src/handlers
|
||||
ADD media /src/media
|
||||
ADD originals /src/originals
|
||||
Add playlists /src/playlists
|
||||
ADD playlists /src/playlists
|
||||
ADD transcodes /src/transcodes
|
||||
ADD users /src/users
|
||||
Add ytdlp /src/ytdlp
|
||||
ADD ytdlp /src/ytdlp
|
||||
ADD go.mod /src/.
|
||||
|
||||
RUN cd /src && go mod tidy
|
||||
RUN cd /src && go build -ldflags "-X ytdlp-site/config.gitSHA=${GIT_SHA} -X ytdlp-site/config.buildDate=$(date +%Y-%m-%d)" -o server *.go
|
||||
|
||||
FROM debian:bookworm-slim
|
||||
FROM debian:trixie-slim
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends --no-install-suggests \
|
||||
ffmpeg \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# copy yt-dlp
|
||||
COPY --from=0 /usr/local/bin/yt-dlp /usr/local/bin/yt-dlp
|
||||
COPY --from=0 /src/server /opt/server
|
||||
|
||||
# copy deno
|
||||
COPY --from=0 /root/.deno /root/.deno
|
||||
ENV PATH="/root/.deno/bin:$PATH"
|
||||
|
||||
ADD templates /opt/templates
|
||||
ADD static /opt/static
|
||||
|
||||
|
||||
6
go.mod
6
go.mod
@@ -1,8 +1,8 @@
|
||||
module ytdlp-site
|
||||
|
||||
go 1.23
|
||||
go 1.24
|
||||
|
||||
toolchain go1.23.0
|
||||
toolchain go1.24.5
|
||||
|
||||
require (
|
||||
github.com/google/uuid v1.6.0
|
||||
@@ -10,6 +10,7 @@ require (
|
||||
github.com/labstack/echo/v4 v4.10.2
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
golang.org/x/crypto v0.9.0
|
||||
golang.org/x/sys v0.8.0
|
||||
gorm.io/driver/sqlite v1.5.1
|
||||
gorm.io/gorm v1.25.1
|
||||
)
|
||||
@@ -26,7 +27,6 @@ require (
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||
golang.org/x/net v0.10.0 // indirect
|
||||
golang.org/x/sys v0.8.0 // indirect
|
||||
golang.org/x/text v0.9.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
)
|
||||
|
||||
20
handlers.go
20
handlers.go
@@ -22,7 +22,6 @@ import (
|
||||
"ytdlp-site/originals"
|
||||
"ytdlp-site/playlists"
|
||||
"ytdlp-site/transcodes"
|
||||
"ytdlp-site/users"
|
||||
"ytdlp-site/ytdlp"
|
||||
)
|
||||
|
||||
@@ -36,23 +35,6 @@ type DisplayVideoClip struct {
|
||||
Stop string
|
||||
}
|
||||
|
||||
func registerHandler(c echo.Context) error {
|
||||
return c.Render(http.StatusOK, "register.html", nil)
|
||||
}
|
||||
|
||||
func registerPostHandler(c echo.Context) error {
|
||||
username := c.FormValue("username")
|
||||
password := c.FormValue("password")
|
||||
|
||||
err := users.Create(db, username, password)
|
||||
|
||||
if err != nil {
|
||||
return c.String(http.StatusInternalServerError, "Error creating user")
|
||||
}
|
||||
|
||||
return c.Redirect(http.StatusSeeOther, "/login")
|
||||
}
|
||||
|
||||
func homeHandler(c echo.Context) error {
|
||||
_, err := handlers.GetUser(c)
|
||||
if err != nil {
|
||||
@@ -623,7 +605,7 @@ func startDownload(originalID uint, videoURL string, audioOnly bool) {
|
||||
cmd.Dir = tempDir
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
log.Errorln("yt-dlp failed")
|
||||
log.Errorf("yt-dlp run error: %v")
|
||||
originals.SetStatus(originalID, originals.StatusFailed)
|
||||
return
|
||||
}
|
||||
|
||||
16
main.go
16
main.go
@@ -1,7 +1,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io"
|
||||
golog "log"
|
||||
@@ -95,24 +94,25 @@ func main() {
|
||||
sqlDB.SetMaxOpenConns(1)
|
||||
|
||||
// Migrate the schema
|
||||
db.AutoMigrate(&originals.Original{}, &playlists.Playlist{},
|
||||
if err := db.AutoMigrate(&originals.Original{}, &playlists.Playlist{},
|
||||
&media.Video{}, &media.Audio{}, &media.VideoClip{},
|
||||
&users.User{}, &TempURL{}, &transcodes.Transcode{})
|
||||
&users.User{}, &TempURL{}, &transcodes.Transcode{}); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
database.Init(db, log)
|
||||
defer database.Fini()
|
||||
err = handlers.Init(log)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("%v", err))
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer handlers.Fini()
|
||||
|
||||
go PeriodicCleanup()
|
||||
|
||||
// create a user
|
||||
err = ensureAdminAccount(db)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to create admin user: %v", err))
|
||||
if err = ensureAdminAccount(db); err != nil {
|
||||
log.Fatal("create admin account error:", err)
|
||||
}
|
||||
|
||||
// Initialize Echo
|
||||
@@ -132,8 +132,6 @@ func main() {
|
||||
e.GET("/", homeHandler)
|
||||
e.GET("/login", handlers.LoginGet)
|
||||
e.POST("/login", handlers.LoginPost)
|
||||
// e.GET("/register", registerHandler)
|
||||
// e.POST("/register", registerPostHandler)
|
||||
e.GET("/logout", handlers.LogoutGet)
|
||||
e.GET("/download", downloadHandler, handlers.AuthMiddleware)
|
||||
e.POST("/download", downloadPostHandler, handlers.AuthMiddleware)
|
||||
|
||||
@@ -277,7 +277,7 @@ func cleanupTranscodes() {
|
||||
err := db.Where("status = ?", "pending").
|
||||
Order("CASE " +
|
||||
"WHEN dst_kind = 'video' AND height = 540 THEN 0 " +
|
||||
"WHEN dst_kind = 'audio' AND rate = 96 THEN 0 " +
|
||||
"WHEN dst_kind = 'audio' AND kbps = 96 THEN 0 " +
|
||||
"ELSE 1 END").First(&trans).Error
|
||||
// err := db.First(&trans, "status = ?", "pending").Error
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
|
||||
Reference in New Issue
Block a user