初次提交
This commit is contained in:
@@ -0,0 +1,787 @@
|
||||
import { db } from '~/drizzle/db'
|
||||
import {
|
||||
notifications,
|
||||
notificationSettings,
|
||||
playTimes,
|
||||
schedules,
|
||||
songCollaborators,
|
||||
songs,
|
||||
systemSettings,
|
||||
users,
|
||||
votes
|
||||
} from '~/drizzle/schema'
|
||||
import { and, eq, gte, inArray } from 'drizzle-orm'
|
||||
import { sendBatchMeowNotifications, sendMeowNotificationToUser } from './meowNotificationService'
|
||||
import { sendBatchEmailNotifications, sendEmailNotificationToUser } from './smtpService'
|
||||
import { formatDateTime, getBeijingTime } from '~/utils/timeUtils'
|
||||
|
||||
/**
|
||||
* 创建联合投稿邀请通知
|
||||
*/
|
||||
export async function createCollaborationInvitationNotification(
|
||||
inviterId: number,
|
||||
inviteeId: number,
|
||||
songId: number,
|
||||
songTitle: string
|
||||
) {
|
||||
try {
|
||||
const inviter = await db
|
||||
.select()
|
||||
.from(users)
|
||||
.where(eq(users.id, inviterId))
|
||||
.limit(1)
|
||||
.then((res) => res[0])
|
||||
const message = `用户 ${inviter?.name || '未知用户'} 邀请您共同投稿歌曲《${songTitle}》。`
|
||||
|
||||
// 创建通知
|
||||
const notificationResult = await db
|
||||
.insert(notifications)
|
||||
.values({
|
||||
userId: inviteeId,
|
||||
type: 'COLLABORATION_INVITE',
|
||||
message,
|
||||
songId
|
||||
})
|
||||
.returning()
|
||||
|
||||
// 发送外部通知(MeoW, Email等)
|
||||
try {
|
||||
await sendMeowNotificationToUser(inviteeId, '收到联合投稿邀请', message)
|
||||
} catch (error) {
|
||||
console.error('发送 MeoW 通知失败:', error)
|
||||
}
|
||||
|
||||
try {
|
||||
await sendEmailNotificationToUser(
|
||||
inviteeId,
|
||||
'收到联合投稿邀请',
|
||||
message,
|
||||
undefined,
|
||||
'notification.collaborationInvite',
|
||||
{
|
||||
inviterName: inviter?.name || '未知用户',
|
||||
songTitle: songTitle
|
||||
}
|
||||
)
|
||||
} catch (error) {
|
||||
console.error('发送邮件通知失败:', error)
|
||||
}
|
||||
|
||||
return notificationResult[0]
|
||||
} catch (error) {
|
||||
console.error('创建联合投稿邀请通知失败:', error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建联合投稿回复通知
|
||||
*/
|
||||
export async function createCollaborationResponseNotification(
|
||||
inviteeId: number,
|
||||
inviterId: number,
|
||||
songTitle: string,
|
||||
accepted: boolean
|
||||
) {
|
||||
try {
|
||||
const invitee = await db
|
||||
.select()
|
||||
.from(users)
|
||||
.where(eq(users.id, inviteeId))
|
||||
.limit(1)
|
||||
.then((res) => res[0])
|
||||
const actionText = accepted ? '接受' : '拒绝'
|
||||
const message = `用户 ${invitee?.name || '未知用户'} ${actionText}了您的歌曲《${songTitle}》的联合投稿邀请。`
|
||||
|
||||
// 创建通知
|
||||
const notificationResult = await db
|
||||
.insert(notifications)
|
||||
.values({
|
||||
userId: inviterId,
|
||||
type: 'COLLABORATION_RESPONSE',
|
||||
message
|
||||
// songId // 这里可能不需要songId,或者需要传进来
|
||||
})
|
||||
.returning()
|
||||
|
||||
return notificationResult[0]
|
||||
} catch (error) {
|
||||
console.error('创建联合投稿回复通知失败:', error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建歌曲被选中的通知
|
||||
*/
|
||||
export async function createSongSelectedNotification(
|
||||
userId: number,
|
||||
songId: number,
|
||||
songInfo: {
|
||||
title: string
|
||||
artist: string
|
||||
playDate: Date
|
||||
},
|
||||
ipAddress?: string
|
||||
) {
|
||||
try {
|
||||
// 获取系统设置,检查是否启用播出时段功能
|
||||
const systemSettingsResult = await db.select().from(systemSettings).limit(1)
|
||||
const systemConfig = systemSettingsResult[0]
|
||||
const isPlayTimeEnabled = systemConfig?.enablePlayTimeSelection || false
|
||||
|
||||
// 获取排期对应的播出时段
|
||||
const scheduleResult = await db
|
||||
.select({
|
||||
id: schedules.id,
|
||||
songId: schedules.songId,
|
||||
playDate: schedules.playDate,
|
||||
playTimeId: schedules.playTimeId,
|
||||
playTime: {
|
||||
id: playTimes.id,
|
||||
name: playTimes.name,
|
||||
startTime: playTimes.startTime,
|
||||
endTime: playTimes.endTime
|
||||
}
|
||||
})
|
||||
.from(schedules)
|
||||
.leftJoin(playTimes, eq(schedules.playTimeId, playTimes.id))
|
||||
.where(and(eq(schedules.songId, songId), eq(schedules.playDate, songInfo.playDate)))
|
||||
.limit(1)
|
||||
const schedule = scheduleResult[0]
|
||||
|
||||
// 获取用户通知设置
|
||||
const settingsResult = await db
|
||||
.select()
|
||||
.from(notificationSettings)
|
||||
.where(eq(notificationSettings.userId, userId))
|
||||
.limit(1)
|
||||
const settings = settingsResult[0]
|
||||
|
||||
// 如果用户关闭了此类通知,则不发送
|
||||
if (settings && !settings.enabled) {
|
||||
return null
|
||||
}
|
||||
|
||||
// 创建通知,根据播出时段功能启用状态决定显示内容
|
||||
let message = `您投稿的歌曲《${songInfo.title}》已被安排播放,播放日期:${formatDate(songInfo.playDate)}。`
|
||||
|
||||
// 只有在启用播出时段功能且有播出时段信息时,才添加播出时段详情
|
||||
if (isPlayTimeEnabled && schedule?.playTime) {
|
||||
let timeInfo = ''
|
||||
|
||||
// 根据开始和结束时间的情况,格式化显示
|
||||
if (schedule.playTime.startTime && schedule.playTime.endTime) {
|
||||
timeInfo = `(${schedule.playTime.startTime}-${schedule.playTime.endTime})`
|
||||
} else if (schedule.playTime.startTime) {
|
||||
timeInfo = `(开始时间:${schedule.playTime.startTime})`
|
||||
} else if (schedule.playTime.endTime) {
|
||||
timeInfo = `(结束时间:${schedule.playTime.endTime})`
|
||||
}
|
||||
|
||||
message += `播出时段:${schedule.playTime.name}${timeInfo ? ' ' + timeInfo : ''}。`
|
||||
}
|
||||
|
||||
let notification
|
||||
try {
|
||||
const notificationResult = await db
|
||||
.insert(notifications)
|
||||
.values({
|
||||
userId,
|
||||
type: 'SONG_SELECTED',
|
||||
message,
|
||||
songId
|
||||
})
|
||||
.returning()
|
||||
notification = notificationResult[0]
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
|
||||
// 同步发送 MeoW 通知
|
||||
try {
|
||||
await sendMeowNotificationToUser(userId, '收到新选中', message)
|
||||
} catch (error) {
|
||||
console.error('发送 MeoW 通知失败:', error)
|
||||
}
|
||||
|
||||
// 同步发送 邮件通知
|
||||
try {
|
||||
await sendEmailNotificationToUser(
|
||||
userId,
|
||||
'歌曲被选中',
|
||||
message,
|
||||
ipAddress,
|
||||
'notification.songSelected',
|
||||
{
|
||||
songTitle: songInfo.title,
|
||||
playDate: formatDate(songInfo.playDate),
|
||||
playTimeName: isPlayTimeEnabled && schedule?.playTime ? schedule.playTime.name : '',
|
||||
playTimeRange:
|
||||
isPlayTimeEnabled &&
|
||||
schedule?.playTime &&
|
||||
(schedule.playTime.startTime || schedule.playTime.endTime)
|
||||
? `${schedule.playTime.startTime || ''}${schedule.playTime.startTime && schedule.playTime.endTime ? '-' : ''}${schedule.playTime.endTime || ''}`
|
||||
: ''
|
||||
}
|
||||
)
|
||||
} catch (error) {
|
||||
console.error('发送邮件通知失败:', error)
|
||||
}
|
||||
|
||||
return notification
|
||||
} catch (err) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
// 格式化日期为 yyyy-MM-dd 格式(北京时间)
|
||||
function formatDate(date: Date): string {
|
||||
return formatDateTime(date, 'YYYY-MM-DD')
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建歌曲已播放的通知
|
||||
*/
|
||||
export async function createSongPlayedNotification(songId: number, ipAddress?: string) {
|
||||
try {
|
||||
// 获取歌曲信息
|
||||
const songResult = await db.select().from(songs).where(eq(songs.id, songId)).limit(1)
|
||||
const song = songResult[0]
|
||||
|
||||
if (!song) {
|
||||
return null
|
||||
}
|
||||
|
||||
// 获取用户通知设置
|
||||
const settingsResult = await db
|
||||
.select()
|
||||
.from(notificationSettings)
|
||||
.where(eq(notificationSettings.userId, song.requesterId))
|
||||
.limit(1)
|
||||
const settings = settingsResult[0]
|
||||
|
||||
// 如果用户关闭了此类通知,则不发送
|
||||
if (settings && !settings.songPlayedEnabled) {
|
||||
return null
|
||||
}
|
||||
|
||||
// 创建通知
|
||||
const message = `您投稿的歌曲《${song.title}》已播放。`
|
||||
|
||||
// 获取所有关联用户(投稿人 + 联合投稿人)
|
||||
const userIdsToNotify = [song.requesterId]
|
||||
|
||||
// 获取联合投稿人
|
||||
const collaborators = await db
|
||||
.select()
|
||||
.from(songCollaborators)
|
||||
.where(and(eq(songCollaborators.songId, songId), eq(songCollaborators.status, 'ACCEPTED')))
|
||||
|
||||
collaborators.forEach((c) => {
|
||||
if (!userIdsToNotify.includes(c.userId)) {
|
||||
userIdsToNotify.push(c.userId)
|
||||
}
|
||||
})
|
||||
|
||||
const notificationsCreated = []
|
||||
|
||||
for (const targetUserId of userIdsToNotify) {
|
||||
try {
|
||||
// 获取用户通知设置
|
||||
const settingsResult = await db
|
||||
.select()
|
||||
.from(notificationSettings)
|
||||
.where(eq(notificationSettings.userId, targetUserId))
|
||||
.limit(1)
|
||||
const settings = settingsResult[0]
|
||||
|
||||
// 如果用户关闭了此类通知,则不发送
|
||||
if (settings && !settings.songPlayedEnabled) {
|
||||
continue
|
||||
}
|
||||
|
||||
const userMessage =
|
||||
targetUserId === song.requesterId
|
||||
? message
|
||||
: `您参与联合投稿的歌曲《${song.title}》已播放。`
|
||||
|
||||
const notificationResult = await db
|
||||
.insert(notifications)
|
||||
.values({
|
||||
userId: targetUserId,
|
||||
type: 'SONG_PLAYED',
|
||||
message: userMessage,
|
||||
songId: songId
|
||||
})
|
||||
.returning()
|
||||
notificationsCreated.push(notificationResult[0])
|
||||
|
||||
// 同步发送 MeoW 通知
|
||||
try {
|
||||
await sendMeowNotificationToUser(targetUserId, '歌曲已播放', userMessage)
|
||||
} catch (error) {
|
||||
console.error(`发送 MeoW 通知失败 (User: ${targetUserId}):`, error)
|
||||
}
|
||||
|
||||
// 同步发送 邮件通知
|
||||
try {
|
||||
await sendEmailNotificationToUser(
|
||||
targetUserId,
|
||||
'歌曲已播放',
|
||||
userMessage,
|
||||
ipAddress,
|
||||
'notification.songPlayed',
|
||||
{ songTitle: song.title }
|
||||
)
|
||||
} catch (error) {
|
||||
console.error(`发送邮件通知失败 (User: ${targetUserId}):`, error)
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`处理播放通知失败 (User: ${targetUserId}):`, err)
|
||||
}
|
||||
}
|
||||
|
||||
return notificationsCreated.length > 0 ? notificationsCreated[0] : null
|
||||
} catch (err) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建歌曲获得投票的通知
|
||||
*/
|
||||
export async function createSongVotedNotification(
|
||||
songId: number,
|
||||
voterId: number,
|
||||
ipAddress?: string
|
||||
) {
|
||||
try {
|
||||
// 获取歌曲信息
|
||||
const songResult = await db.select().from(songs).where(eq(songs.id, songId)).limit(1)
|
||||
const song = songResult[0]
|
||||
|
||||
if (!song) {
|
||||
return null
|
||||
}
|
||||
|
||||
// 获取歌曲的投票信息
|
||||
const songVotes = await db.select().from(votes).where(eq(votes.songId, songId))
|
||||
|
||||
// 获取投票用户信息
|
||||
const voterResult = await db.select().from(users).where(eq(users.id, voterId)).limit(1)
|
||||
const voter = voterResult[0]
|
||||
|
||||
if (!voter) {
|
||||
return null
|
||||
}
|
||||
|
||||
// 获取用户通知设置
|
||||
const settingsResult = await db
|
||||
.select()
|
||||
.from(notificationSettings)
|
||||
.where(eq(notificationSettings.userId, song.requesterId))
|
||||
.limit(1)
|
||||
const settings = settingsResult[0]
|
||||
|
||||
// 如果用户关闭了此类通知,则不发送
|
||||
if (settings && !settings.songVotedEnabled) {
|
||||
return null
|
||||
}
|
||||
|
||||
// 不要给自己投票发通知
|
||||
if (song.requesterId === voterId) {
|
||||
return null
|
||||
}
|
||||
|
||||
// 检查投票阈值
|
||||
const threshold = settings?.songVotedThreshold || 1
|
||||
if (songVotes.length % threshold !== 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
const message = `您投稿的歌曲《${song.title}》获得了一个新的投票,当前共有 ${songVotes.length} 个投票。`
|
||||
|
||||
// 防重复通知:检查最近5分钟内是否有相同歌曲的投票通知
|
||||
const fiveMinutesAgo = new Date(getBeijingTime().getTime() - 5 * 60 * 1000)
|
||||
|
||||
const existingNotificationResult = await db
|
||||
.select()
|
||||
.from(notifications)
|
||||
.where(
|
||||
and(
|
||||
eq(notifications.userId, song.requesterId),
|
||||
eq(notifications.type, 'SONG_VOTED'),
|
||||
eq(notifications.songId, songId),
|
||||
eq(notifications.read, false),
|
||||
gte(notifications.createdAt, fiveMinutesAgo)
|
||||
)
|
||||
)
|
||||
.orderBy(notifications.createdAt)
|
||||
.limit(1)
|
||||
const existingNotification = existingNotificationResult[0]
|
||||
|
||||
let notification
|
||||
if (existingNotification) {
|
||||
// 更新现有通知
|
||||
const updateResult = await db
|
||||
.update(notifications)
|
||||
.set({
|
||||
message
|
||||
})
|
||||
.where(eq(notifications.id, existingNotification.id))
|
||||
.returning()
|
||||
notification = updateResult[0]
|
||||
} else {
|
||||
// 创建新通知
|
||||
const createResult = await db
|
||||
.insert(notifications)
|
||||
.values({
|
||||
userId: song.requesterId,
|
||||
type: 'SONG_VOTED',
|
||||
message,
|
||||
songId: songId
|
||||
})
|
||||
.returning()
|
||||
notification = createResult[0]
|
||||
}
|
||||
|
||||
// 同步发送 MeoW 通知
|
||||
try {
|
||||
await sendMeowNotificationToUser(song.requesterId, '收到新投票', message)
|
||||
} catch (error) {
|
||||
console.error('发送 MeoW 通知失败:', error)
|
||||
}
|
||||
|
||||
// 同步发送 邮件通知
|
||||
try {
|
||||
await sendEmailNotificationToUser(
|
||||
song.requesterId,
|
||||
'收到新投票',
|
||||
message,
|
||||
ipAddress,
|
||||
'notification.songVoted',
|
||||
{ songTitle: song.title, votesCount: songVotes.length }
|
||||
)
|
||||
} catch (error) {
|
||||
console.error('发送邮件通知失败:', error)
|
||||
}
|
||||
|
||||
return notification
|
||||
} catch (err) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建歌曲驳回通知
|
||||
*/
|
||||
export async function createSongRejectedNotification(
|
||||
userId: number,
|
||||
songInfo: { title: string; artist: string },
|
||||
reason: string,
|
||||
ipAddress?: string
|
||||
) {
|
||||
try {
|
||||
// 获取用户通知设置
|
||||
const settingsResult = await db
|
||||
.select()
|
||||
.from(notificationSettings)
|
||||
.where(eq(notificationSettings.userId, userId))
|
||||
.limit(1)
|
||||
const settings = settingsResult[0]
|
||||
|
||||
// 如果用户关闭了通知,则不发送
|
||||
if (settings && !settings.enabled) {
|
||||
return null
|
||||
}
|
||||
|
||||
// 创建通知消息
|
||||
const message = `您投稿的歌曲《${songInfo.title} - ${songInfo.artist}》已被管理员驳回。驳回原因:${reason}`
|
||||
|
||||
// 创建站内通知
|
||||
let notification
|
||||
try {
|
||||
const notificationResult = await db
|
||||
.insert(notifications)
|
||||
.values({
|
||||
userId,
|
||||
type: 'SONG_REJECTED',
|
||||
message
|
||||
})
|
||||
.returning()
|
||||
notification = notificationResult[0]
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
|
||||
// 同步发送 MeoW 通知
|
||||
try {
|
||||
await sendMeowNotificationToUser(userId, '歌曲被驳回', message)
|
||||
} catch (error) {
|
||||
console.error('发送 MeoW 通知失败:', error)
|
||||
}
|
||||
|
||||
// 同步发送邮件通知
|
||||
try {
|
||||
await sendEmailNotificationToUser(
|
||||
userId,
|
||||
'歌曲被驳回',
|
||||
message,
|
||||
ipAddress,
|
||||
'notification.songRejected',
|
||||
{
|
||||
songTitle: songInfo.title,
|
||||
songArtist: songInfo.artist,
|
||||
reason: reason
|
||||
}
|
||||
)
|
||||
} catch (error) {
|
||||
console.error('发送邮件通知失败:', error)
|
||||
}
|
||||
|
||||
return notification
|
||||
} catch (err) {
|
||||
console.error('创建歌曲驳回通知失败:', err)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export async function createSubmissionNoteClearedNotification(
|
||||
userIds: number[],
|
||||
songInfo: { title: string; artist: string },
|
||||
reason?: string,
|
||||
ipAddress?: string
|
||||
) {
|
||||
try {
|
||||
const uniqueUserIds = [...new Set(userIds.filter((userId) => Number.isInteger(userId) && userId > 0))]
|
||||
|
||||
if (uniqueUserIds.length === 0) {
|
||||
return []
|
||||
}
|
||||
|
||||
const title = '歌曲备注已被管理员清空'
|
||||
const content = reason?.trim()
|
||||
? `您投稿歌曲《${songInfo.title} - ${songInfo.artist}》的备注已被管理员清空。原因:${reason.trim()}`
|
||||
: `您投稿歌曲《${songInfo.title} - ${songInfo.artist}》的备注已被管理员清空。`
|
||||
|
||||
return await createBatchSystemNotifications(uniqueUserIds, title, content, ipAddress)
|
||||
} catch (error) {
|
||||
console.error('创建歌曲备注清空通知失败:', error)
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建系统通知
|
||||
*/
|
||||
export async function createSystemNotification(
|
||||
userId: number,
|
||||
title: string,
|
||||
content: string,
|
||||
ipAddress?: string
|
||||
) {
|
||||
try {
|
||||
// 获取用户通知设置
|
||||
const settingsResult = await db
|
||||
.select()
|
||||
.from(notificationSettings)
|
||||
.where(eq(notificationSettings.userId, userId))
|
||||
.limit(1)
|
||||
const settings = settingsResult[0]
|
||||
|
||||
// 如果用户关闭了通知,则不发送
|
||||
if (settings && !settings.enabled) {
|
||||
return null
|
||||
}
|
||||
|
||||
// 创建通知
|
||||
const notificationResult = await db
|
||||
.insert(notifications)
|
||||
.values({
|
||||
userId: userId,
|
||||
type: 'SYSTEM_NOTICE',
|
||||
message: content
|
||||
})
|
||||
.returning()
|
||||
const notification = notificationResult[0]
|
||||
|
||||
// 同步发送 MeoW 通知
|
||||
try {
|
||||
await sendMeowNotificationToUser(userId, title, content)
|
||||
} catch (error) {
|
||||
console.error('发送 MeoW 通知失败:', error)
|
||||
}
|
||||
|
||||
// 同步发送邮件通知
|
||||
try {
|
||||
await sendEmailNotificationToUser(
|
||||
userId,
|
||||
title,
|
||||
content,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
ipAddress
|
||||
)
|
||||
} catch (error) {
|
||||
console.error('发送邮件通知失败:', error)
|
||||
}
|
||||
|
||||
return notification
|
||||
} catch (err) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量创建系统通知
|
||||
*/
|
||||
export async function createBatchSystemNotifications(
|
||||
userIds: number[],
|
||||
title: string,
|
||||
content: string,
|
||||
ipAddress?: string
|
||||
) {
|
||||
try {
|
||||
if (!userIds.length) {
|
||||
return []
|
||||
}
|
||||
|
||||
// 获取用户通知设置
|
||||
const userSettings = await db
|
||||
.select()
|
||||
.from(notificationSettings)
|
||||
.where(inArray(notificationSettings.userId, userIds))
|
||||
|
||||
// 构建用户ID到通知设置的映射
|
||||
const settingsMap = new Map()
|
||||
userSettings.forEach((setting) => {
|
||||
settingsMap.set(setting.userId, setting)
|
||||
})
|
||||
|
||||
// 准备要创建的通知数据
|
||||
const notificationsToCreate = []
|
||||
|
||||
for (const userId of userIds) {
|
||||
const settings = settingsMap.get(userId)
|
||||
|
||||
// 如果用户关闭了通知,则不发送
|
||||
if (settings && !settings.enabled) {
|
||||
continue
|
||||
}
|
||||
|
||||
notificationsToCreate.push({
|
||||
userId,
|
||||
type: 'SYSTEM_NOTICE',
|
||||
message: content
|
||||
})
|
||||
}
|
||||
|
||||
// 如果没有可发送的通知,直接返回
|
||||
if (notificationsToCreate.length === 0) {
|
||||
return []
|
||||
}
|
||||
|
||||
// 批量创建通知
|
||||
const createdNotifications = await db
|
||||
.insert(notifications)
|
||||
.values(notificationsToCreate)
|
||||
.returning()
|
||||
const notificationCount = { count: createdNotifications.length }
|
||||
|
||||
// 同步发送 MeoW 通知
|
||||
let meowResults = { success: 0, failed: 0 }
|
||||
try {
|
||||
meowResults = await sendBatchMeowNotifications(userIds, title, content)
|
||||
} catch (error) {
|
||||
console.error('批量发送 MeoW 通知失败:', error)
|
||||
}
|
||||
|
||||
// 同步发送邮件通知
|
||||
let emailResults = { success: 0, failed: 0 }
|
||||
try {
|
||||
emailResults = await sendBatchEmailNotifications(
|
||||
userIds,
|
||||
title,
|
||||
content,
|
||||
undefined,
|
||||
undefined,
|
||||
ipAddress
|
||||
)
|
||||
} catch (error) {
|
||||
console.error('批量发送邮件通知失败:', error)
|
||||
}
|
||||
|
||||
return {
|
||||
count: notificationCount.count,
|
||||
total: userIds.length,
|
||||
meowNotifications: meowResults,
|
||||
emailNotifications: emailResults
|
||||
}
|
||||
} catch (err) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建重播申请拒绝通知
|
||||
*/
|
||||
export async function createReplayRequestRejectedNotification(
|
||||
userId: number,
|
||||
songInfo: { title: string; artist: string },
|
||||
ipAddress?: string
|
||||
) {
|
||||
try {
|
||||
// 获取用户通知设置
|
||||
const settingsResult = await db
|
||||
.select()
|
||||
.from(notificationSettings)
|
||||
.where(eq(notificationSettings.userId, userId))
|
||||
.limit(1)
|
||||
const settings = settingsResult[0]
|
||||
|
||||
// 如果用户关闭了通知,则不发送
|
||||
if (settings && !settings.enabled) {
|
||||
return null
|
||||
}
|
||||
|
||||
// 创建通知消息
|
||||
const message = `您的重播申请《${songInfo.title}》已被管理员拒绝。`
|
||||
|
||||
// 创建站内通知
|
||||
let notification
|
||||
try {
|
||||
const notificationResult = await db
|
||||
.insert(notifications)
|
||||
.values({
|
||||
userId,
|
||||
type: 'REPLAY_REJECTED',
|
||||
message
|
||||
})
|
||||
.returning()
|
||||
notification = notificationResult[0]
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
|
||||
// 同步发送 MeoW 通知
|
||||
try {
|
||||
await sendMeowNotificationToUser(userId, '重播申请已拒绝', message)
|
||||
} catch (error) {
|
||||
console.error('发送 MeoW 通知失败:', error)
|
||||
}
|
||||
|
||||
// 同步发送邮件通知
|
||||
try {
|
||||
await sendEmailNotificationToUser(userId, '重播申请已拒绝', message, ipAddress)
|
||||
} catch (error) {
|
||||
console.error('发送邮件通知失败:', error)
|
||||
}
|
||||
|
||||
return notification
|
||||
} catch (err) {
|
||||
console.error('创建重播申请拒绝通知失败:', err)
|
||||
return null
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user