Strip Songs2VID to a payment-free self-hosted OSS core.
Remove Stripe/billing/pricing/marketing, simplify schema and entitlements for unlimited self-host use, and keep auth, encode, and YouTube upload.
This commit is contained in:
+7
-58
@@ -1,62 +1,11 @@
|
||||
import { Plan } from "@prisma/client";
|
||||
import { getPlanLimits } from "./plans";
|
||||
import { hasProFeatures } from "./edition";
|
||||
import {
|
||||
requiresArtTrackLayoutEntitlement,
|
||||
type LayoutSettings,
|
||||
} from "./layout";
|
||||
import {
|
||||
PREMIUM_REQUIRED_CODE,
|
||||
requiresCustomWatermarkEntitlement,
|
||||
type WatermarkSettings,
|
||||
} from "./watermark";
|
||||
import type { LayoutSettings } from "./layout";
|
||||
import type { WatermarkSettings } from "./watermark";
|
||||
|
||||
export class PremiumRequiredError extends Error {
|
||||
readonly code = PREMIUM_REQUIRED_CODE;
|
||||
readonly status = 403;
|
||||
constructor(message: string) {
|
||||
super(message);
|
||||
this.name = "PremiumRequiredError";
|
||||
}
|
||||
}
|
||||
export function assertCustomWatermarkAllowed(_settings: WatermarkSettings) {}
|
||||
|
||||
export function assertCustomWatermarkAllowed(plan: Plan, settings: WatermarkSettings) {
|
||||
if (!requiresCustomWatermarkEntitlement(settings)) return;
|
||||
if (getPlanLimits(plan).customWatermark || hasProFeatures(plan)) return;
|
||||
throw new PremiumRequiredError(
|
||||
"Custom watermark, typography, logo overlay, and position controls require Pro.",
|
||||
);
|
||||
}
|
||||
|
||||
export function assertArtTrackLayoutAllowed(plan: Plan, settings: LayoutSettings) {
|
||||
if (!requiresArtTrackLayoutEntitlement(settings)) return;
|
||||
if (getPlanLimits(plan).artTrackLayouts || hasProFeatures(plan)) return;
|
||||
throw new PremiumRequiredError(
|
||||
"Blurred backgrounds and art-track layout templates require Pro.",
|
||||
);
|
||||
}
|
||||
export function assertArtTrackLayoutAllowed(_settings: LayoutSettings) {}
|
||||
|
||||
export function assertPerItemImagesAllowed(
|
||||
plan: Plan,
|
||||
sharedImagePath: string,
|
||||
itemImagePaths: Array<string | null | undefined>,
|
||||
) {
|
||||
const unique = new Set(
|
||||
itemImagePaths
|
||||
.map((p) => (p && p.trim() ? p.trim() : sharedImagePath))
|
||||
.filter(Boolean),
|
||||
);
|
||||
// More than one distinct cover in the batch → Pro
|
||||
if (unique.size <= 1) return;
|
||||
if (getPlanLimits(plan).perItemImages || hasProFeatures(plan)) return;
|
||||
throw new PremiumRequiredError(
|
||||
"Matching a unique image to each audio file requires Pro. Free plan uses one shared cover image.",
|
||||
);
|
||||
}
|
||||
|
||||
export function premiumRequiredResponse(message: string) {
|
||||
return {
|
||||
error: message,
|
||||
code: PREMIUM_REQUIRED_CODE,
|
||||
};
|
||||
}
|
||||
_sharedImagePath: string,
|
||||
_itemImagePaths: Array<string | null | undefined>,
|
||||
) {}
|
||||
|
||||
Reference in New Issue
Block a user