initial push

This commit is contained in:
Piotr Domański 2025-09-17 20:25:56 +02:00
commit 6470a6882b
6 changed files with 199 additions and 0 deletions

25
.gitignore vendored Normal file
View file

@ -0,0 +1,25 @@
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
# Go workspace file
go.work
go.work.sum
# env file
.env

18
Dockerfile Normal file
View file

@ -0,0 +1,18 @@
FROM golang:alpine as builder
# build app
WORKDIR /opt/torrentchecker/src
COPY . /opt/torrentchecker/src
RUN go build -o /opt/torrentchecker/torrentchecker main.go
RUN chmod a+x /opt/torrentchecker/torrentchecker
# target image
FROM golang:alpine
RUN mkdir -p /opt/torrentchecker
COPY --from=builder /opt/torrentchecker/torrentchecker /opt/torrentchecker/torrentchecker
RUN crontab -l | { cat; echo "0 * * * * /opt/torrentchecker/torrentchecker"; } | crontab -
CMD ["crond", "-f", "-l", "2"]

10
docker-compose.yaml Normal file
View file

@ -0,0 +1,10 @@
services:
app:
image: registry.domandoman.xyz/utils/torrentchecker
restart: unless-stopped
build:
context: .
dockerfile: Dockerfile
env_file:
- .env
platform: "linux/amd64"

3
env.template Normal file
View file

@ -0,0 +1,3 @@
TORRENT_BASEPATH=""
TORRENT_USERNAME=""
TORRENT_PASSWORD=""

3
go.mod Normal file
View file

@ -0,0 +1,3 @@
module git.domandoman.xyz/doman/tchecker
go 1.24.1

140
main.go Normal file
View file

@ -0,0 +1,140 @@
package main
import (
"encoding/json"
"fmt"
"net/http"
"net/http/cookiejar"
"net/url"
"os"
)
type HTTPClient struct {
client *http.Client
basePath string
jar *cookiejar.Jar
}
func NewHTTPClient(basePath string) *HTTPClient {
jar, err := cookiejar.New(nil)
if err != nil {
panic(err)
}
return &HTTPClient{
client: &http.Client{Jar: jar},
basePath: basePath,
jar: jar,
}
}
func (c *HTTPClient) Get(subPath string, query map[string]string) (*http.Response, error) {
combined, err := url.JoinPath(c.basePath, subPath)
if err != nil {
return nil, err
}
parsed, err := url.Parse(combined)
if err != nil {
return nil, err
}
if query != nil {
q := parsed.Query()
for k, v := range query {
q.Set(k, v)
}
parsed.RawQuery = q.Encode()
}
return c.client.Get(parsed.String())
}
func (c *HTTPClient) PostForm(subPath string, data map[string][]string) (*http.Response, error) {
url, err := url.JoinPath(c.basePath, subPath)
if err != nil {
return nil, err
}
return c.client.PostForm(url, data)
}
func (c *HTTPClient) Login(username string, password string) error {
resp, err := c.PostForm("/api/v2/auth/login", map[string][]string{"username": {username}, "password": {password}})
if err != nil {
return err
}
if resp.StatusCode != 200 {
return fmt.Errorf("unexpected status code: %d", resp.StatusCode)
}
setCookie := resp.Header.Get("Set-Cookie")
if setCookie == "" {
return fmt.Errorf("no Set-Cookie in response header")
}
jarCookie := c.jar.Cookies(resp.Request.URL)
if len(jarCookie) == 0 {
return fmt.Errorf("no cookie saved to cookiejar")
}
return nil
}
func main() {
basePath := os.Getenv("TORRENT_BASEPATH")
username := os.Getenv("TORRENT_USERNAME")
password := os.Getenv("TORRENT_PASSWORD")
client := NewHTTPClient(basePath)
err := client.Login(username, password)
if err != nil {
panic(err)
}
resp, err := client.Get("/api/v2/torrents/info", map[string]string{"filter": "seeding"})
if err != nil {
panic(err)
}
if resp.StatusCode != 200 {
panic(fmt.Errorf("unexpected status code: %d", resp.StatusCode))
}
decoder := json.NewDecoder(resp.Body)
var torrents []map[string]interface{}
err = decoder.Decode(&torrents)
if err != nil {
panic(err)
}
for _, torrent := range torrents {
resp, err := client.PostForm("/api/v2/torrents/stop", map[string][]string{"hashes": {torrent["hash"].(string)}})
if err != nil {
panic(err)
}
if resp.StatusCode != 200 {
panic(fmt.Errorf("unexpected status code: %d", resp.StatusCode))
}
}
fmt.Println("done")
}