Files
zurg/pkg/realdebrid/api.go
2023-10-23 20:01:55 +02:00

352 lines
8.7 KiB
Go

package realdebrid
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"net/url"
"strconv"
)
func UnrestrictCheck(accessToken, link string) (*UnrestrictResponse, error) {
data := url.Values{}
data.Set("link", link)
req, err := http.NewRequest("POST", "https://api.real-debrid.com/rest/1.0/unrestrict/check", bytes.NewBufferString(data.Encode()))
if err != nil {
return nil, err
}
req.Header.Set("Authorization", "Bearer "+accessToken)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("HTTP error: %s", resp.Status)
}
var response UnrestrictResponse
err = json.Unmarshal(body, &response)
if err != nil {
return nil, err
}
return &response, nil
}
func UnrestrictLink(accessToken, link string) (*UnrestrictResponse, error) {
data := url.Values{}
data.Set("link", link)
req, err := http.NewRequest("POST", "https://api.real-debrid.com/rest/1.0/unrestrict/link", bytes.NewBufferString(data.Encode()))
if err != nil {
return nil, err
}
req.Header.Set("Authorization", "Bearer "+accessToken)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("HTTP error: %s", resp.Status)
}
var response UnrestrictResponse
err = json.Unmarshal(body, &response)
if err != nil {
return nil, err
}
if !canFetchFirstByte(response.Download) {
return nil, fmt.Errorf("can't fetch first byte")
}
return &response, nil
}
// GetTorrents returns all torrents, paginated
// if customLimit is 0, the default limit of 2500 is used
func GetTorrents(accessToken string, customLimit int) ([]Torrent, int, error) {
baseURL := "https://api.real-debrid.com/rest/1.0/torrents"
var allTorrents []Torrent
page := 1
limit := customLimit
if limit == 0 {
limit = 2500
}
totalCount := 0
for {
params := url.Values{}
params.Set("page", fmt.Sprintf("%d", page))
params.Set("limit", fmt.Sprintf("%d", limit))
params.Set("filter", "active")
reqURL := baseURL + "?" + params.Encode()
req, err := http.NewRequest("GET", reqURL, nil)
if err != nil {
return nil, 0, err
}
req.Header.Set("Authorization", "Bearer "+accessToken)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, 0, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, 0, fmt.Errorf("HTTP error: %s", resp.Status)
}
var torrents []Torrent
decoder := json.NewDecoder(resp.Body)
err = decoder.Decode(&torrents)
if err != nil {
return nil, 0, err
}
allTorrents = append(allTorrents, torrents...)
totalCountHeader := resp.Header.Get("x-total-count")
totalCount, err = strconv.Atoi(totalCountHeader)
if err != nil {
break
}
if len(allTorrents) >= totalCount || (customLimit != 0 && customLimit <= len(allTorrents) && customLimit <= totalCount) {
break
}
page++
}
return allTorrents, totalCount, nil
}
func GetTorrentInfo(accessToken, id string) (*Torrent, error) {
url := "https://api.real-debrid.com/rest/1.0/torrents/info/" + id
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
req.Header.Set("Authorization", "Bearer "+accessToken)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("HTTP error: %s", resp.Status)
}
var response Torrent
err = json.Unmarshal(body, &response)
if err != nil {
return nil, err
}
return &response, nil
}
// SelectTorrentFiles selects files of a torrent to start it.
func SelectTorrentFiles(accessToken string, id string, files string) error {
// Prepare request data
data := url.Values{}
data.Set("files", files)
// Construct request URL
reqURL := fmt.Sprintf("https://api.real-debrid.com/rest/1.0/torrents/selectFiles/%s", id)
req, err := http.NewRequest("POST", reqURL, bytes.NewBufferString(data.Encode()))
if err != nil {
return err
}
// Set request headers
req.Header.Set("Authorization", "Bearer "+accessToken)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
// Send the request
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
// Handle response status codes
switch resp.StatusCode {
case http.StatusOK, http.StatusNoContent:
return nil // Success
case http.StatusAccepted:
return errors.New("action already done")
case http.StatusBadRequest:
return errors.New("bad request")
case http.StatusUnauthorized:
return errors.New("bad token (expired or invalid)")
case http.StatusForbidden:
return errors.New("permission denied (account locked or not premium)")
case http.StatusNotFound:
return errors.New("wrong parameter (invalid file id(s)) or unknown resource (invalid id)")
default:
return fmt.Errorf("unexpected HTTP error: %s", resp.Status)
}
}
// DeleteTorrent deletes a torrent from the torrents list.
func DeleteTorrent(accessToken string, id string) error {
// Construct request URL
reqURL := fmt.Sprintf("https://api.real-debrid.com/rest/1.0/torrents/delete/%s", id)
req, err := http.NewRequest("DELETE", reqURL, nil)
if err != nil {
return err
}
// Set request headers
req.Header.Set("Authorization", "Bearer "+accessToken)
// Send the request
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
// Handle response status codes
switch resp.StatusCode {
case http.StatusNoContent:
return nil // Success
case http.StatusUnauthorized:
return errors.New("bad token (expired or invalid)")
case http.StatusForbidden:
return errors.New("permission denied (account locked)")
case http.StatusNotFound:
return errors.New("unknown resource")
default:
return fmt.Errorf("unexpected HTTP error: %s", resp.Status)
}
}
// AddMagnetHash adds a magnet link to download.
func AddMagnetHash(accessToken, magnet string) (*MagnetResponse, error) {
// Prepare request data
data := url.Values{}
data.Set("magnet", fmt.Sprintf("magnet:?xt=urn:btih:%s", magnet))
// Construct request URL
reqURL := "https://api.real-debrid.com/rest/1.0/torrents/addMagnet"
req, err := http.NewRequest("POST", reqURL, bytes.NewBufferString(data.Encode()))
if err != nil {
return nil, err
}
// Set request headers
req.Header.Set("Authorization", "Bearer "+accessToken)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
// Send the request
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
// Handle response status codes
switch resp.StatusCode {
case http.StatusCreated:
var response MagnetResponse
err := json.NewDecoder(resp.Body).Decode(&response)
if err != nil {
return nil, err
}
return &response, nil
case http.StatusBadRequest:
return nil, errors.New("bad request")
case http.StatusUnauthorized:
return nil, errors.New("bad token (expired or invalid)")
case http.StatusForbidden:
return nil, errors.New("permission denied (account locked or not premium)")
case http.StatusServiceUnavailable:
return nil, errors.New("service unavailable")
default:
return nil, fmt.Errorf("unexpected HTTP error: %s", resp.Status)
}
}
// GetActiveTorrentCount gets the number of currently active torrents and the current maximum limit.
func GetActiveTorrentCount(accessToken string) (*ActiveTorrentCountResponse, error) {
// Construct request URL
reqURL := "https://api.real-debrid.com/rest/1.0/torrents/activeCount"
req, err := http.NewRequest("GET", reqURL, nil)
if err != nil {
return nil, err
}
// Set request headers
req.Header.Set("Authorization", "Bearer "+accessToken)
// Send the request
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
// Handle response status codes
switch resp.StatusCode {
case http.StatusOK:
var response ActiveTorrentCountResponse
err := json.NewDecoder(resp.Body).Decode(&response)
if err != nil {
return nil, err
}
return &response, nil
case http.StatusUnauthorized:
return nil, errors.New("bad token (expired or invalid)")
case http.StatusForbidden:
return nil, errors.New("permission denied (account locked)")
default:
return nil, fmt.Errorf("unexpected HTTP error: %s", resp.Status)
}
}