initial push
This commit is contained in:
commit
6470a6882b
6 changed files with 199 additions and 0 deletions
25
.gitignore
vendored
Normal file
25
.gitignore
vendored
Normal 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
18
Dockerfile
Normal 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
10
docker-compose.yaml
Normal 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
3
env.template
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
TORRENT_BASEPATH=""
|
||||
TORRENT_USERNAME=""
|
||||
TORRENT_PASSWORD=""
|
||||
3
go.mod
Normal file
3
go.mod
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
module git.domandoman.xyz/doman/tchecker
|
||||
|
||||
go 1.24.1
|
||||
140
main.go
Normal file
140
main.go
Normal 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")
|
||||
}
|
||||
Loading…
Reference in a new issue