package handlers import ( "errors" "path/filepath" "seanime/internal/database/db_bridge" "seanime/internal/library/anime" "strconv" "github.com/labstack/echo/v4" ) // HandleRunAutoDownloader // // @summary tells the AutoDownloader to check for new episodes if enabled. // @desc This will run the AutoDownloader if it is enabled. // @desc It does nothing if the AutoDownloader is disabled. // @route /api/v1/auto-downloader/run [POST] // @returns bool func (h *Handler) HandleRunAutoDownloader(c echo.Context) error { h.App.AutoDownloader.Run() return h.RespondWithData(c, true) } // HandleGetAutoDownloaderRule // // @summary returns the rule with the given DB id. // @desc This is used to get a specific rule, useful for editing. // @route /api/v1/auto-downloader/rule/{id} [GET] // @param id - int - true - "The DB id of the rule" // @returns anime.AutoDownloaderRule func (h *Handler) HandleGetAutoDownloaderRule(c echo.Context) error { id, err := strconv.Atoi(c.Param("id")) if err != nil { return h.RespondWithError(c, errors.New("invalid id")) } rule, err := db_bridge.GetAutoDownloaderRule(h.App.Database, uint(id)) if err != nil { return h.RespondWithError(c, err) } return h.RespondWithData(c, rule) } // HandleGetAutoDownloaderRulesByAnime // // @summary returns the rules with the given media id. // @route /api/v1/auto-downloader/rule/anime/{id} [GET] // @param id - int - true - "The AniList anime id of the rules" // @returns []anime.AutoDownloaderRule func (h *Handler) HandleGetAutoDownloaderRulesByAnime(c echo.Context) error { id, err := strconv.Atoi(c.Param("id")) if err != nil { return h.RespondWithError(c, errors.New("invalid id")) } rules := db_bridge.GetAutoDownloaderRulesByMediaId(h.App.Database, id) return h.RespondWithData(c, rules) } // HandleGetAutoDownloaderRules // // @summary returns all rules. // @desc This is used to list all rules. It returns an empty slice if there are no rules. // @route /api/v1/auto-downloader/rules [GET] // @returns []anime.AutoDownloaderRule func (h *Handler) HandleGetAutoDownloaderRules(c echo.Context) error { rules, err := db_bridge.GetAutoDownloaderRules(h.App.Database) if err != nil { return h.RespondWithError(c, err) } return h.RespondWithData(c, rules) } // HandleCreateAutoDownloaderRule // // @summary creates a new rule. // @desc The body should contain the same fields as entities.AutoDownloaderRule. // @desc It returns the created rule. // @route /api/v1/auto-downloader/rule [POST] // @returns anime.AutoDownloaderRule func (h *Handler) HandleCreateAutoDownloaderRule(c echo.Context) error { type body struct { Enabled bool `json:"enabled"` MediaId int `json:"mediaId"` ReleaseGroups []string `json:"releaseGroups"` Resolutions []string `json:"resolutions"` AdditionalTerms []string `json:"additionalTerms"` ComparisonTitle string `json:"comparisonTitle"` TitleComparisonType anime.AutoDownloaderRuleTitleComparisonType `json:"titleComparisonType"` EpisodeType anime.AutoDownloaderRuleEpisodeType `json:"episodeType"` EpisodeNumbers []int `json:"episodeNumbers,omitempty"` Destination string `json:"destination"` } var b body if err := c.Bind(&b); err != nil { return h.RespondWithError(c, err) } if b.Destination == "" { return h.RespondWithError(c, errors.New("destination is required")) } if !filepath.IsAbs(b.Destination) { return h.RespondWithError(c, errors.New("destination must be an absolute path")) } rule := &anime.AutoDownloaderRule{ Enabled: b.Enabled, MediaId: b.MediaId, ReleaseGroups: b.ReleaseGroups, Resolutions: b.Resolutions, ComparisonTitle: b.ComparisonTitle, TitleComparisonType: b.TitleComparisonType, EpisodeType: b.EpisodeType, EpisodeNumbers: b.EpisodeNumbers, Destination: b.Destination, AdditionalTerms: b.AdditionalTerms, } if err := db_bridge.InsertAutoDownloaderRule(h.App.Database, rule); err != nil { return h.RespondWithError(c, err) } return h.RespondWithData(c, rule) } // HandleUpdateAutoDownloaderRule // // @summary updates a rule. // @desc The body should contain the same fields as entities.AutoDownloaderRule. // @desc It returns the updated rule. // @route /api/v1/auto-downloader/rule [PATCH] // @returns anime.AutoDownloaderRule func (h *Handler) HandleUpdateAutoDownloaderRule(c echo.Context) error { type body struct { Rule *anime.AutoDownloaderRule `json:"rule"` } var b body if err := c.Bind(&b); err != nil { return h.RespondWithError(c, err) } if b.Rule == nil { return h.RespondWithError(c, errors.New("invalid rule")) } if b.Rule.DbID == 0 { return h.RespondWithError(c, errors.New("invalid id")) } // Update the rule based on its DbID (primary key) if err := db_bridge.UpdateAutoDownloaderRule(h.App.Database, b.Rule.DbID, b.Rule); err != nil { return h.RespondWithError(c, err) } return h.RespondWithData(c, b.Rule) } // HandleDeleteAutoDownloaderRule // // @summary deletes a rule. // @desc It returns 'true' if the rule was deleted. // @route /api/v1/auto-downloader/rule/{id} [DELETE] // @param id - int - true - "The DB id of the rule" // @returns bool func (h *Handler) HandleDeleteAutoDownloaderRule(c echo.Context) error { id, err := strconv.Atoi(c.Param("id")) if err != nil { return h.RespondWithError(c, errors.New("invalid id")) } if err := db_bridge.DeleteAutoDownloaderRule(h.App.Database, uint(id)); err != nil { return h.RespondWithError(c, err) } return h.RespondWithData(c, true) } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // HandleGetAutoDownloaderItems // // @summary returns all queued items. // @desc Queued items are episodes that are downloaded but not scanned or not yet downloaded. // @desc The AutoDownloader uses these items in order to not download the same episode twice. // @route /api/v1/auto-downloader/items [GET] // @returns []models.AutoDownloaderItem func (h *Handler) HandleGetAutoDownloaderItems(c echo.Context) error { rules, err := h.App.Database.GetAutoDownloaderItems() if err != nil { return h.RespondWithError(c, err) } return h.RespondWithData(c, rules) } // HandleDeleteAutoDownloaderItem // // @summary delete a queued item. // @desc This is used to remove a queued item from the list. // @desc Returns 'true' if the item was deleted. // @route /api/v1/auto-downloader/item [DELETE] // @param id - int - true - "The DB id of the item" // @returns bool func (h *Handler) HandleDeleteAutoDownloaderItem(c echo.Context) error { type body struct { ID uint `json:"id"` } var b body if err := c.Bind(&b); err != nil { return h.RespondWithError(c, err) } if err := h.App.Database.DeleteAutoDownloaderItem(b.ID); err != nil { return h.RespondWithError(c, err) } return h.RespondWithData(c, true) }