- Created setup-directus-collections.js to automate the creation of tech stack collections, fields, and relations in Directus. - Created setup-directus-hobbies.js for setting up hobbies collection with translations. - Created setup-directus-projects.js for establishing projects collection with comprehensive fields and translations. - Added setup-tech-stack-directus.js to populate tech_stack_items with predefined data.
198 lines
5.7 KiB
JavaScript
198 lines
5.7 KiB
JavaScript
// --------------------------------------------------------
|
|
// DATEN AUS DEN VORHERIGEN NODES HOLEN
|
|
// --------------------------------------------------------
|
|
|
|
// 1. Spotify Node
|
|
let spotifyData = null;
|
|
try {
|
|
spotifyData = $('Spotify').first().json;
|
|
} catch (e) {}
|
|
|
|
// 2. Lanyard Node (Discord)
|
|
let lanyardData = null;
|
|
try {
|
|
lanyardData = $('Lanyard').first().json.data;
|
|
} catch (e) {}
|
|
|
|
// 3. Wakapi Summary (Tages-Statistik)
|
|
let wakapiStats = null;
|
|
try {
|
|
const wRaw = $('Wakapi').first().json;
|
|
// Manchmal ist es direkt im Root, manchmal unter data
|
|
wakapiStats = wRaw.grand_total ? wRaw : (wRaw.data ? wRaw.data : null);
|
|
} catch (e) {}
|
|
|
|
// 4. Wakapi Heartbeats (Live Check)
|
|
let heartbeatsList = [];
|
|
try {
|
|
const response = $('WakapiLast').last().json;
|
|
if (response.data && Array.isArray(response.data)) {
|
|
heartbeatsList = response.data;
|
|
}
|
|
} catch (e) {}
|
|
|
|
// 5. Hardcover Reading (Neu!)
|
|
let hardcoverData = null;
|
|
try {
|
|
// Falls du einen Node "Hardcover" hast
|
|
hardcoverData = $('Hardcover').first().json;
|
|
} catch (e) {}
|
|
|
|
|
|
// --------------------------------------------------------
|
|
// LOGIK & FORMATIERUNG
|
|
// --------------------------------------------------------
|
|
|
|
// --- A. SPOTIFY / MUSIC ---
|
|
let music = null;
|
|
|
|
if (spotifyData && spotifyData.item && spotifyData.is_playing) {
|
|
music = {
|
|
isPlaying: true,
|
|
track: spotifyData.item.name,
|
|
artist: spotifyData.item.artists.map(a => a.name).join(', '),
|
|
album: spotifyData.item.album.name,
|
|
albumArt: spotifyData.item.album.images[0]?.url,
|
|
url: spotifyData.item.external_urls.spotify
|
|
};
|
|
} else if (lanyardData?.listening_to_spotify && lanyardData.spotify) {
|
|
music = {
|
|
isPlaying: true,
|
|
track: lanyardData.spotify.song,
|
|
artist: lanyardData.spotify.artist.replace(/;/g, ", "),
|
|
album: lanyardData.spotify.album,
|
|
albumArt: lanyardData.spotify.album_art_url,
|
|
url: `https://open.spotify.com/track/${lanyardData.spotify.track_id}`
|
|
};
|
|
}
|
|
|
|
// --- B. GAMING & STATUS ---
|
|
let gaming = null;
|
|
let status = {
|
|
text: lanyardData?.discord_status || "offline",
|
|
color: 'gray'
|
|
};
|
|
|
|
// Farben mapping
|
|
if (status.text === 'online') status.color = 'green';
|
|
if (status.text === 'idle') status.color = 'yellow';
|
|
if (status.text === 'dnd') status.color = 'red';
|
|
|
|
if (lanyardData?.activities) {
|
|
lanyardData.activities.forEach(act => {
|
|
// Type 0 = Game (Spotify ignorieren)
|
|
if (act.type === 0 && act.name !== "Spotify") {
|
|
let image = null;
|
|
if (act.assets?.large_image) {
|
|
if (act.assets.large_image.startsWith("mp:external")) {
|
|
image = act.assets.large_image.replace(/mp:external\/([^\/]*)\/(https?)\/(^\/]*)\/(.*)/,"$2://$3/$4");
|
|
} else {
|
|
image = `https://cdn.discordapp.com/app-assets/${act.application_id}/${act.assets.large_image}.png`;
|
|
}
|
|
}
|
|
gaming = {
|
|
isPlaying: true,
|
|
name: act.name,
|
|
details: act.details,
|
|
state: act.state,
|
|
image: image
|
|
};
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
// --- C. CODING (Wakapi Logic) ---
|
|
let coding = null;
|
|
|
|
// 1. Basis-Stats von heute (Fallback)
|
|
if (wakapiStats && wakapiStats.grand_total) {
|
|
coding = {
|
|
isActive: false,
|
|
stats: {
|
|
time: wakapiStats.grand_total.text,
|
|
topLang: wakapiStats.languages?.[0]?.name || "Code",
|
|
topProject: wakapiStats.projects?.[0]?.name || "Project"
|
|
}
|
|
};
|
|
}
|
|
|
|
// 2. Live Check via Heartbeats
|
|
if (heartbeatsList.length > 0) {
|
|
const latestBeat = heartbeatsList[heartbeatsList.length - 1];
|
|
|
|
if (latestBeat && latestBeat.time) {
|
|
const beatTime = new Date(latestBeat.time * 1000).getTime();
|
|
const now = new Date().getTime();
|
|
const diffMinutes = (now - beatTime) / 1000 / 60;
|
|
|
|
// Wenn jünger als 15 Minuten -> AKTIV
|
|
if (diffMinutes < 15) {
|
|
if (!coding) coding = { stats: { time: "Just started" } };
|
|
|
|
coding.isActive = true;
|
|
coding.project = latestBeat.project || coding.stats?.topProject;
|
|
|
|
if (latestBeat.entity) {
|
|
const parts = latestBeat.entity.split(/[/\\]/);
|
|
coding.file = parts[parts.length - 1];
|
|
}
|
|
|
|
coding.language = latestBeat.language;
|
|
}
|
|
}
|
|
}
|
|
|
|
// --- D. CUSTOM ACTIVITIES (Komplett dynamisch!) ---
|
|
// Hier kannst du beliebige Activities hinzufügen ohne Website Code zu ändern
|
|
let customActivities = {};
|
|
|
|
// Beispiel: Reading Activity (Hardcover Integration)
|
|
if (hardcoverData && hardcoverData.user_book) {
|
|
const book = hardcoverData.user_book;
|
|
customActivities.reading = {
|
|
enabled: true,
|
|
title: book.book?.title,
|
|
author: book.book?.contributions?.[0]?.author?.name,
|
|
progress: book.progress_pages && book.book?.pages
|
|
? Math.round((book.progress_pages / book.book.pages) * 100)
|
|
: undefined,
|
|
coverUrl: book.book?.image_url
|
|
};
|
|
}
|
|
|
|
// Beispiel: Manuell gesetzt via separatem Webhook
|
|
// Du kannst einen Webhook erstellen der customActivities setzt:
|
|
// POST /webhook/set-custom-activity
|
|
// {
|
|
// "type": "working_out",
|
|
// "data": {
|
|
// "enabled": true,
|
|
// "activity": "Running",
|
|
// "duration_minutes": 45,
|
|
// "distance_km": 7.2,
|
|
// "calories": 350
|
|
// }
|
|
// }
|
|
// Dann hier einfach: customActivities.working_out = $('SetCustomActivity').first().json.data;
|
|
|
|
// WICHTIG: Du kannst auch mehrere Activities gleichzeitig haben!
|
|
// customActivities.learning = { enabled: true, course: "Docker", platform: "Udemy", progress: 67 };
|
|
// customActivities.streaming = { enabled: true, platform: "Twitch", viewers: 42 };
|
|
// etc.
|
|
|
|
|
|
// --------------------------------------------------------
|
|
// OUTPUT
|
|
// --------------------------------------------------------
|
|
return {
|
|
json: {
|
|
status,
|
|
music,
|
|
gaming,
|
|
coding,
|
|
customActivities, // NEU! Komplett dynamisch
|
|
timestamp: new Date().toISOString()
|
|
}
|
|
};
|