A new start

This commit is contained in:
Valknar XXX
2025-10-25 22:04:41 +02:00
commit be0fc11a5c
193 changed files with 25076 additions and 0 deletions

View File

@@ -0,0 +1,54 @@
{
"name": "@sexy.pivoine.art/bundle",
"description": "Please enter a description for your extension",
"icon": "extension",
"version": "1.0.0",
"keywords": [
"directus",
"directus-extension",
"directus-extension-bundle"
],
"type": "module",
"files": [
"dist"
],
"directus:extension": {
"type": "bundle",
"path": {
"app": "dist/app.js",
"api": "dist/api.js"
},
"entries": [
{
"name": "endpoint",
"type": "endpoint",
"source": "src/endpoint"
},
{
"name": "hook",
"type": "hook",
"source": "src/hook"
},
{
"name": "theme",
"type": "theme",
"source": "src/theme"
}
],
"host": "^11.11.0"
},
"scripts": {
"build": "directus-extension build",
"dev": "directus-extension build -w --no-minify",
"link": "directus-extension link",
"validate": "directus-extension validate",
"add": "directus-extension add"
},
"devDependencies": {
"@directus/extensions-sdk": "16.0.2"
},
"dependencies": {
"@sindresorhus/slugify": "^3.0.0",
"fluent-ffmpeg": "^2.1.3"
}
}

View File

@@ -0,0 +1,61 @@
const createPolicyFilter = (policy) => ({
_or: [
{
policies: {
policy: {
name: {
_eq: policy,
},
},
},
},
{
role: {
name: {
_eq: policy,
},
},
},
],
});
export default {
id: "sexy",
handler: (router, context) => {
const { services, getSchema } = context;
const { ItemsService } = services;
router.get("/stats", async (_req, res) => {
const usersService = new ItemsService("directus_users", {
schema: await getSchema(),
});
const modelsCount = await usersService.readByQuery({
aggregate: {
count: ["*"],
},
filter: createPolicyFilter("Model"),
});
const viewersCount = await usersService.readByQuery({
aggregate: {
count: ["*"],
},
filter: createPolicyFilter("Viewer"),
});
const videosService = new ItemsService("sexy_videos", {
schema: await getSchema(),
});
const videosCount = await videosService.readByQuery({
aggregate: {
count: ["*"],
},
});
res.json({
models_count: modelsCount[0].count,
viewers_count: viewersCount[0].count,
videos_count: videosCount[0].count,
});
});
},
};

View File

@@ -0,0 +1,70 @@
import { createRequire } from "module";
global.require = createRequire(import.meta.url);
import { defineHook } from "@directus/extensions-sdk";
import slugify from "@sindresorhus/slugify";
import ffmpeg from "fluent-ffmpeg";
async function processVideo(
meta,
{ schema, accountability },
services,
logger,
) {
const { FilesService } = services;
const itemId = meta.key;
const videoPath = `/directus/uploads/${meta.payload.filename_disk}`; // Adjust path as needed
const videoService = new FilesService({ schema, accountability }); // Replace with your collection name
try {
const durationInSeconds = await new Promise((resolve, reject) => {
ffmpeg.ffprobe(videoPath, function (err, metadata) {
if (err) {
reject(err);
}
resolve(parseInt(metadata.format.duration));
});
});
// Update the item with the duration
await videoService.updateOne(itemId, { duration: durationInSeconds });
logger.info(`Video ${itemId} duration updated to ${durationInSeconds}`);
} catch (error) {
logger.error(`Error processing video ${itemId}:`, error);
}
}
export default defineHook(async ({ filter, action }, { services, logger }) => {
action("files.upload", async (meta, context) => {
await processVideo(meta, context, services, logger);
});
filter(
"users.create",
(payload: {
first_name: string;
last_name: string;
artist_name: string;
slug: string;
}) => {
const artist_name = `${payload.first_name}-${new Date().getTime()}`;
const slug = slugify(artist_name);
const join_date = new Date();
return { ...payload, artist_name, slug, join_date };
},
);
filter(
"users.update",
(payload: {
first_name: string;
last_name: string;
artist_name: string;
slug: string;
}) => {
if (payload.artist_name) {
const slug = slugify(payload.artist_name);
return { ...payload, slug };
}
return payload;
},
);
});

View File

@@ -0,0 +1,130 @@
import { defineTheme } from "@directus/extensions-sdk";
import "./style.css";
export default defineTheme({
id: "@sexy.pivoine.art/theme",
name: "Sexy.Art Dark",
appearance: "dark",
rules: {
borderRadius: "6px",
borderWidth: "2px",
foreground: "#c9d1d9",
foregroundSubdued: "#666672",
foregroundAccent: "#f0f6fc",
background: "#0D1117",
backgroundNormal: "#21262E",
backgroundAccent: "#30363D",
backgroundSubdued: "#161B22",
borderColor: "#21262E",
borderColorAccent: "#30363D",
borderColorSubdued: "#161B22",
primary: "#ce47eb",
secondary: "#613dff",
success: "#87ff66",
warning: "#ffbf66",
danger: "#ff6467",
navigation: {
background: "#21262E",
backgroundAccent: "#30363D",
borderWidth: "0px",
borderColor: "transparent",
project: {
background: "#30363D",
borderWidth: "0px",
borderColor: "transparent",
},
modules: {
borderWidth: "0px",
borderColor: "transparent",
button: {
foregroundHover: "#fff",
background: "transparent",
backgroundHover: "transparent",
backgroundActive: "#21262E",
},
},
list: {
background: "transparent",
backgroundHover: "#30363D",
backgroundActive: "#30363D",
divider: {
borderColor: "#30363D",
},
},
},
header: {
borderWidth: "0px",
borderColor: "transparent",
boxShadow: "0 4px 7px -4px black",
},
form: {
columnGap: "32px",
rowGap: "40px",
field: {
label: {
fontWeight: "600",
},
input: {
borderColor: "#21262E",
borderColorHover: "#30363D",
boxShadow: "none",
boxShadowHover: "none",
height: "60px",
padding: "16px",
},
},
},
sidebar: {
background: "#21262E",
borderWidth: "0px",
borderColor: "transparent",
section: {
toggle: {
background: "#30363D",
borderWidth: "0px",
borderColor: "transparent",
},
form: {
field: {
input: {
height: "52px",
padding: "12px",
},
},
},
},
},
public: {
art: {
background: "#21262E",
speed: "1",
},
},
popover: {
menu: {
background: "#30363D",
boxShadow: "0px 0px 6px 0px black",
},
},
banner: {
background: "#161B22",
padding: "40px",
avatar: {
background: "#fff",
borderRadius: "50%",
},
headline: {
foreground: "#fff",
},
title: {
foreground: "#fff",
},
subtitle: {
foreground: "#969696",
},
art: {
foreground: "#21262E",
},
},
},
});

View File

View File

@@ -0,0 +1,29 @@
{
"compilerOptions": {
"target": "ES2022",
"lib": ["ES2022", "DOM"],
"module": "ES2022",
"moduleResolution": "node",
"strict": false,
"noFallthroughCasesInSwitch": true,
"esModuleInterop": true,
"noImplicitAny": false,
"noImplicitThis": true,
"noImplicitReturns": true,
"noUnusedLocals": true,
"noUncheckedIndexedAccess": true,
"noUnusedParameters": true,
"alwaysStrict": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictBindCallApply": true,
"strictPropertyInitialization": true,
"resolveJsonModule": false,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"allowSyntheticDefaultImports": true,
"isolatedModules": true,
"allowJs": true
},
"include": ["./src/**/*.ts"]
}