- Added new models for premium tier configurations and assignments, enabling feature limits for free and premium users. - Introduced GDPR deletion logging and commands for user data management. - Enhanced logging configuration with retention days for audit logs. - Updated bot commands and job processing to include new premium and GDPR functionalities. - Improved localization with new keys for premium features and GDPR commands in both English and German. - Added UI components for managing premium settings and logging retention in the WebUI.
93 lines
2.6 KiB
TypeScript
93 lines
2.6 KiB
TypeScript
import type {
|
|
SocialFeedDashboard,
|
|
SocialFeedDashboardCreate,
|
|
SocialFeedDashboardUpdate
|
|
} from '@nexumi/shared';
|
|
import type { SocialFeed } from '@prisma/client';
|
|
import { prisma } from '../prisma';
|
|
import { assertPremiumLimit, PremiumLimitError } from '../premium';
|
|
|
|
export class FeedPremiumError extends Error {
|
|
constructor(public readonly code: 'premium_limit' | 'premium_feature') {
|
|
super(code);
|
|
}
|
|
}
|
|
|
|
function toDashboard(feed: SocialFeed): SocialFeedDashboard {
|
|
return {
|
|
id: feed.id,
|
|
type: feed.type as SocialFeedDashboard['type'],
|
|
sourceId: feed.sourceId,
|
|
channelId: feed.channelId,
|
|
rolePingId: feed.rolePingId ?? '',
|
|
template: feed.template,
|
|
enabled: feed.enabled
|
|
};
|
|
}
|
|
|
|
export async function listFeeds(guildId: string): Promise<SocialFeedDashboard[]> {
|
|
const feeds = await prisma.socialFeed.findMany({
|
|
where: { guildId },
|
|
orderBy: { createdAt: 'asc' }
|
|
});
|
|
return feeds.map(toDashboard);
|
|
}
|
|
|
|
export async function createFeed(
|
|
guildId: string,
|
|
input: SocialFeedDashboardCreate
|
|
): Promise<SocialFeedDashboard> {
|
|
await prisma.guild.upsert({ where: { id: guildId }, update: {}, create: { id: guildId } });
|
|
const currentCount = await prisma.socialFeed.count({ where: { guildId } });
|
|
try {
|
|
await assertPremiumLimit(prisma, guildId, 'feeds', currentCount);
|
|
} catch (error) {
|
|
if (error instanceof PremiumLimitError) {
|
|
throw new FeedPremiumError(error.code === 'feature_disabled' ? 'premium_feature' : 'premium_limit');
|
|
}
|
|
throw error;
|
|
}
|
|
const feed = await prisma.socialFeed.create({
|
|
data: {
|
|
guildId,
|
|
type: input.type,
|
|
sourceId: input.sourceId,
|
|
channelId: input.channelId,
|
|
rolePingId: input.rolePingId || null,
|
|
template: input.template ?? null,
|
|
enabled: input.enabled
|
|
}
|
|
});
|
|
return toDashboard(feed);
|
|
}
|
|
|
|
export async function updateFeed(
|
|
guildId: string,
|
|
feedId: string,
|
|
patch: SocialFeedDashboardUpdate
|
|
): Promise<SocialFeedDashboard | null> {
|
|
const existing = await prisma.socialFeed.findFirst({ where: { id: feedId, guildId } });
|
|
if (!existing) {
|
|
return null;
|
|
}
|
|
|
|
const { rolePingId, ...rest } = patch;
|
|
const updated = await prisma.socialFeed.update({
|
|
where: { id: feedId },
|
|
data: {
|
|
...rest,
|
|
...(rolePingId !== undefined ? { rolePingId: rolePingId === '' ? null : rolePingId } : {})
|
|
}
|
|
});
|
|
return toDashboard(updated);
|
|
}
|
|
|
|
export async function deleteFeed(guildId: string, feedId: string): Promise<boolean> {
|
|
const existing = await prisma.socialFeed.findFirst({ where: { id: feedId, guildId } });
|
|
if (!existing) {
|
|
return false;
|
|
}
|
|
await prisma.socialFeed.delete({ where: { id: feedId } });
|
|
return true;
|
|
}
|