Skip to content

Commit

Permalink
Add: Add ability to hide unreleased items (#1)
Browse files Browse the repository at this point in the history
* Add: Add ability to hide unreleased items

* Fix: Fix lint failures

* Refactor: Extract into variable

* Code: level -> item (I forgot to change)

* Refactor: More extracting

* Fix: Reverse publishedAt

* Code: serverConfigurations -> serverOptions

* Fix: Return item if it's item

* Fix: Hide levels in playlist details

* Fix: Fix some code issue

* Refactor: Extract into spoiler.ts

* Delete: Delete unnecessary conversion
  • Loading branch information
sevenc-nanashi authored Aug 30, 2024
1 parent 87aaa2a commit af35654
Show file tree
Hide file tree
Showing 14 changed files with 129 additions and 27 deletions.
11 changes: 9 additions & 2 deletions src/sonolus/background/info.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import { Icon, Text } from '@sonolus/core'
import { BackgroundItemModel } from '@sonolus/express'
import { randomize } from '../../utils/math.js'
import { sonolus } from '../index.js'
import { hideSpoilers } from '../utils/spoiler.js'
import { backgroundSearches } from './search.js'

export const installBackgroundInfo = () => {
sonolus.background.infoHandler = () => {
const cardBackgrounds = sonolus.background.items.filter(({ meta }) => meta)
sonolus.background.infoHandler = ({ options }) => {
const cardBackgrounds = hideSpoilers(
options.spoilers,
sonolus.background.items.filter(
(item): item is BackgroundItemModel & { meta: object } => item.meta !== undefined,
),
)
const otherBackgrounds = sonolus.background.items.filter(({ meta }) => !meta)

return {
Expand Down
4 changes: 2 additions & 2 deletions src/sonolus/background/item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export const updateBackgroundItems = (repository: Repository) => {
rarityIndex: cardRarity.index,
attributeIndex: attribute.index,
id: card.id,
releaseAt: card.releaseAt,
publishedAt: card.releaseAt,
}

if (cardRarity.hasTraining) {
Expand Down Expand Up @@ -96,6 +96,6 @@ export const updateBackgroundItems = (repository: Repository) => {

sonolus.background.items = [
...initialBackgrounds,
...backgrounds.sort((a, b) => b.meta.releaseAt - a.meta.releaseAt),
...backgrounds.sort((a, b) => b.meta.publishedAt - a.meta.publishedAt),
]
}
26 changes: 19 additions & 7 deletions src/sonolus/background/list.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
import { filterBackgrounds, paginateItems } from '@sonolus/express'
import { BackgroundItemModel, filterBackgrounds, paginateItems } from '@sonolus/express'
import { sonolus } from '../index.js'
import { randomizeItems, toIndexes } from '../utils/list.js'
import { hideSpoilers } from '../utils/spoiler.js'
import { backgroundSearches } from './search.js'

export const installBackgroundList = () => {
sonolus.background.listHandler = ({ search: { type, options }, page }) => {
sonolus.background.listHandler = ({
search: { type, options },
page,
options: serverOptions,
}) => {
const filteredBackgrounds = [
...hideSpoilers(
serverOptions.spoilers,
sonolus.background.items.filter(
(item): item is BackgroundItemModel & { meta: object } =>
item.meta !== undefined,
),
),
...sonolus.background.items.filter(({ meta }) => !meta),
]
if (type === 'quick')
return {
...paginateItems(
filterBackgrounds(sonolus.background.items, options.keywords),
page,
),
...paginateItems(filterBackgrounds(filteredBackgrounds, options.keywords), page),
searches: backgroundSearches,
}

Expand All @@ -32,7 +44,7 @@ export const installBackgroundList = () => {
const imageIndexes = toIndexes(options.images)

const items = filterBackgrounds(
sonolus.background.items.filter(
filteredBackgrounds.filter(
({ meta }) =>
meta &&
characterIndexes.includes(meta.characterIndex) &&
Expand Down
2 changes: 1 addition & 1 deletion src/sonolus/background/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ declare module '@sonolus/express' {
attributeIndex: number
imageIndex: number
id: number
releaseAt: number
publishedAt: number
}
}
}
15 changes: 15 additions & 0 deletions src/sonolus/configuration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { ServerOptionsModel } from '@sonolus/express'

export const serverOptions = {
spoilers: {
type: 'toggle',
name: {
en: 'Spoilers',
},
def: false,
description: {
en: 'Whether to show unreleased items.',
},
required: false,
},
} as const satisfies ServerOptionsModel
4 changes: 4 additions & 0 deletions src/sonolus/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { config } from '../config.js'
import { Repository } from '../repository/index.js'
import { installBackground, updateBackground } from './background/index.js'
import { backgroundSearches } from './background/search.js'
import { serverOptions } from './configuration.js'
import { installEngine } from './engine/index.js'
import { installInfo } from './info/index.js'
import { installLevel, updateLevel } from './level/index.js'
Expand All @@ -25,6 +26,9 @@ export const sonolus = new Sonolus({
background: {
searches: backgroundSearches,
},
configuration: {
options: serverOptions,
},
})

installPack()
Expand Down
5 changes: 3 additions & 2 deletions src/sonolus/level/info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@ import { Icon, Text } from '@sonolus/core'
import { LevelItemModel } from '@sonolus/express'
import { randomize } from '../../utils/math.js'
import { sonolus } from '../index.js'
import { hideSpoilers } from '../utils/spoiler.js'
import { levelSearches } from './search.js'

export const installLevelInfo = () => {
sonolus.level.infoHandler = () => {
sonolus.level.infoHandler = ({ options }) => {
const randomLevels: Record<string, LevelItemModel> = {}

const newestMusicIds = new Set<number>()
const newestLevels: LevelItemModel[] = []

for (const level of sonolus.level.items) {
for (const level of hideSpoilers(options.spoilers, sonolus.level.items)) {
randomLevels[`${level.meta.musicId}-${level.meta.musicVocalId}`] ??= level

if (newestLevels.length >= 5) continue
Expand Down
8 changes: 5 additions & 3 deletions src/sonolus/level/list.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { filterLevels, paginateItems } from '@sonolus/express'
import { sonolus } from '../index.js'
import { randomizeItems, toIndexes } from '../utils/list.js'
import { hideSpoilers } from '../utils/spoiler.js'
import { levelSearches } from './search.js'

export const installLevelList = () => {
sonolus.level.listHandler = ({ search: { type, options }, page }) => {
sonolus.level.listHandler = ({ search: { type, options }, page, options: serverOptions }) => {
const filteredLevels = hideSpoilers(serverOptions.spoilers, sonolus.level.items)
if (type === 'quick')
return {
...paginateItems(filterLevels(sonolus.level.items, options.keywords), page),
...paginateItems(filterLevels(filteredLevels, options.keywords), page),
searches: levelSearches,
}

Expand All @@ -16,7 +18,7 @@ export const installLevelList = () => {
const difficultyIndexes = toIndexes(options.difficulties)

const items = filterLevels(
sonolus.level.items.filter(
filteredLevels.filter(
({ rating, meta }) =>
(!meta.characterIndexes.length ||
meta.characterIndexes.some((characterIndex) =>
Expand Down
8 changes: 5 additions & 3 deletions src/sonolus/playlist/details.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import { config } from '../../config.js'
import { randomize } from '../../utils/math.js'
import { sonolus } from '../index.js'
import { nonEmpty } from '../utils/section.js'
import { hideSpoilers, hideSpoilersFromPlaylist } from '../utils/spoiler.js'

export const installPlaylistDetails = () => {
sonolus.playlist.detailsHandler = ({ itemName }) => {
sonolus.playlist.detailsHandler = ({ itemName, options }) => {
if (itemName.startsWith(`${config.sonolus.prefix}-random-`)) {
const [, , , min, max] = itemName.split('-')
const minRating = +(min ?? '') || 0
Expand All @@ -22,14 +23,15 @@ export const installPlaylistDetails = () => {
author: databaseEngineItem.subtitle,
tags: [{ title: { en: Text.Random } }],
levels: randomize(
sonolus.level.items
hideSpoilers(options.spoilers, sonolus.level.items)
.filter(({ rating }) => rating >= minRating && rating <= maxRating)
.map(({ name }) => name),
20,
),
meta: {
musicVocalTypeIndexes: new Set(),
characterIndexes: new Set(),
publishedAt: Date.now(),
},
},
actions: {},
Expand All @@ -43,7 +45,7 @@ export const installPlaylistDetails = () => {
if (!item) return 404

return {
item,
item: hideSpoilersFromPlaylist(options.spoilers, item),
description: item.description,
actions: {},
hasCommunity: false,
Expand Down
11 changes: 8 additions & 3 deletions src/sonolus/playlist/info.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
import { Icon, Text } from '@sonolus/core'
import { randomize } from '../../utils/math.js'
import { sonolus } from '../index.js'
import { hideSpoilersFromPlaylists } from '../utils/spoiler.js'
import { playlistSearches } from './search.js'

export const installPlaylistInfo = () => {
sonolus.playlist.infoHandler = () => {
sonolus.playlist.infoHandler = ({ options }) => {
const filteredPlaylists = hideSpoilersFromPlaylists(
options.spoilers,
sonolus.playlist.items,
)
return {
searches: playlistSearches,
sections: [
{
title: { en: Text.Random },
icon: Icon.Shuffle,
itemType: 'playlist',
items: randomize(sonolus.playlist.items, 5),
items: randomize(filteredPlaylists, 5),
},
{
title: { en: Text.Newest },
itemType: 'playlist',
items: sonolus.playlist.items.slice(0, 5),
items: filteredPlaylists.slice(0, 5),
},
],
banner: sonolus.banner,
Expand Down
5 changes: 5 additions & 0 deletions src/sonolus/playlist/item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ export const updatePlaylistItems = () => {
for (const characterIndex of level.meta.characterIndexes) {
playlist.meta.characterIndexes.add(characterIndex)
}

if (level.meta.publishedAt < playlist.meta.publishedAt) {
playlist.meta.publishedAt = level.meta.publishedAt
}
} else {
playlists.set(level.meta.musicId, {
name: `${config.sonolus.prefix}-${level.meta.musicId}`,
Expand All @@ -32,6 +36,7 @@ export const updatePlaylistItems = () => {
meta: {
musicVocalTypeIndexes: new Set([level.meta.musicVocalTypeIndex]),
characterIndexes: new Set(level.meta.characterIndexes),
publishedAt: level.meta.publishedAt,
},
})
}
Expand Down
17 changes: 13 additions & 4 deletions src/sonolus/playlist/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,22 @@ import { databaseEngineItem } from 'sonolus-pjsekai-engine'
import { config } from '../../config.js'
import { sonolus } from '../index.js'
import { randomizeItems, toIndexes } from '../utils/list.js'
import { hideSpoilersFromPlaylists } from '../utils/spoiler.js'
import { playlistSearches } from './search.js'

export const installPlaylistList = () => {
sonolus.playlist.listHandler = ({ search: { type, options }, page }) => {
sonolus.playlist.listHandler = ({
search: { type, options },
page,
options: serverOptions,
}) => {
const filteredPlaylists = hideSpoilersFromPlaylists(
serverOptions.spoilers,
sonolus.playlist.items,
)
if (type === 'quick')
return {
...paginateItems(filterPlaylists(sonolus.playlist.items, options.keywords), page),
...paginateItems(filterPlaylists(filteredPlaylists, options.keywords), page),
searches: playlistSearches,
}

Expand All @@ -29,6 +38,7 @@ export const installPlaylistList = () => {
meta: {
musicVocalTypeIndexes: new Set(),
characterIndexes: new Set(),
publishedAt: Date.now(),
},
},
],
Expand All @@ -39,7 +49,7 @@ export const installPlaylistList = () => {
const musicVocalTypeIndexes = toIndexes(options.categories)

const items = filterPlaylists(
sonolus.playlist.items.filter(
filteredPlaylists.filter(
({ meta }) =>
(!meta.characterIndexes.size ||
characterIndexes.some((characterIndex) =>
Expand All @@ -51,7 +61,6 @@ export const installPlaylistList = () => {
),
options.keywords,
)

return {
...(options.random ? randomizeItems(items) : paginateItems(items, page)),
searches: playlistSearches,
Expand Down
1 change: 1 addition & 0 deletions src/sonolus/playlist/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ declare module '@sonolus/express' {
meta: {
musicVocalTypeIndexes: Set<number>
characterIndexes: Set<number>
publishedAt: number
}
}
}
39 changes: 39 additions & 0 deletions src/sonolus/utils/spoiler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { PlaylistItemModel } from '@sonolus/express'
import { sonolus } from '../index.js'

export const hideSpoilers = <T extends { meta: { publishedAt: number } }>(
passThrough: boolean,
items: T[],
): T[] => {
if (passThrough) {
return items
}
return items.filter((item) => item.meta.publishedAt <= Date.now())
}

export const hideSpoilersFromPlaylist = (
passThrough: boolean,
playlist: PlaylistItemModel,
): PlaylistItemModel => {
if (passThrough) {
return playlist
}
return {
...playlist,
levels: hideSpoilers(
false,
playlist.levels.map((levelNameOrItem) => {
if (typeof levelNameOrItem === 'object') return levelNameOrItem
const level = sonolus.level.items.find((level) => level.name === levelNameOrItem)
if (!level) throw new Error(`Level not found: ${levelNameOrItem}`)
return level
}),
),
}
}

export const hideSpoilersFromPlaylists = (
passThrough: boolean,
playlists: PlaylistItemModel[],
): PlaylistItemModel[] =>
playlists.map((playlist) => hideSpoilersFromPlaylist(passThrough, playlist))

0 comments on commit af35654

Please sign in to comment.