diff --git a/CHANGELOG.md b/CHANGELOG.md index 4dba5099..21ec6582 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,10 @@ All notable changes to this project will be documented in this file. ## v2.6.1 +- ⚡️ Anime library: Filtering by year now takes into account the season year +- ⚡️ Torrent streaming: Custom stream URL address setting #182 - 🦺 Scanner: Fixed duplicated files due to incorrect path comparison +- 🦺 Use AniList season year instead of start year for media cards #193 - 🏗️ Issue recorder: Increase data cap limit ## v2.6.0 diff --git a/codegen/generated/public_structs.json b/codegen/generated/public_structs.json index 4c3b1b66..52358c37 100644 --- a/codegen/generated/public_structs.json +++ b/codegen/generated/public_structs.json @@ -123,6 +123,15 @@ "public": true, "comments": [] }, + { + "name": "SeasonYear", + "jsonName": "seasonYear", + "goType": "int", + "typescriptType": "number", + "required": false, + "public": true, + "comments": [] + }, { "name": "BannerImage", "jsonName": "bannerImage", @@ -321,6 +330,15 @@ "public": true, "comments": [] }, + { + "name": "SeasonYear", + "jsonName": "seasonYear", + "goType": "int", + "typescriptType": "number", + "required": false, + "public": true, + "comments": [] + }, { "name": "Type", "jsonName": "type", @@ -28005,6 +28023,15 @@ "required": true, "public": true, "comments": [] + }, + { + "name": "StreamUrlAddress", + "jsonName": "streamUrlAddress", + "goType": "string", + "typescriptType": "string", + "required": true, + "public": true, + "comments": [] } ], "comments": [], diff --git a/internal/api/anilist/client_gen.go b/internal/api/anilist/client_gen.go index fdd96eb3..192c3bda 100644 --- a/internal/api/anilist/client_gen.go +++ b/internal/api/anilist/client_gen.go @@ -49,6 +49,7 @@ type BaseAnime struct { Season *MediaSeason "json:\"season,omitempty\" graphql:\"season\"" Type *MediaType "json:\"type,omitempty\" graphql:\"type\"" Format *MediaFormat "json:\"format,omitempty\" graphql:\"format\"" + SeasonYear *int "json:\"seasonYear,omitempty\" graphql:\"seasonYear\"" BannerImage *string "json:\"bannerImage,omitempty\" graphql:\"bannerImage\"" Episodes *int "json:\"episodes,omitempty\" graphql:\"episodes\"" Synonyms []*string "json:\"synonyms,omitempty\" graphql:\"synonyms\"" @@ -108,6 +109,12 @@ func (t *BaseAnime) GetFormat() *MediaFormat { } return t.Format } +func (t *BaseAnime) GetSeasonYear() *int { + if t == nil { + t = &BaseAnime{} + } + return t.SeasonYear +} func (t *BaseAnime) GetBannerImage() *string { if t == nil { t = &BaseAnime{} @@ -205,6 +212,7 @@ type CompleteAnime struct { SiteURL *string "json:\"siteUrl,omitempty\" graphql:\"siteUrl\"" Status *MediaStatus "json:\"status,omitempty\" graphql:\"status\"" Season *MediaSeason "json:\"season,omitempty\" graphql:\"season\"" + SeasonYear *int "json:\"seasonYear,omitempty\" graphql:\"seasonYear\"" Type *MediaType "json:\"type,omitempty\" graphql:\"type\"" Format *MediaFormat "json:\"format,omitempty\" graphql:\"format\"" BannerImage *string "json:\"bannerImage,omitempty\" graphql:\"bannerImage\"" @@ -255,6 +263,12 @@ func (t *CompleteAnime) GetSeason() *MediaSeason { } return t.Season } +func (t *CompleteAnime) GetSeasonYear() *int { + if t == nil { + t = &CompleteAnime{} + } + return t.SeasonYear +} func (t *CompleteAnime) GetType() *MediaType { if t == nil { t = &CompleteAnime{} @@ -6920,6 +6934,7 @@ fragment baseAnime on Media { season type format + seasonYear bannerImage episodes synonyms @@ -7018,6 +7033,7 @@ fragment completeAnime on Media { siteUrl status(version: 2) season + seasonYear type format bannerImage @@ -7078,6 +7094,7 @@ fragment baseAnime on Media { season type format + seasonYear bannerImage episodes synonyms @@ -7152,6 +7169,7 @@ fragment baseAnime on Media { season type format + seasonYear bannerImage episodes synonyms @@ -7226,6 +7244,7 @@ fragment baseAnime on Media { season type format + seasonYear bannerImage episodes synonyms @@ -7305,6 +7324,7 @@ fragment baseAnime on Media { season type format + seasonYear bannerImage episodes synonyms @@ -7386,6 +7406,7 @@ fragment completeAnime on Media { siteUrl status(version: 2) season + seasonYear type format bannerImage @@ -7446,6 +7467,7 @@ fragment baseAnime on Media { season type format + seasonYear bannerImage episodes synonyms @@ -7649,6 +7671,7 @@ fragment baseAnime on Media { season type format + seasonYear bannerImage episodes synonyms @@ -7732,6 +7755,7 @@ fragment baseAnime on Media { season type format + seasonYear bannerImage episodes synonyms @@ -7831,6 +7855,7 @@ fragment baseAnime on Media { season type format + seasonYear bannerImage episodes synonyms @@ -8627,6 +8652,7 @@ fragment baseAnime on Media { season type format + seasonYear bannerImage episodes synonyms diff --git a/internal/api/anilist/media_helper.go b/internal/api/anilist/media_helper.go index 2039085d..e1093570 100644 --- a/internal/api/anilist/media_helper.go +++ b/internal/api/anilist/media_helper.go @@ -489,6 +489,7 @@ func (m *CompleteAnime) ToBaseAnime() *BaseAnime { Synonyms: m.GetSynonyms(), BannerImage: m.GetBannerImage(), Season: m.GetSeason(), + SeasonYear: m.GetSeasonYear(), Type: m.GetType(), IsAdult: m.GetIsAdult(), CountryOfOrigin: m.GetCountryOfOrigin(), diff --git a/internal/api/anilist/queries/anime.graphql b/internal/api/anilist/queries/anime.graphql index 2b28c0ce..f5a67ba1 100644 --- a/internal/api/anilist/queries/anime.graphql +++ b/internal/api/anilist/queries/anime.graphql @@ -275,6 +275,7 @@ fragment baseAnime on Media { season type format + seasonYear bannerImage episodes synonyms @@ -324,6 +325,7 @@ fragment completeAnime on Media { siteUrl status(version: 2) season + seasonYear type format bannerImage diff --git a/internal/core/modules.go b/internal/core/modules.go index 4959dbbd..57a401cb 100644 --- a/internal/core/modules.go +++ b/internal/core/modules.go @@ -453,6 +453,7 @@ func (a *App) InitOrRefreshTorrentstreamSettings() { StreamingServerHost: "0.0.0.0", StreamingServerPort: 43214, IncludeInLibrary: false, + StreamUrlAddress: "", }) if err != nil { a.Logger.Error().Err(err).Msg("app: Failed to initialize mediastream module") diff --git a/internal/database/models/models.go b/internal/database/models/models.go index 3dfff2d6..280daa00 100644 --- a/internal/database/models/models.go +++ b/internal/database/models/models.go @@ -330,6 +330,8 @@ type TorrentstreamSettings struct { StreamingServerPort int `gorm:"column:streaming_server_port" json:"streamingServerPort"` // UNUSED, LEGACY //FallbackToTorrentStreamingView bool `gorm:"column:fallback_to_torrent_streaming_view" json:"fallbackToTorrentStreamingView"` // DEPRECATED IncludeInLibrary bool `gorm:"column:include_in_library" json:"includeInLibrary"` + // v2.6+ + StreamUrlAddress string `gorm:"column:stream_url_address" json:"streamUrlAddress"` } type TorrentstreamHistory struct { diff --git a/internal/torrentstream/client.go b/internal/torrentstream/client.go index e3411fe1..1d910b84 100644 --- a/internal/torrentstream/client.go +++ b/internal/torrentstream/client.go @@ -240,7 +240,14 @@ func (c *Client) GetStreamingUrl() string { return "" } address := fmt.Sprintf("%s:%d", c.repository.settings.MustGet().Host, c.repository.settings.MustGet().Port) - return fmt.Sprintf("http://%s/api/v1/torrentstream/stream/%s", address, url.PathEscape(c.currentFile.MustGet().DisplayPath())) + if c.repository.settings.MustGet().StreamUrlAddress != "" { + address = c.repository.settings.MustGet().StreamUrlAddress + } + _url := fmt.Sprintf("http://%s/api/v1/torrentstream/stream/%s", address, url.PathEscape(c.currentFile.MustGet().DisplayPath())) + if strings.HasPrefix(_url, "http://http") { + _url = strings.Replace(_url, "http://http", "http", 1) + } + return _url } func (c *Client) AddTorrent(id string) (*torrent.Torrent, error) { diff --git a/seanime-web/src/api/generated/types.ts b/seanime-web/src/api/generated/types.ts index 4d17ffae..9787ec05 100644 --- a/seanime-web/src/api/generated/types.ts +++ b/seanime-web/src/api/generated/types.ts @@ -398,6 +398,7 @@ export type AL_BaseAnime = { season?: AL_MediaSeason type?: AL_MediaType format?: AL_MediaFormat + seasonYear?: number bannerImage?: string episodes?: number synonyms?: Array @@ -2872,6 +2873,7 @@ export type Models_TorrentstreamSettings = { */ streamingServerPort: number includeInLibrary: boolean + streamUrlAddress: string id: number createdAt?: string updatedAt?: string diff --git a/seanime-web/src/app/(main)/_features/global-search/global-search.tsx b/seanime-web/src/app/(main)/_features/global-search/global-search.tsx index d51ef6fe..656ced98 100644 --- a/seanime-web/src/app/(main)/_features/global-search/global-search.tsx +++ b/seanime-web/src/app/(main)/_features/global-search/global-search.tsx @@ -213,10 +213,8 @@ export function GlobalSearch() {

{activeOption.format}{activeOption.season ? ` - ${capitalize(activeOption.season)} ` - : " - "}{activeOption.startDate?.year - ? new Intl.DateTimeFormat("en-US", { year: "numeric" }) - .format(new Date(activeOption.startDate?.year || 0, - activeOption.startDate?.month || 0)) + : " - "}{activeOption.seasonYear + ? activeOption.seasonYear : "-"}

diff --git a/seanime-web/src/app/(main)/_features/media/_components/media-entry-card.tsx b/seanime-web/src/app/(main)/_features/media/_components/media-entry-card.tsx index a56b6b44..39714e91 100644 --- a/seanime-web/src/app/(main)/_features/media/_components/media-entry-card.tsx +++ b/seanime-web/src/app/(main)/_features/media/_components/media-entry-card.tsx @@ -180,7 +180,7 @@ export function MediaEntryCard(props: MediaEntryCar (props: MediaEntryCar diff --git a/seanime-web/src/app/(main)/settings/_containers/torrentstream-settings.tsx b/seanime-web/src/app/(main)/settings/_containers/torrentstream-settings.tsx index afb12042..5be8b71d 100644 --- a/seanime-web/src/app/(main)/settings/_containers/torrentstream-settings.tsx +++ b/seanime-web/src/app/(main)/settings/_containers/torrentstream-settings.tsx @@ -19,6 +19,7 @@ const torrentstreamSchema = defineSchema(({ z }) => z.object({ torrentClientPort: z.number(), preferredResolution: z.string(), includeInLibrary: z.boolean(), + streamUrlAddress: z.string().optional().default(""), })) @@ -68,6 +69,7 @@ export function TorrentstreamSettings(props: TorrentstreamSettingsProps) { torrentClientPort: settings.torrentClientPort, preferredResolution: settings.preferredResolution || "-", includeInLibrary: settings.includeInLibrary, + streamUrlAddress: settings.streamUrlAddress || "", }} stackClass="space-y-6" > @@ -160,6 +162,15 @@ export function TorrentstreamSettings(props: TorrentstreamSettingsProps) { label="Disable IPv6" /> + + + +
diff --git a/seanime-web/src/lib/helpers/filtering.ts b/seanime-web/src/lib/helpers/filtering.ts index f98c22be..56ea8d1c 100644 --- a/seanime-web/src/lib/helpers/filtering.ts +++ b/seanime-web/src/lib/helpers/filtering.ts @@ -109,7 +109,9 @@ export function filterListEntries n.media?.status === params.status) // Filter by year - if (!!arr && !!params.year) arr = arr.filter(n => n.media?.startDate?.year === Number(params.year)) + if (!!arr && !!params.year) arr = arr.filter(n => (n.media as AL_BaseAnime)?.seasonYear ? + ((n.media as AL_BaseAnime)?.seasonYear === Number(params.year) || n.media?.startDate?.year === Number(params.year)) + : n.media?.startDate?.year === Number(params.year)) // Filter by genre if (!!arr && !!params.genre?.length) { @@ -193,7 +195,7 @@ export function filterCollectionEntries n.media?.status === params.status) // Filter by year - if (!!arr && !!params.year) arr = arr.filter(n => n.media?.startDate?.year === Number(params.year)) + if (!!arr && !!params.year) arr = arr.filter(n => n.media?.seasonYear === Number(params.year) || n.media?.startDate?.year === Number(params.year)) // Filter by genre if (!!arr && !!params.genre?.length) {