Files
seanime-docker/seanime-2.9.10/internal/handlers/local.go
2025-09-20 14:08:38 +01:00

227 lines
5.8 KiB
Go

package handlers
import (
"seanime/internal/util"
"strconv"
"github.com/labstack/echo/v4"
)
// HandleSetOfflineMode
//
// @summary sets the offline mode.
// @desc Returns true if the offline mode is active, false otherwise.
// @route /api/v1/local/offline [POST]
// @returns bool
func (h *Handler) HandleSetOfflineMode(c echo.Context) error {
type body struct {
Enabled bool `json:"enabled"`
}
var b body
if err := c.Bind(&b); err != nil {
return h.RespondWithError(c, err)
}
h.App.SetOfflineMode(b.Enabled)
return h.RespondWithData(c, b.Enabled)
}
// HandleLocalGetTrackedMediaItems
//
// @summary gets all tracked media.
// @route /api/v1/local/track [GET]
// @returns []local.TrackedMediaItem
func (h *Handler) HandleLocalGetTrackedMediaItems(c echo.Context) error {
tracked := h.App.LocalManager.GetTrackedMediaItems()
return h.RespondWithData(c, tracked)
}
// HandleLocalAddTrackedMedia
//
// @summary adds one or multiple media to be tracked for offline sync.
// @route /api/v1/local/track [POST]
// @returns bool
func (h *Handler) HandleLocalAddTrackedMedia(c echo.Context) error {
type body struct {
Media []struct {
MediaId int `json:"mediaId"`
Type string `json:"type"`
} `json:"media"`
}
var b body
if err := c.Bind(&b); err != nil {
return h.RespondWithError(c, err)
}
var err error
for _, m := range b.Media {
switch m.Type {
case "anime":
err = h.App.LocalManager.TrackAnime(m.MediaId)
case "manga":
err = h.App.LocalManager.TrackManga(m.MediaId)
}
}
if err != nil {
return h.RespondWithError(c, err)
}
return h.RespondWithData(c, true)
}
// HandleLocalRemoveTrackedMedia
//
// @summary remove media from being tracked for offline sync.
// @desc This will remove anime from being tracked for offline sync and delete any associated data.
// @route /api/v1/local/track [DELETE]
// @returns bool
func (h *Handler) HandleLocalRemoveTrackedMedia(c echo.Context) error {
type body struct {
MediaId int `json:"mediaId"`
Type string `json:"type"`
}
var b body
if err := c.Bind(&b); err != nil {
return h.RespondWithError(c, err)
}
var err error
switch b.Type {
case "anime":
err = h.App.LocalManager.UntrackAnime(b.MediaId)
case "manga":
err = h.App.LocalManager.UntrackManga(b.MediaId)
}
if err != nil {
return h.RespondWithError(c, err)
}
return h.RespondWithData(c, true)
}
// HandleLocalGetIsMediaTracked
//
// @summary checks if media is being tracked for offline sync.
// @route /api/v1/local/track/{id}/{type} [GET]
// @param id - int - true - "AniList anime media ID"
// @param type - string - true - "Type of media (anime/manga)"
// @returns bool
func (h *Handler) HandleLocalGetIsMediaTracked(c echo.Context) error {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
return h.RespondWithError(c, err)
}
kind := c.Param("type")
tracked := h.App.LocalManager.IsMediaTracked(id, kind)
return h.RespondWithData(c, tracked)
}
// HandleLocalSyncData
//
// @summary syncs local data with AniList.
// @route /api/v1/local/local [POST]
// @returns bool
func (h *Handler) HandleLocalSyncData(c echo.Context) error {
// Do not allow syncing if the user is simulated
if h.App.GetUser().IsSimulated {
return h.RespondWithData(c, true)
}
err := h.App.LocalManager.SynchronizeLocal()
if err != nil {
return h.RespondWithError(c, err)
}
if h.App.Settings.GetLibrary().AutoSaveCurrentMediaOffline {
go func() {
added, _ := h.App.LocalManager.AutoTrackCurrentMedia()
if added {
_ = h.App.LocalManager.SynchronizeLocal()
}
}()
}
return h.RespondWithData(c, true)
}
// HandleLocalGetSyncQueueState
//
// @summary gets the current sync queue state.
// @desc This will return the list of media that are currently queued for syncing.
// @route /api/v1/local/queue [GET]
// @returns local.QueueState
func (h *Handler) HandleLocalGetSyncQueueState(c echo.Context) error {
return h.RespondWithData(c, h.App.LocalManager.GetSyncer().GetQueueState())
}
// HandleLocalSyncAnilistData
//
// @summary syncs AniList data with local.
// @route /api/v1/local/anilist [POST]
// @returns bool
func (h *Handler) HandleLocalSyncAnilistData(c echo.Context) error {
err := h.App.LocalManager.SynchronizeAnilist()
if err != nil {
return h.RespondWithError(c, err)
}
return h.RespondWithData(c, true)
}
// HandleLocalSetHasLocalChanges
//
// @summary sets the flag to determine if there are local changes that need to be synced with AniList.
// @route /api/v1/local/updated [POST]
// @returns bool
func (h *Handler) HandleLocalSetHasLocalChanges(c echo.Context) error {
type body struct {
Updated bool `json:"updated"`
}
var b body
if err := c.Bind(&b); err != nil {
return h.RespondWithError(c, err)
}
h.App.LocalManager.SetHasLocalChanges(b.Updated)
return h.RespondWithData(c, true)
}
// HandleLocalGetHasLocalChanges
//
// @summary gets the flag to determine if there are local changes that need to be synced with AniList.
// @route /api/v1/local/updated [GET]
// @returns bool
func (h *Handler) HandleLocalGetHasLocalChanges(c echo.Context) error {
updated := h.App.LocalManager.HasLocalChanges()
return h.RespondWithData(c, updated)
}
// HandleLocalGetLocalStorageSize
//
// @summary gets the size of the local storage in a human-readable format.
// @route /api/v1/local/storage/size [GET]
// @returns string
func (h *Handler) HandleLocalGetLocalStorageSize(c echo.Context) error {
size := h.App.LocalManager.GetLocalStorageSize()
return h.RespondWithData(c, util.Bytes(uint64(size)))
}
// HandleLocalSyncSimulatedDataToAnilist
//
// @summary syncs the simulated data to AniList.
// @route /api/v1/local/sync-simulated-to-anilist [POST]
// @returns bool
func (h *Handler) HandleLocalSyncSimulatedDataToAnilist(c echo.Context) error {
err := h.App.LocalManager.SynchronizeSimulatedCollectionToAnilist()
if err != nil {
return h.RespondWithError(c, err)
}
return h.RespondWithData(c, true)
}