@@ -35,23 +35,73 @@ func generateFilmPath(title string, year int) string {
3535 return "/films/" + cleaned + "/"
3636}
3737
38+ func updateOrCreateFilmPoster (filmID int , filmTitle , posterPath string ) error {
39+ if posterPath == "" {
40+ return fmt .Errorf ("poster path is empty" )
41+ }
42+
43+ mediaRelations , err := db .GetMediaRelationsForEntity ("film" , filmID )
44+ if err != nil {
45+ return fmt .Errorf ("failed to get media relations: %w" , err )
46+ }
47+
48+ for _ , rel := range mediaRelations {
49+ if rel .Role != nil && * rel .Role == "poster" {
50+ if err := db .DeleteMediaRelation ("film" , filmID , rel .Path ); err != nil {
51+ return fmt .Errorf ("failed to delete existing media relation: %w" , err )
52+ }
53+ if err := db .DeleteMedia (rel .MediaID ); err != nil {
54+ return fmt .Errorf ("failed to delete existing media: %w" , err )
55+ }
56+ break
57+ }
58+ }
59+
60+ posterData , err := tmdb .DownloadPoster (* tmdbAPIKey , posterPath , 500 )
61+ if err != nil {
62+ return fmt .Errorf ("failed to download poster: %w" , err )
63+ }
64+
65+ ext := ".jpg"
66+ if posterData .ContentType == "image/png" {
67+ ext = ".png"
68+ }
69+ filename := fmt .Sprintf ("%d%s" , filmID , ext )
70+ mediaRelationsPath := fmt .Sprintf ("/films/%d/poster%s" , filmID , ext )
71+
72+ mediaID , err := db .CreateMedia (posterData .ContentType , filename , posterData .Data , & posterData .Width , & posterData .Height , nil )
73+ if err != nil {
74+ return fmt .Errorf ("failed to create media: %w" , err )
75+ }
76+
77+ description := fmt .Sprintf ("Poster of %s" , filmTitle )
78+ caption := filmTitle
79+ role := "poster"
80+ if err := db .CreateMediaRelation ("film" , filmID , mediaID , mediaRelationsPath , & caption , & description , & role ); err != nil {
81+ return fmt .Errorf ("failed to create media relation: %w" , err )
82+ }
83+
84+ return nil
85+ }
86+
3887var (
3988 tmdbAPIKey = flag .String ("tmdb-api-key" , "" , "TMDB API key" )
4089)
4190
4291func ListFilmsHandler () func (http.ResponseWriter , * http.Request ) {
4392 return func (w http.ResponseWriter , r * http.Request ) {
44- films , err := db .GetAllFilmsWithReviews ()
93+ films , err := db .GetAllFilmsWithReviewsAndPosters ()
4594 if err != nil {
95+ slog .Error ("Failed to retrieve films" , "error" , err )
4696 http .Error (w , "Failed to retrieve films" , http .StatusInternalServerError )
4797 return
4898 }
4999
50100 filmSummaries := make ([]templates.FilmSummary , len (films ))
51101 for i , film := range films {
52102 year := ""
53- if film .Year != nil {
54- year = strconv .Itoa (* film .Year )
103+ if film .Film . Year != nil {
104+ year = strconv .Itoa (* film .Film . Year )
55105 }
56106
57107 rating := ""
@@ -60,11 +110,14 @@ func ListFilmsHandler() func(http.ResponseWriter, *http.Request) {
60110 }
61111
62112 filmSummaries [i ] = templates.FilmSummary {
63- ID : film .ID ,
64- Title : film .Title ,
65- Year : year ,
66- Rating : rating ,
67- Published : film .Published ,
113+ ID : film .Film .ID ,
114+ Title : film .Film .Title ,
115+ Year : year ,
116+ Rating : rating ,
117+ Published : film .Film .Published ,
118+ PosterMediaID : film .PosterMediaID ,
119+ ReviewCount : film .ReviewCount ,
120+ LastWatched : film .LastWatched ,
68121 }
69122 }
70123
@@ -173,31 +226,8 @@ func CreateFilmHandler() func(http.ResponseWriter, *http.Request) {
173226 return
174227 }
175228
176- if posterPath != "" {
177- posterData , err := tmdb .DownloadPoster (* tmdbAPIKey , posterPath , 500 )
178- if err != nil {
179- slog .Error ("Failed to download poster" , "error" , err )
180- } else {
181- ext := ".jpg"
182- if posterData .ContentType == "image/png" {
183- ext = ".png"
184- }
185- filename := fmt .Sprintf ("%d%s" , filmID , ext )
186- mediaRelationsPath := fmt .Sprintf ("/films/%d/poster%s" , filmID , ext )
187-
188- mediaID , err := db .CreateMedia (posterData .ContentType , filename , posterData .Data , & posterData .Width , & posterData .Height , nil )
189- if err != nil {
190- slog .Error ("Failed to create media" , "error" , err )
191- } else {
192- description := fmt .Sprintf ("Poster of %s" , movie .Title )
193- caption := movie .Title
194- role := "poster"
195- err := db .CreateMediaRelation ("film" , filmID , mediaID , mediaRelationsPath , & caption , & description , & role )
196- if err != nil {
197- slog .Error ("Failed to create media relation" , "error" , err )
198- }
199- }
200- }
229+ if err := updateOrCreateFilmPoster (filmID , movie .Title , posterPath ); err != nil {
230+ slog .Error ("Failed to update film poster" , "error" , err )
201231 }
202232
203233 reviewID , err := db .CreateFilmReview (filmID , 0 , time .Now (), false , false , false , "" )
@@ -368,6 +398,49 @@ func DeleteFilmHandler() func(http.ResponseWriter, *http.Request) {
368398 }
369399}
370400
401+ func FetchFilmPosterHandler () func (http.ResponseWriter , * http.Request ) {
402+ return func (w http.ResponseWriter , r * http.Request ) {
403+ if * tmdbAPIKey == "" {
404+ http .Error (w , "TMDB API key not configured" , http .StatusInternalServerError )
405+ return
406+ }
407+
408+ idStr := r .PathValue ("id" )
409+ id , err := strconv .Atoi (idStr )
410+ if err != nil {
411+ http .Error (w , "Invalid film ID" , http .StatusBadRequest )
412+ return
413+ }
414+
415+ film , err := db .GetFilmByID (id )
416+ if err != nil {
417+ slog .Error ("Failed to get film" , "error" , err )
418+ http .Error (w , "Film not found" , http .StatusNotFound )
419+ return
420+ }
421+
422+ if film .TMDBID == nil {
423+ http .Error (w , "Film has no TMDB ID" , http .StatusBadRequest )
424+ return
425+ }
426+
427+ movie , err := tmdb .GetMovie (* tmdbAPIKey , * film .TMDBID )
428+ if err != nil {
429+ slog .Error ("Failed to get movie from TMDB" , "error" , err )
430+ http .Error (w , "Failed to fetch movie from TMDB" , http .StatusInternalServerError )
431+ return
432+ }
433+
434+ if err := updateOrCreateFilmPoster (id , film .Title , movie .PosterPath ); err != nil {
435+ slog .Error ("Failed to update film poster" , "error" , err )
436+ http .Error (w , "Failed to update film poster" , http .StatusInternalServerError )
437+ return
438+ }
439+
440+ http .Redirect (w , r , fmt .Sprintf ("/films/edit/%d" , id ), http .StatusSeeOther )
441+ }
442+ }
443+
371444func GetFilmsWithReviewsHandler () func (http.ResponseWriter , * http.Request ) {
372445 return func (w http.ResponseWriter , r * http.Request ) {
373446 films , err := db .GetAllFilmsWithReviews ()
0 commit comments