Files
neomovies-api/internal/api/handlers.go
Foxix 612e49817c Update 16 files
- /docs/swagger.yaml
- /docs/swagger.json
- /docs/docs.go
- /internal/api/init.go
- /internal/api/models.go
- /internal/api/handlers.go
- /internal/api/utils.go
- /internal/tmdb/models.go
- /internal/tmdb/client.go
- /build.sh
- /go.mod
- /go.sum
- /main.go
- /render.yaml
- /run.sh
- /README.md
2025-01-03 18:42:44 +00:00

506 lines
16 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package api
import (
"net/http"
"github.com/gin-gonic/gin"
"neomovies-api/internal/tmdb"
)
// GetPopularMovies возвращает список популярных фильмов
// @Summary Get popular movies
// @Description Get a list of popular movies
// @Tags movies
// @Accept json
// @Produce json
// @Param page query int false "Page number (default: 1)"
// @Success 200 {object} MoviesResponse
// @Router /movies/popular [get]
func GetPopularMovies(c *gin.Context) {
page := c.DefaultQuery("page", "1")
movies, err := tmdbClient.GetPopular(page)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
// Добавляем полные URL для изображений
for i := range movies.Results {
if movies.Results[i].PosterPath != "" {
movies.Results[i].PosterPath = tmdbClient.GetImageURL(movies.Results[i].PosterPath, "w500")
}
if movies.Results[i].BackdropPath != "" {
movies.Results[i].BackdropPath = tmdbClient.GetImageURL(movies.Results[i].BackdropPath, "w1280")
}
}
c.JSON(http.StatusOK, movies)
}
// GetMovie возвращает информацию о фильме
// @Summary Get movie details
// @Description Get detailed information about a specific movie
// @Tags movies
// @Accept json
// @Produce json
// @Param id path int true "Movie ID"
// @Success 200 {object} MovieDetails
// @Router /movies/{id} [get]
func GetMovie(c *gin.Context) {
id := c.Param("id")
movie, err := tmdbClient.GetMovie(id)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
// Добавляем полные URL для изображений
if movie.PosterPath != "" {
movie.PosterPath = tmdbClient.GetImageURL(movie.PosterPath, "original")
}
if movie.BackdropPath != "" {
movie.BackdropPath = tmdbClient.GetImageURL(movie.BackdropPath, "original")
}
// Обрабатываем изображения для коллекции
if movie.BelongsToCollection != nil {
if movie.BelongsToCollection.PosterPath != "" {
movie.BelongsToCollection.PosterPath = tmdbClient.GetImageURL(movie.BelongsToCollection.PosterPath, "w500")
}
if movie.BelongsToCollection.BackdropPath != "" {
movie.BelongsToCollection.BackdropPath = tmdbClient.GetImageURL(movie.BelongsToCollection.BackdropPath, "w1280")
}
}
// Обрабатываем логотипы компаний
for i := range movie.ProductionCompanies {
if movie.ProductionCompanies[i].LogoPath != "" {
movie.ProductionCompanies[i].LogoPath = tmdbClient.GetImageURL(movie.ProductionCompanies[i].LogoPath, "w185")
}
}
c.JSON(http.StatusOK, movie)
}
// SearchMovies ищет фильмы
// @Summary Поиск фильмов
// @Description Поиск фильмов по запросу
// @Tags movies
// @Accept json
// @Produce json
// @Param query query string true "Поисковый запрос"
// @Param page query string false "Номер страницы (по умолчанию 1)"
// @Success 200 {object} SearchResponse
// @Router /movies/search [get]
func SearchMovies(c *gin.Context) {
query := c.Query("query")
if query == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "query parameter is required"})
return
}
page := c.DefaultQuery("page", "1")
// Получаем результаты поиска
results, err := tmdbClient.SearchMovies(query, page)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
// Преобразуем результаты в формат ответа
response := SearchResponse{
Page: results.Page,
TotalPages: results.TotalPages,
TotalResults: results.TotalResults,
Results: make([]MovieResponse, 0),
}
// Преобразуем каждый фильм
for _, movie := range results.Results {
// Форматируем дату
releaseDate := formatDate(movie.ReleaseDate)
// Добавляем фильм в результаты
response.Results = append(response.Results, MovieResponse{
ID: movie.ID,
Title: movie.Title,
Overview: movie.Overview,
ReleaseDate: releaseDate,
VoteAverage: movie.VoteAverage,
PosterPath: tmdbClient.GetImageURL(movie.PosterPath, "w500"),
BackdropPath: tmdbClient.GetImageURL(movie.BackdropPath, "w1280"),
})
}
c.JSON(http.StatusOK, response)
}
// GetTopRatedMovies возвращает список лучших фильмов
// @Summary Get top rated movies
// @Description Get a list of top rated movies
// @Tags movies
// @Accept json
// @Produce json
// @Param page query int false "Page number (default: 1)"
// @Success 200 {object} MoviesResponse
// @Router /movies/top-rated [get]
func GetTopRatedMovies(c *gin.Context) {
page := c.DefaultQuery("page", "1")
movies, err := tmdbClient.GetTopRated(page)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
// Добавляем полные URL для изображений
for i := range movies.Results {
if movies.Results[i].PosterPath != "" {
movies.Results[i].PosterPath = tmdbClient.GetImageURL(movies.Results[i].PosterPath, "w500")
}
if movies.Results[i].BackdropPath != "" {
movies.Results[i].BackdropPath = tmdbClient.GetImageURL(movies.Results[i].BackdropPath, "w1280")
}
}
c.JSON(http.StatusOK, movies)
}
// GetUpcomingMovies возвращает список предстоящих фильмов
// @Summary Get upcoming movies
// @Description Get a list of upcoming movies
// @Tags movies
// @Accept json
// @Produce json
// @Param page query int false "Page number (default: 1)"
// @Success 200 {object} MoviesResponse
// @Router /movies/upcoming [get]
func GetUpcomingMovies(c *gin.Context) {
page := c.DefaultQuery("page", "1")
movies, err := tmdbClient.GetUpcoming(page)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
// Добавляем полные URL для изображений
for i := range movies.Results {
if movies.Results[i].PosterPath != "" {
movies.Results[i].PosterPath = tmdbClient.GetImageURL(movies.Results[i].PosterPath, "w500")
}
if movies.Results[i].BackdropPath != "" {
movies.Results[i].BackdropPath = tmdbClient.GetImageURL(movies.Results[i].BackdropPath, "w1280")
}
}
c.JSON(http.StatusOK, movies)
}
// GetTMDBPopularMovies возвращает список популярных фильмов из TMDB
// @Summary Get TMDB popular movies
// @Description Get a list of popular movies directly from TMDB
// @Tags tmdb
// @Accept json
// @Produce json
// @Param page query int false "Page number (default: 1)"
// @Success 200 {object} TMDBMoviesResponse
// @Router /bridge/tmdb/movie/popular [get]
func GetTMDBPopularMovies(c *gin.Context) {
page := c.DefaultQuery("page", "1")
movies, err := tmdbClient.GetPopular(page)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
// Добавляем полные URL для изображений
for i := range movies.Results {
if movies.Results[i].PosterPath != "" {
movies.Results[i].PosterPath = tmdbClient.GetImageURL(movies.Results[i].PosterPath, "w500")
}
if movies.Results[i].BackdropPath != "" {
movies.Results[i].BackdropPath = tmdbClient.GetImageURL(movies.Results[i].BackdropPath, "w1280")
}
}
c.JSON(http.StatusOK, movies)
}
// GetTMDBMovie возвращает информацию о фильме из TMDB
// @Summary Get TMDB movie details
// @Description Get detailed information about a specific movie directly from TMDB
// @Tags tmdb
// @Accept json
// @Produce json
// @Param id path int true "Movie ID"
// @Success 200 {object} tmdb.Movie
// @Router /bridge/tmdb/movie/{id} [get]
func GetTMDBMovie(c *gin.Context) {
id := c.Param("id")
movie, err := tmdbClient.GetMovie(id)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, movie)
}
// GetTMDBTopRatedMovies возвращает список лучших фильмов из TMDB
// @Summary Get TMDB top rated movies
// @Description Get a list of top rated movies directly from TMDB
// @Tags tmdb
// @Accept json
// @Produce json
// @Param page query int false "Page number (default: 1)"
// @Success 200 {object} TMDBMoviesResponse
// @Router /bridge/tmdb/movie/top_rated [get]
func GetTMDBTopRatedMovies(c *gin.Context) {
page := c.DefaultQuery("page", "1")
movies, err := tmdbClient.GetTopRated(page)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
// Добавляем полные URL для изображений
for i := range movies.Results {
if movies.Results[i].PosterPath != "" {
movies.Results[i].PosterPath = tmdbClient.GetImageURL(movies.Results[i].PosterPath, "w500")
}
if movies.Results[i].BackdropPath != "" {
movies.Results[i].BackdropPath = tmdbClient.GetImageURL(movies.Results[i].BackdropPath, "w1280")
}
}
c.JSON(http.StatusOK, movies)
}
// GetTMDBUpcomingMovies возвращает список предстоящих фильмов из TMDB
// @Summary Get TMDB upcoming movies
// @Description Get a list of upcoming movies directly from TMDB
// @Tags tmdb
// @Accept json
// @Produce json
// @Param page query int false "Page number (default: 1)"
// @Success 200 {object} TMDBMoviesResponse
// @Router /bridge/tmdb/movie/upcoming [get]
func GetTMDBUpcomingMovies(c *gin.Context) {
page := c.DefaultQuery("page", "1")
movies, err := tmdbClient.GetUpcoming(page)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
// Добавляем полные URL для изображений
for i := range movies.Results {
if movies.Results[i].PosterPath != "" {
movies.Results[i].PosterPath = tmdbClient.GetImageURL(movies.Results[i].PosterPath, "w500")
}
if movies.Results[i].BackdropPath != "" {
movies.Results[i].BackdropPath = tmdbClient.GetImageURL(movies.Results[i].BackdropPath, "w1280")
}
}
c.JSON(http.StatusOK, movies)
}
// SearchTMDBMovies ищет фильмы в TMDB
// @Summary Search TMDB movies
// @Description Search for movies directly in TMDB
// @Tags tmdb
// @Accept json
// @Produce json
// @Param query query string true "Search query"
// @Param page query int false "Page number (default: 1)"
// @Success 200 {object} tmdb.MoviesResponse
// @Router /bridge/tmdb/search/movie [get]
func SearchTMDBMovies(c *gin.Context) {
query := c.Query("query")
if query == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "query parameter is required"})
return
}
page := c.DefaultQuery("page", "1")
movies, err := tmdbClient.SearchMovies(query, page)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, movies)
}
// SearchTMDBTV ищет сериалы в TMDB
// @Summary Search TMDB TV shows
// @Description Search for TV shows directly in TMDB
// @Tags tmdb
// @Accept json
// @Produce json
// @Param query query string true "Search query"
// @Param page query int false "Page number (default: 1)"
// @Success 200 {object} tmdb.TVSearchResults
// @Router /bridge/tmdb/search/tv [get]
func SearchTMDBTV(c *gin.Context) {
query := c.Query("query")
if query == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "query parameter is required"})
return
}
page := c.DefaultQuery("page", "1")
tv, err := tmdbClient.SearchTV(query, page)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, tv)
}
// DiscoverMovies возвращает список фильмов по фильтрам
// @Summary Discover movies
// @Description Get a list of movies based on filters
// @Tags tmdb
// @Accept json
// @Produce json
// @Param page query int false "Page number (default: 1)"
// @Success 200 {object} TMDBMoviesResponse
// @Router /bridge/tmdb/discover/movie [get]
func DiscoverMovies(c *gin.Context) {
page := c.DefaultQuery("page", "1")
movies, err := tmdbClient.DiscoverMovies(page)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, movies)
}
// DiscoverTV возвращает список сериалов по фильтрам
// @Summary Discover TV shows
// @Description Get a list of TV shows based on filters
// @Tags tmdb
// @Accept json
// @Produce json
// @Param page query int false "Page number (default: 1)"
// @Success 200 {object} TMDBMoviesResponse
// @Router /bridge/tmdb/discover/tv [get]
func DiscoverTV(c *gin.Context) {
page := c.DefaultQuery("page", "1")
shows, err := tmdbClient.DiscoverTV(page)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, shows)
}
// GetTMDBMovieExternalIDs возвращает внешние идентификаторы фильма
// @Summary Get TMDB movie external IDs
// @Description Get external IDs (IMDb, Facebook, Instagram, Twitter) for a specific movie
// @Tags tmdb
// @Accept json
// @Produce json
// @Param id path int true "Movie ID"
// @Success 200 {object} tmdb.ExternalIDs
// @Router /bridge/tmdb/movie/{id}/external_ids [get]
func GetTMDBMovieExternalIDs(c *gin.Context) {
id := c.Param("id")
externalIDs, err := tmdbClient.GetMovieExternalIDs(id)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, externalIDs)
}
// GetTMDBTVExternalIDs возвращает внешние идентификаторы сериала
// @Summary Get TMDB TV show external IDs
// @Description Get external IDs (IMDb, Facebook, Instagram, Twitter) for a specific TV show
// @Tags tmdb
// @Accept json
// @Produce json
// @Param id path int true "TV Show ID"
// @Success 200 {object} tmdb.ExternalIDs
// @Router /bridge/tmdb/tv/{id}/external_ids [get]
func GetTMDBTVExternalIDs(c *gin.Context) {
id := c.Param("id")
externalIDs, err := tmdbClient.GetTVExternalIDs(id)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, externalIDs)
}
// HealthCheck godoc
// @Summary Проверка работоспособности API
// @Description Проверяет, что API работает
// @Tags health
// @Produce json
// @Success 200 {object} map[string]string
// @Router /health [get]
func HealthCheck(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"status": "ok",
})
}
// InitTMDBClientWithProxy инициализирует TMDB клиент с прокси
func InitTMDBClientWithProxy(apiKey string, proxyAddr string) error {
tmdbClient = tmdb.NewClient(apiKey)
return tmdbClient.SetSOCKS5Proxy(proxyAddr)
}
// Admin handlers
// GetAdminMovies возвращает список фильмов для админа
func GetAdminMovies(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"message": "Admin movies list"})
}
// ToggleMovieVisibility переключает видимость фильма
func ToggleMovieVisibility(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"message": "Movie visibility toggled"})
}
// GetUsers возвращает список пользователей
func GetUsers(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"message": "Users list"})
}
// CreateUser создает нового пользователя
func CreateUser(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"message": "User created"})
}
// ToggleAdmin переключает права администратора
func ToggleAdmin(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"message": "Admin status toggled"})
}
// SendVerification отправляет код верификации
func SendVerification(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"message": "Verification code sent"})
}
// VerifyCode проверяет код верификации
func VerifyCode(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"message": "Code verified"})
}