package web import ( "errors" "net/http" "gitea.kazu634.com/kazu634/tver/internal/store" ) type episodeActionView struct { ID, Genre, Status, StatusText string } func statusText(status string) string { switch status { case "queued": return "待機中" case "running": return "ダウンロード中" case "succeeded": return "完了" case "failed": return "失敗" case "canceled": return "取り消し" default: return "" } } func (s *server) enqueue(w http.ResponseWriter, r *http.Request) { genre, id, ok := episodeForm(w, r) if !ok { return } ep, found := s.cachedEpisode(genre, id) if !found { http.Error(w, "新着キャッシュにエピソードがありません。新着を再表示してください", http.StatusNotFound) return } job, _, err := s.jobs.Enqueue(r.Context(), storeEpisode(ep), "manual") if err != nil { s.logger.Printf("待ち行列への登録に失敗: %v", err) http.Error(w, "待ち行列に登録できませんでした", http.StatusInternalServerError) return } s.episodeActionResponse(w, r, episodeActionView{ID: id, Genre: genre, Status: job.Status, StatusText: statusText(job.Status)}) } func (s *server) retryEpisode(w http.ResponseWriter, r *http.Request) { genre, id, ok := episodeForm(w, r) if !ok { return } if _, found := s.cachedEpisode(genre, id); !found { http.Error(w, "新着キャッシュにエピソードがありません。新着を再表示してください", http.StatusNotFound) return } if err := s.jobs.RetryEpisode(r.Context(), id); err != nil { if errors.Is(err, store.ErrInvalidTransition) { http.Error(w, "再試行できる状態ではありません", http.StatusConflict) } else { s.logger.Printf("ジョブの再試行に失敗: %v", err) http.Error(w, "再試行できませんでした", http.StatusInternalServerError) } return } s.episodeActionResponse(w, r, episodeActionView{ID: id, Genre: genre, Status: "queued", StatusText: statusText("queued")}) } func episodeForm(w http.ResponseWriter, r *http.Request) (string, string, bool) { if err := r.ParseForm(); err != nil { http.Error(w, "フォームを読み取れませんでした", http.StatusBadRequest) return "", "", false } genre, id := r.Form.Get("genre"), r.Form.Get("episode_id") if (genre != "drama" && genre != "variety") || id == "" { http.Error(w, "ジャンルまたはエピソード ID が不正です", http.StatusBadRequest) return "", "", false } return genre, id, true } func (s *server) episodeActionResponse(w http.ResponseWriter, r *http.Request, view episodeActionView) { if r.Header.Get("HX-Request") != "true" { http.Redirect(w, r, "/?genre="+view.Genre, http.StatusSeeOther) return } s.render(w, "episode_action", view) }