basic map results + improved fetching from piped
This commit is contained in:
parent
1efca320c8
commit
6c9ec56327
9 changed files with 239 additions and 20 deletions
102
video.go
102
video.go
|
@ -8,10 +8,30 @@ import (
|
|||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const PIPED_INSTANCE = "pipedapi.kavin.rocks"
|
||||
const retryDuration = 12 * time.Hour // Retry duration for unresponding piped instances
|
||||
|
||||
var (
|
||||
pipedInstances = []string{
|
||||
"pipedapi.kavin.rocks",
|
||||
"api.piped.yt",
|
||||
"pipedapi.moomoo.me",
|
||||
"pipedapi.darkness.services",
|
||||
"piped-api.hostux.net",
|
||||
"pipedapi.syncpundit.io",
|
||||
"piped-api.cfe.re",
|
||||
"pipedapi.in.projectsegfau.lt",
|
||||
"piapi.ggtyler.dev",
|
||||
"piped-api.codespace.cz",
|
||||
"pipedapi.coldforge.xyz",
|
||||
"pipedapi.osphost.fi",
|
||||
}
|
||||
disabledInstances = make(map[string]bool)
|
||||
mu sync.Mutex
|
||||
)
|
||||
|
||||
// VideoResult reflects the structured data for a video result
|
||||
type VideoResult struct {
|
||||
|
@ -71,24 +91,76 @@ func formatDuration(seconds int) string {
|
|||
return fmt.Sprintf("%02d:%02d", minutes, seconds)
|
||||
}
|
||||
|
||||
// makeHTMLRequest fetches search results from the Piped API, similarly to the Python `makeHTMLRequest`
|
||||
func init() {
|
||||
go checkDisabledInstancesPeriodically()
|
||||
}
|
||||
|
||||
func checkDisabledInstancesPeriodically() {
|
||||
checkAndReactivateInstances() // Initial immediate check
|
||||
ticker := time.NewTicker(retryDuration)
|
||||
defer ticker.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
checkAndReactivateInstances()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func checkAndReactivateInstances() {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
|
||||
for instance, isDisabled := range disabledInstances {
|
||||
if isDisabled {
|
||||
// Check if the instance is available again
|
||||
if testInstanceAvailability(instance) {
|
||||
log.Printf("Instance %s is now available and reactivated.", instance)
|
||||
delete(disabledInstances, instance)
|
||||
} else {
|
||||
log.Printf("Instance %s is still not available.", instance)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testInstanceAvailability(instance string) bool {
|
||||
resp, err := http.Get(fmt.Sprintf("https://%s/search?q=%s&filter=all", instance, url.QueryEscape("test")))
|
||||
if err != nil || resp.StatusCode != http.StatusOK {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func makeHTMLRequest(query string) (*VideoAPIResponse, error) {
|
||||
resp, err := http.Get(fmt.Sprintf("https://%s/search?q=%s&filter=all", PIPED_INSTANCE, url.QueryEscape(query)))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error making request: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
var lastError error
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
|
||||
}
|
||||
for _, instance := range pipedInstances {
|
||||
if disabledInstances[instance] {
|
||||
continue // Skip this instance because it's still disabled
|
||||
}
|
||||
|
||||
var apiResp VideoAPIResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&apiResp); err != nil {
|
||||
return nil, fmt.Errorf("error decoding response: %w", err)
|
||||
}
|
||||
url := fmt.Sprintf("https://%s/search?q=%s&filter=all", instance, url.QueryEscape(query))
|
||||
resp, err := http.Get(url)
|
||||
if err != nil || resp.StatusCode != http.StatusOK {
|
||||
log.Printf("Disabling instance %s due to error or status code: %v", instance, err)
|
||||
disabledInstances[instance] = true
|
||||
lastError = fmt.Errorf("error making request to %s: %w", instance, err)
|
||||
continue
|
||||
}
|
||||
|
||||
return &apiResp, nil
|
||||
defer resp.Body.Close()
|
||||
var apiResp VideoAPIResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&apiResp); err != nil {
|
||||
lastError = fmt.Errorf("error decoding response from %s: %w", instance, err)
|
||||
continue
|
||||
}
|
||||
return &apiResp, nil
|
||||
}
|
||||
return nil, fmt.Errorf("all instances failed, last error: %v", lastError)
|
||||
}
|
||||
|
||||
func videoSearchEndpointHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue