222 lines
4.7 KiB
Go
222 lines
4.7 KiB
Go
package realdebrid
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"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 &response, nil
|
|
}
|
|
return nil, fmt.Errorf("can't fetch first byte")
|
|
}
|
|
|
|
func canFetchFirstByte(url string) bool {
|
|
// Create a new HTTP request
|
|
req, err := http.NewRequest("GET", url, nil)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
|
|
// Set the Range header to request only the first byte
|
|
req.Header.Set("Range", "bytes=0-0")
|
|
|
|
// Execute the request
|
|
resp, err := http.DefaultClient.Do(req)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
// If server supports partial content
|
|
if resp.StatusCode == http.StatusPartialContent {
|
|
buffer := make([]byte, 1)
|
|
_, err := resp.Body.Read(buffer)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
// If server doesn't support partial content, try reading the first byte and immediately close
|
|
buffer := make([]byte, 1)
|
|
_, err = io.ReadFull(resp.Body, buffer)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
// 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))
|
|
|
|
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
|
|
}
|