Add favorite property for items and associated filters.

This commit is contained in:
Rapha149 2026-03-16 19:46:45 +01:00
parent 6d3773a0b8
commit a5999fb9df
14 changed files with 308 additions and 11 deletions

View file

@ -114,6 +114,8 @@ class User extends Model {
this.updatedAt
/** @type {import('./MediaProgress')[]?} - Only included when extended */
this.mediaProgresses
/** @type {import('./LibraryItem')[]?} - Only included when extended */
this.favorites
}
// Excludes "root" since their can only be 1 root user
@ -357,7 +359,15 @@ class User extends Model {
[sequelize.Op.like]: username
}
},
include: this.sequelize.models.mediaProgress
include: [
this.sequelize.models.mediaProgress,
{
model: this.sequelize.models.libraryItem,
as: 'favorites',
attributes: ['id'],
through: { attributes: [] }
}
]
})
if (user) userCache.set(user)
@ -382,7 +392,15 @@ class User extends Model {
[sequelize.Op.like]: email
}
},
include: this.sequelize.models.mediaProgress
include: [
this.sequelize.models.mediaProgress,
{
model: this.sequelize.models.libraryItem,
as: 'favorites',
attributes: ['id'],
through: { attributes: [] }
}
]
})
if (user) userCache.set(user)
@ -402,7 +420,15 @@ class User extends Model {
if (cachedUser) return cachedUser
const user = await this.findByPk(userId, {
include: this.sequelize.models.mediaProgress
include: [
this.sequelize.models.mediaProgress,
{
model: this.sequelize.models.libraryItem,
as: 'favorites',
attributes: ['id'],
through: { attributes: [] }
}
]
})
if (user) userCache.set(user)
@ -426,7 +452,15 @@ class User extends Model {
where: {
[sequelize.Op.or]: [{ id: userId }, { 'extraData.oldUserId': userId }]
},
include: this.sequelize.models.mediaProgress
include: [
this.sequelize.models.mediaProgress,
{
model: this.sequelize.models.libraryItem,
as: 'favorites',
attributes: ['id'],
through: { attributes: [] }
}
]
})
if (user) userCache.set(user)
@ -447,7 +481,15 @@ class User extends Model {
const user = await this.findOne({
where: sequelize.where(sequelize.literal(`extraData->>"authOpenIDSub"`), sub),
include: this.sequelize.models.mediaProgress
include: [
this.sequelize.models.mediaProgress,
{
model: this.sequelize.models.libraryItem,
as: 'favorites',
attributes: ['id'],
through: { attributes: [] }
}
]
})
if (user) userCache.set(user)
@ -621,6 +663,7 @@ class User extends Model {
isOldToken: this.isOldToken,
mediaProgress: this.mediaProgresses?.map((mp) => mp.getOldMediaProgress()) || [],
seriesHideFromContinueListening: [...seriesHideFromContinueListening],
favorites: this.favorites?.map(f => f.id) || [],
bookmarks: this.bookmarks?.map((b) => ({ ...b })) || [],
isActive: this.isActive,
isLocked: this.isLocked,

View file

@ -0,0 +1,66 @@
const { DataTypes, Model } = require('sequelize')
class UserFavorite extends Model {
constructor(values, options) {
super(values, options)
/** @type {UUIDV4} */
this.id
/** @type {UUIDV4} */
this.libraryItemId
/** @type {UUIDV4} */
this.userId
}
static init(sequelize) {
super.init(
{
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true
},
libraryItemId: DataTypes.UUID,
userId: DataTypes.UUID
},
{
sequelize,
modelName: 'userFavorite',
indexes: [
{
fields: ['userId']
},
{
fields: ['libraryItemId']
},
{
unique: true,
fields: ['libraryItemId', 'userId'],
}
]
}
)
const { libraryItem, user } = sequelize.models
libraryItem.hasMany(UserFavorite, {
foreignKey: 'libraryItemId',
onDelete: 'CASCADE'
})
UserFavorite.belongsTo(libraryItem, { foreignKey: 'libraryItemId' })
user.hasMany(UserFavorite, {
foreignKey: 'userId',
onDelete: 'CASCADE'
})
user.belongsToMany(libraryItem, {
through: UserFavorite,
foreignKey: 'userId',
otherKey: 'libraryItemId',
as: 'favorites'
})
UserFavorite.belongsTo(user, { foreignKey: 'userId' })
}
}
module.exports = UserFavorite