diff --git a/.env.example b/.env.example index 70ee0e3..d97cc69 100644 --- a/.env.example +++ b/.env.example @@ -16,6 +16,7 @@ GMAIL_APP_PASSWORD=your_gmail_app_password # Players LUMEX_URL= ALLOHA_TOKEN=your_alloha_token +VIBIX_TOKEN # Torrents (RedAPI) REDAPI_BASE_URL=http://redapi.cfhttp.top diff --git a/README.md b/README.md index 7193ce3..b3eeb1f 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,7 @@ GMAIL_APP_PASSWORD=your_gmail_app_password # Плееры LUMEX_URL= ALLOHA_TOKEN=your_alloha_token +VIBIX_TOKEN=your_vibix_token # Торренты (RedAPI) REDAPI_BASE_URL=http://redapi.cfhttp.top @@ -122,6 +123,7 @@ GET /api/v1/tv/{id}/similar # Похожие # Плееры GET /api/v1/players/alloha/{imdb_id} # Alloha плеер по IMDb ID GET /api/v1/players/lumex/{imdb_id} # Lumex плеер по IMDb ID +GET /api/v1/players/vibix/{imdb_id} # Vibix плеер по IMDb ID # Торренты GET /api/v1/torrents/search/{imdbId} # Поиск торрентов diff --git a/api/index.go b/api/index.go index 219136d..fa1b4e8 100644 --- a/api/index.go +++ b/api/index.go @@ -91,6 +91,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { api.HandleFunc("/players/alloha/{imdb_id}", playersHandler.GetAllohaPlayer).Methods("GET") api.HandleFunc("/players/lumex/{imdb_id}", playersHandler.GetLumexPlayer).Methods("GET") + api.HandleFunc("/players/vibix/{imdb_id}", playersHandler.GetVibixPlayer).Methods("GET") api.HandleFunc("/torrents/search/{imdbId}", torrentsHandler.SearchTorrents).Methods("GET") api.HandleFunc("/torrents/movies", torrentsHandler.SearchMovies).Methods("GET") diff --git a/main.go b/main.go index 8426f38..a87bc61 100644 --- a/main.go +++ b/main.go @@ -71,6 +71,7 @@ func main() { api.HandleFunc("/players/alloha/{imdb_id}", playersHandler.GetAllohaPlayer).Methods("GET") api.HandleFunc("/players/lumex/{imdb_id}", playersHandler.GetLumexPlayer).Methods("GET") + api.HandleFunc("/players/vibix/{imdb_id}", playersHandler.GetVibixPlayer).Methods("GET") api.HandleFunc("/torrents/search/{imdbId}", torrentsHandler.SearchTorrents).Methods("GET") api.HandleFunc("/torrents/movies", torrentsHandler.SearchMovies).Methods("GET") diff --git a/pkg/config/config.go b/pkg/config/config.go index eda0414..c7a9376 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -23,6 +23,8 @@ type Config struct { GoogleClientSecret string GoogleRedirectURL string FrontendURL string + VibixHost string + VibixToken string } func New() *Config { @@ -46,6 +48,8 @@ func New() *Config { GoogleClientSecret: getEnv(EnvGoogleClientSecret, ""), GoogleRedirectURL: getEnv(EnvGoogleRedirectURL, ""), FrontendURL: getEnv(EnvFrontendURL, ""), + VibixHost: getEnv(EnvVibixHost, DefaultVibixHost), + VibixToken: getEnv(EnvVibixToken, ""), } } diff --git a/pkg/config/vars.go b/pkg/config/vars.go index 4541e9c..56ac949 100644 --- a/pkg/config/vars.go +++ b/pkg/config/vars.go @@ -18,7 +18,9 @@ const ( EnvGoogleClientSecret= "GOOGLE_CLIENT_SECRET" EnvGoogleRedirectURL = "GOOGLE_REDIRECT_URL" EnvFrontendURL = "FRONTEND_URL" - + EnvVibixHost = "VIBIX_HOST" + EnvVibixToken = "VIBIX_TOKEN" + // Default values DefaultJWTSecret = "your-secret-key" DefaultPort = "3000" @@ -26,6 +28,7 @@ const ( DefaultNodeEnv = "development" DefaultRedAPIBase = "http://redapi.cfhttp.top" DefaultMongoDBName = "database" + DefaultVibixHost = "https://vibix.org" // Static constants TMDBImageBaseURL = "https://image.tmdb.org/t/p" diff --git a/pkg/handlers/docs.go b/pkg/handlers/docs.go index 6d6531b..bb7a75f 100644 --- a/pkg/handlers/docs.go +++ b/pkg/handlers/docs.go @@ -251,6 +251,32 @@ func getOpenAPISpecWithURL(baseURL string) *OpenAPISpec { }, }, }, + "/api/v1/players/vibix/{imdb_id}": map[string]interface{}{ + "get": map[string]interface{}{ + "summary": "Vibix плеер по IMDb ID", + "description": "Возвращает HTML-страницу с iframe Vibix для указанного IMDb ID", + "tags": []string{"Players"}, + "parameters": []map[string]interface{}{ + { + "name": "imdb_id", + "in": "path", + "required": true, + "schema": map[string]string{"type": "string"}, + "description": "IMDb ID, например tt0133093", + }, + }, + "responses": map[string]interface{}{ + "200": map[string]interface{}{ + "description": "HTML со встроенным Vibix плеером", + "content": map[string]interface{}{ + "text/html": map[string]interface{}{}, + }, + }, + "404": map[string]interface{}{"description": "Фильм не найден"}, + "503": map[string]interface{}{"description": "VIBIX_TOKEN не настроен"}, + }, + }, + }, "/api/v1/torrents/search/{imdbId}": map[string]interface{}{ "get": map[string]interface{}{ "summary": "Поиск торрентов", @@ -553,8 +579,7 @@ func getOpenAPISpecWithURL(baseURL string) *OpenAPISpec { }, }, }, - // --- Добавленный блок для DELETE-запроса --- - "delete": map[string]interface{}{ + "delete": map[string]interface{}{ "summary": "Удалить аккаунт пользователя", "description": "Полное и безвозвратное удаление аккаунта пользователя и всех связанных с ним данных (избранное, реакции)", "tags": []string{"Authentication"}, @@ -584,7 +609,6 @@ func getOpenAPISpecWithURL(baseURL string) *OpenAPISpec { }, }, }, - // ------------------------------------------ }, "/api/v1/movies/search": map[string]interface{}{ "get": map[string]interface{}{ diff --git a/pkg/handlers/players.go b/pkg/handlers/players.go index 48a0a59..5fea0f0 100644 --- a/pkg/handlers/players.go +++ b/pkg/handlers/players.go @@ -3,140 +3,125 @@ package handlers import ( "encoding/json" "fmt" - "io" - "log" "net/http" - "net/url" - "strings" + "time" + + "github.com/gorilla/mux" "neomovies-api/pkg/config" - "github.com/gorilla/mux" ) type PlayersHandler struct { - config *config.Config + cfg *config.Config } func NewPlayersHandler(cfg *config.Config) *PlayersHandler { - return &PlayersHandler{ - config: cfg, - } + return &PlayersHandler{cfg: cfg} } func (h *PlayersHandler) GetAllohaPlayer(w http.ResponseWriter, r *http.Request) { - log.Printf("GetAllohaPlayer 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) + http.Error(w, "imdb_id is required", http.StatusBadRequest) return } - - log.Printf("Processing imdb_id: %s", imdbID) - - if h.config.AllohaToken == "" { - log.Printf("Error: ALLOHA_TOKEN is missing") - http.Error(w, "Server misconfiguration: ALLOHA_TOKEN missing", http.StatusInternalServerError) + if h.cfg.AllohaToken == "" { + http.Error(w, "ALLOHA_TOKEN is not configured", http.StatusServiceUnavailable) return } - - idParam := fmt.Sprintf("imdb=%s", url.QueryEscape(imdbID)) - apiURL := fmt.Sprintf("https://api.alloha.tv/?token=%s&%s", h.config.AllohaToken, idParam) - log.Printf("Calling Alloha API: %s", apiURL) - - resp, err := http.Get(apiURL) - if err != nil { - log.Printf("Error calling Alloha API: %v", err) - http.Error(w, "Failed to fetch from Alloha API", http.StatusInternalServerError) - return - } - defer resp.Body.Close() - - log.Printf("Alloha API response status: %d", resp.StatusCode) - - if resp.StatusCode != http.StatusOK { - http.Error(w, fmt.Sprintf("Alloha API error: %d", resp.StatusCode), http.StatusBadGateway) - return - } - - body, err := io.ReadAll(resp.Body) - if err != nil { - log.Printf("Error reading Alloha response: %v", err) - http.Error(w, "Failed to read Alloha response", http.StatusInternalServerError) - return - } - - log.Printf("Alloha API response body: %s", string(body)) - - var allohaResponse struct { - Status string `json:"status"` - Data struct { - Iframe string `json:"iframe"` - } `json:"data"` - } - - if err := json.Unmarshal(body, &allohaResponse); err != nil { - log.Printf("Error unmarshaling JSON: %v", err) - http.Error(w, "Invalid JSON from Alloha", http.StatusBadGateway) - return - } - - if allohaResponse.Status != "success" || allohaResponse.Data.Iframe == "" { - log.Printf("Video not found or empty iframe") - http.Error(w, "Video not found", http.StatusNotFound) - return - } - - iframeCode := allohaResponse.Data.Iframe - if !strings.Contains(iframeCode, "<") { - iframeCode = fmt.Sprintf(``, iframeCode) - } - - htmlDoc := fmt.Sprintf(`