mirror of
https://gitlab.com/foxixus/neomovies-api.git
synced 2025-10-28 09:58:50 +05:00
Compare commits
2 Commits
e734e462c4
...
feature/ad
| Author | SHA1 | Date | |
|---|---|---|---|
| 1cdc35370b | |||
|
|
a8cdfd9a5f |
@@ -96,7 +96,6 @@ func Handler(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
api.HandleFunc("/players/alloha/{imdb_id}", playersHandler.GetAllohaPlayer).Methods("GET")
|
api.HandleFunc("/players/alloha/{imdb_id}", playersHandler.GetAllohaPlayer).Methods("GET")
|
||||||
api.HandleFunc("/players/lumex/{imdb_id}", playersHandler.GetLumexPlayer).Methods("GET")
|
api.HandleFunc("/players/lumex/{imdb_id}", playersHandler.GetLumexPlayer).Methods("GET")
|
||||||
api.HandleFunc("/players/vibix/{imdb_id}", playersHandler.GetVibixPlayer).Methods("GET")
|
|
||||||
api.HandleFunc("/players/rgshows/{tmdb_id}", playersHandler.GetRgShowsPlayer).Methods("GET")
|
api.HandleFunc("/players/rgshows/{tmdb_id}", playersHandler.GetRgShowsPlayer).Methods("GET")
|
||||||
api.HandleFunc("/players/rgshows/{tmdb_id}/{season}/{episode}", playersHandler.GetRgShowsTVPlayer).Methods("GET")
|
api.HandleFunc("/players/rgshows/{tmdb_id}/{season}/{episode}", playersHandler.GetRgShowsTVPlayer).Methods("GET")
|
||||||
api.HandleFunc("/players/iframevideo/{kinopoisk_id}/{imdb_id}", playersHandler.GetIframeVideoPlayer).Methods("GET")
|
api.HandleFunc("/players/iframevideo/{kinopoisk_id}/{imdb_id}", playersHandler.GetIframeVideoPlayer).Methods("GET")
|
||||||
@@ -153,9 +152,8 @@ func Handler(w http.ResponseWriter, r *http.Request) {
|
|||||||
corsHandler := handlers.CORS(
|
corsHandler := handlers.CORS(
|
||||||
handlers.AllowedOrigins([]string{"*"}),
|
handlers.AllowedOrigins([]string{"*"}),
|
||||||
handlers.AllowedMethods([]string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}),
|
handlers.AllowedMethods([]string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}),
|
||||||
handlers.AllowedHeaders([]string{"Authorization", "Content-Type", "Accept", "Origin", "X-Requested-With", "X-CSRF-Token"}),
|
handlers.AllowedHeaders([]string{"Authorization", "Content-Type", "Accept", "Origin", "X-Requested-With"}),
|
||||||
handlers.AllowCredentials(),
|
handlers.AllowCredentials(),
|
||||||
handlers.ExposedHeaders([]string{"Authorization", "Content-Type"}),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
corsHandler(router).ServeHTTP(w, r)
|
corsHandler(router).ServeHTTP(w, r)
|
||||||
|
|||||||
@@ -374,8 +374,76 @@ func getOpenAPISpecWithURL(baseURL string) *OpenAPISpec {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"/api/v1/webtorrent/player": map[string]interface{}{
|
||||||
|
"get": map[string]interface{}{
|
||||||
|
"summary": "WebTorrent плеер",
|
||||||
|
"description": "Открытие WebTorrent плеера с магнет ссылкой. Плеер работает полностью на стороне клиента.",
|
||||||
|
"tags": []string{"WebTorrent"},
|
||||||
|
"parameters": []map[string]interface{}{
|
||||||
|
{
|
||||||
|
"name": "magnet",
|
||||||
|
"in": "query",
|
||||||
|
"required": false,
|
||||||
|
"schema": map[string]string{"type": "string"},
|
||||||
|
"description": "Магнет ссылка торрента",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "X-Magnet-Link",
|
||||||
|
"in": "header",
|
||||||
|
"required": false,
|
||||||
|
"schema": map[string]string{"type": "string"},
|
||||||
|
"description": "Магнет ссылка через заголовок (альтернативный способ)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"responses": map[string]interface{}{
|
||||||
|
"200": map[string]interface{}{
|
||||||
|
"description": "HTML страница с WebTorrent плеером",
|
||||||
|
"content": map[string]interface{}{
|
||||||
|
"text/html": map[string]interface{}{
|
||||||
|
"schema": map[string]string{"type": "string"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"400": map[string]interface{}{
|
||||||
|
"description": "Отсутствует магнет ссылка",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"/api/v1/webtorrent/metadata": map[string]interface{}{
|
||||||
|
"get": map[string]interface{}{
|
||||||
|
"summary": "Метаданные медиа",
|
||||||
|
"description": "Получение метаданных фильма или сериала по названию для WebTorrent плеера",
|
||||||
|
"tags": []string{"WebTorrent"},
|
||||||
|
"parameters": []map[string]interface{}{
|
||||||
|
{
|
||||||
|
"name": "query",
|
||||||
|
"in": "query",
|
||||||
|
"required": true,
|
||||||
|
"schema": map[string]string{"type": "string"},
|
||||||
|
"description": "Название для поиска (извлеченное из торрента)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"responses": map[string]interface{}{
|
||||||
|
"200": map[string]interface{}{
|
||||||
|
"description": "Метаданные найдены",
|
||||||
|
"content": map[string]interface{}{
|
||||||
|
"application/json": map[string]interface{}{
|
||||||
|
"schema": map[string]interface{}{
|
||||||
|
"$ref": "#/components/schemas/WebTorrentMetadata",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"400": map[string]interface{}{
|
||||||
|
"description": "Отсутствует параметр query",
|
||||||
|
},
|
||||||
|
"404": map[string]interface{}{
|
||||||
|
"description": "Метаданные не найдены",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
"/api/v1/torrents/search/{imdbId}": map[string]interface{}{
|
"/api/v1/torrents/search/{imdbId}": map[string]interface{}{
|
||||||
"get": map[string]interface{}{
|
"get": map[string]interface{}{
|
||||||
"summary": "Поиск торрентов",
|
"summary": "Поиск торрентов",
|
||||||
|
|||||||
@@ -144,100 +144,6 @@ func (h *PlayersHandler) GetLumexPlayer(w http.ResponseWriter, r *http.Request)
|
|||||||
log.Printf("Successfully served Lumex player for imdb_id: %s", imdbID)
|
log.Printf("Successfully served Lumex player for imdb_id: %s", imdbID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *PlayersHandler) GetVibixPlayer(w http.ResponseWriter, r *http.Request) {
|
|
||||||
log.Printf("GetVibixPlayer called: %s %s", r.Method, r.URL.Path)
|
|
||||||
|
|
||||||
vars := mux.Vars(r)
|
|
||||||
log.Printf("Route vars: %+v", vars)
|
|
||||||
|
|
||||||
imdbID := vars["imdb_id"]
|
|
||||||
if imdbID == "" {
|
|
||||||
log.Printf("Error: imdb_id is empty")
|
|
||||||
http.Error(w, "imdb_id path param is required", http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("Processing imdb_id: %s", imdbID)
|
|
||||||
|
|
||||||
if h.config.VibixToken == "" {
|
|
||||||
log.Printf("Error: VIBIX_TOKEN is missing")
|
|
||||||
http.Error(w, "Server misconfiguration: VIBIX_TOKEN missing", http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
vibixHost := h.config.VibixHost
|
|
||||||
if vibixHost == "" {
|
|
||||||
vibixHost = "https://vibix.org"
|
|
||||||
}
|
|
||||||
|
|
||||||
apiURL := fmt.Sprintf("%s/api/v1/publisher/videos/imdb/%s", vibixHost, imdbID)
|
|
||||||
log.Printf("Calling Vibix API: %s", apiURL)
|
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", apiURL, nil)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error creating Vibix request: %v", err)
|
|
||||||
http.Error(w, "Failed to create request", http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
req.Header.Set("Accept", "application/json")
|
|
||||||
req.Header.Set("Authorization", "Bearer "+h.config.VibixToken)
|
|
||||||
req.Header.Set("X-CSRF-TOKEN", "")
|
|
||||||
|
|
||||||
client := &http.Client{Timeout: 8 * time.Second}
|
|
||||||
resp, err := client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error calling Vibix API: %v", err)
|
|
||||||
http.Error(w, "Failed to fetch from Vibix API", http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
log.Printf("Vibix API response status: %d", resp.StatusCode)
|
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
log.Printf("Vibix API error: %d", resp.StatusCode)
|
|
||||||
http.Error(w, fmt.Sprintf("Vibix API error: %d", resp.StatusCode), http.StatusBadGateway)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
body, err := io.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error reading Vibix response: %v", err)
|
|
||||||
http.Error(w, "Failed to read Vibix response", http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("Vibix API response body: %s", string(body))
|
|
||||||
|
|
||||||
var vibixResponse struct {
|
|
||||||
ID interface{} `json:"id"`
|
|
||||||
IframeURL string `json:"iframe_url"`
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := json.Unmarshal(body, &vibixResponse); err != nil {
|
|
||||||
log.Printf("Error unmarshaling Vibix JSON: %v", err)
|
|
||||||
http.Error(w, "Invalid JSON from Vibix", http.StatusBadGateway)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if vibixResponse.ID == nil || vibixResponse.IframeURL == "" {
|
|
||||||
log.Printf("Video not found or empty iframe_url")
|
|
||||||
http.Error(w, "Video not found", http.StatusNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("Generated Vibix iframe URL: %s", vibixResponse.IframeURL)
|
|
||||||
|
|
||||||
iframe := fmt.Sprintf(`<iframe src="%s" allowfullscreen loading="lazy" style="border:none;width:100%%;height:100%%;"></iframe>`, vibixResponse.IframeURL)
|
|
||||||
htmlDoc := fmt.Sprintf(`<!DOCTYPE html><html><head><meta charset='utf-8'/><title>Vibix Player</title><style>html,body{margin:0;height:100%%;}</style></head><body>%s</body></html>`, iframe)
|
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "text/html")
|
|
||||||
w.Write([]byte(htmlDoc))
|
|
||||||
|
|
||||||
log.Printf("Successfully served Vibix player for imdb_id: %s", imdbID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetRgShowsPlayer handles RgShows streaming requests
|
// GetRgShowsPlayer handles RgShows streaming requests
|
||||||
func (h *PlayersHandler) GetRgShowsPlayer(w http.ResponseWriter, r *http.Request) {
|
func (h *PlayersHandler) GetRgShowsPlayer(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Printf("GetRgShowsPlayer called: %s %s", r.Method, r.URL.Path)
|
log.Printf("GetRgShowsPlayer called: %s %s", r.Method, r.URL.Path)
|
||||||
|
|||||||
Reference in New Issue
Block a user