From d36ba22c9aa0d78be9f69acb06cf2b405c0ca6da Mon Sep 17 00:00:00 2001 From: Arthur DANJOU Date: Fri, 14 Nov 2025 18:13:14 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20ajouter=20la=20gestion=20des=20contacts?= =?UTF-8?q?=20et=20des=20hobbies=20avec=20des=20ressources=20associ=C3=A9e?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- content.config.ts | 14 ++++ content/contact.json | 34 ++++++++ content/hobbies.md | 16 ++++ nuxt.config.ts | 13 +++ server/api/activity.get.ts | 4 + server/api/contact.get.ts | 10 +++ server/api/educations.get.ts | 8 +- server/api/experiences.get.ts | 8 +- server/api/hobbies.get.ts | 8 ++ server/api/projects.get.ts | 8 +- server/api/skills.get.ts | 8 +- server/api/uses.get.ts | 4 +- server/api/wakatime.get.ts | 57 +++++++++++++ server/routes/mcp.ts | 152 ++++++++++++++++++++++++++++++++++ 14 files changed, 321 insertions(+), 23 deletions(-) create mode 100644 content/contact.json create mode 100644 content/hobbies.md create mode 100644 server/api/activity.get.ts create mode 100644 server/api/contact.get.ts create mode 100644 server/api/hobbies.get.ts create mode 100644 server/api/wakatime.get.ts diff --git a/content.config.ts b/content.config.ts index 9cd44f5..6dbdeed 100644 --- a/content.config.ts +++ b/content.config.ts @@ -71,6 +71,20 @@ export default defineContentConfig({ endDate: z.string().optional(), location: z.string() }) + }), + contact: defineCollection({ + type: 'data', + source: 'contact.json', + schema: z.object({ + body: z.array(z.object({ + name: z.string(), + url: z.string().url() + })) + }) + }), + hobbies: defineCollection({ + type: 'page', + source: 'hobbies.md' }) } }) diff --git a/content/contact.json b/content/contact.json new file mode 100644 index 0000000..9523e01 --- /dev/null +++ b/content/contact.json @@ -0,0 +1,34 @@ +{ + "body": [ + { + "name": "Personal Email", + "icon": "i-ph-envelope-simple-duotone", + "value": "https://go.arthurdanjou.fr/mail-perso" + }, + { + "name": "Professional Email", + "icon": "i-ph-envelope-simple-duotone", + "value": "https://go.arthurdanjou.fr/mail-pro" + }, + { + "name": "LinkedIn", + "icon": "i-ph:linkedin-logo-duotone", + "value": "https://go.arthurdanjou.fr/linkedin" + }, + { + "name": "GitHub", + "icon": "i-ph:github-logo-duotone", + "value": "https://go.arthurdanjou.fr/github" + }, + { + "name": "Twitter", + "icon": "i-ph:x-logo-duotone", + "value": "https://go.arthurdanjou.fr/twitter" + }, + { + "name": "Discord", + "icon": "i-ph:discord-logo-duotone", + "value": "https://go.arthurdanjou.fr/discord" + } + ] +} \ No newline at end of file diff --git a/content/hobbies.md b/content/hobbies.md new file mode 100644 index 0000000..ccb9e91 --- /dev/null +++ b/content/hobbies.md @@ -0,0 +1,16 @@ +--- +title: Balance and Drive: Beyond the Data +description: Exploring my passions outside of data science and machine learning engineering that fuel my creativity and performance. +--- + +While my passion for data science and machine learning engineering is at the core of what I do, I am convinced that personal balance is the key to performance and creativity. Outside of my technical projects, I nurture this balance through several key interests. + +**Sports** are fundamental to my equilibrium. Playing rugby and volleyball has taught me the importance of collective strategy, communication, and physical commitment. Alongside this, as a long-time supporter of PSG in football, I appreciate the tactical analysis and performance management that occurs at the highest level. + +**Music** is my creative outlet. It trains me to think differently and build harmonious solutions—a skill I readily apply to system design and modeling. + +**Travel** provides me with an essential perspective. Having had the opportunity to discover highly diverse cultures since childhood (such as in Egypt, South Africa, Thailand, and the United States) has profoundly nurtured my curiosity and my ability to adapt to different ways of thinking. This is a flexibility I consider crucial in a constantly evolving field like AI. + +Finally, as a **motorsport** enthusiast, particularly Formula 1, I am fascinated by the pursuit of pure performance, optimization under constraint, and real-time, data-driven strategy. + +These passions are not just an escape; they reinforce my commitment, adaptability, and constant drive to progress. It is this balance that allows me to approach every new challenge, whether academic or technical, with motivation and energy. \ No newline at end of file diff --git a/nuxt.config.ts b/nuxt.config.ts index 03e865f..7fe433a 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -12,8 +12,21 @@ export default defineNuxtConfig({ runtimeConfig: { public: { helloText: 'Hello from the Edge 👋' + }, + discord: { + userId: '', + id: '', + token: '' + }, + wakatime: { + userId: '', + coding: '', + editors: '', + languages: '', + os: '' } }, + future: { compatibilityVersion: 4 }, compatibilityDate: '2025-11-12', diff --git a/server/api/activity.get.ts b/server/api/activity.get.ts new file mode 100644 index 0000000..cefbaca --- /dev/null +++ b/server/api/activity.get.ts @@ -0,0 +1,4 @@ +export default defineEventHandler(async (event) => { + const { discord } = useRuntimeConfig(event) + return await $fetch(`https://api.lanyard.rest/v1/users/${discord.userId}`) +}) diff --git a/server/api/contact.get.ts b/server/api/contact.get.ts new file mode 100644 index 0000000..a783ccf --- /dev/null +++ b/server/api/contact.get.ts @@ -0,0 +1,10 @@ +import { queryCollection } from '@nuxt/content/server' + +export default defineCachedEventHandler(async (event) => { + return await queryCollection(event, 'contact') + .where('extension', '=', 'json') + .first() +}, { + name: 'contact-list', + maxAge: 3600 // 1 hour +}) diff --git a/server/api/educations.get.ts b/server/api/educations.get.ts index 099bd55..4bfc1b4 100644 --- a/server/api/educations.get.ts +++ b/server/api/educations.get.ts @@ -1,11 +1,9 @@ import { queryCollection } from '@nuxt/content/server' export default defineCachedEventHandler(async (event) => { - return { - body: await queryCollection(event, 'education') - .where('extension', '=', 'md') - .all() - } + return await queryCollection(event, 'education') + .where('extension', '=', 'md') + .all() }, { name: 'educations-list', maxAge: 3600 // 1 hour diff --git a/server/api/experiences.get.ts b/server/api/experiences.get.ts index 8b480d6..f4c1556 100644 --- a/server/api/experiences.get.ts +++ b/server/api/experiences.get.ts @@ -1,11 +1,9 @@ import { queryCollection } from '@nuxt/content/server' export default defineCachedEventHandler(async (event) => { - return { - body: await queryCollection(event, 'experiences') - .where('extension', '=', 'md') - .all() - } + return await queryCollection(event, 'experiences') + .where('extension', '=', 'md') + .all() }, { name: 'experiences-list', maxAge: 3600 // 1 hour diff --git a/server/api/hobbies.get.ts b/server/api/hobbies.get.ts new file mode 100644 index 0000000..e0d8a9d --- /dev/null +++ b/server/api/hobbies.get.ts @@ -0,0 +1,8 @@ +import { queryCollection } from '@nuxt/content/server' + +export default defineCachedEventHandler(async (event) => { + return await queryCollection(event, 'hobbies').first() +}, { + name: 'hobbies-list', + maxAge: 3600 // 1 hour +}) diff --git a/server/api/projects.get.ts b/server/api/projects.get.ts index 21ce5ca..3901124 100644 --- a/server/api/projects.get.ts +++ b/server/api/projects.get.ts @@ -1,11 +1,9 @@ import { queryCollection } from '@nuxt/content/server' export default defineCachedEventHandler(async (event) => { - return { - body: await queryCollection(event, 'projects') - .where('extension', '=', 'md') - .all() - } + return await queryCollection(event, 'projects') + .where('extension', '=', 'md') + .all() }, { name: 'projects-list', maxAge: 3600 // 1 hour diff --git a/server/api/skills.get.ts b/server/api/skills.get.ts index 99b5805..19dd7a3 100644 --- a/server/api/skills.get.ts +++ b/server/api/skills.get.ts @@ -1,11 +1,9 @@ import { queryCollection } from '@nuxt/content/server' export default defineCachedEventHandler(async (event) => { - return { - body: await queryCollection(event, 'skills') - .where('extension', '=', 'json') - .all() - } + return await queryCollection(event, 'skills') + .where('extension', '=', 'json') + .first() }, { name: 'skills-list', maxAge: 3600 // 1 hour diff --git a/server/api/uses.get.ts b/server/api/uses.get.ts index 505a4c4..5e864ef 100644 --- a/server/api/uses.get.ts +++ b/server/api/uses.get.ts @@ -15,9 +15,7 @@ export default defineCachedEventHandler(async (event) => { }) } - return { - body: uses_by_categories - } + return uses_by_categories }, { name: 'uses-list', maxAge: 3600 // 1 hour diff --git a/server/api/wakatime.get.ts b/server/api/wakatime.get.ts new file mode 100644 index 0000000..cb99140 --- /dev/null +++ b/server/api/wakatime.get.ts @@ -0,0 +1,57 @@ +import type { H3Event } from 'h3' + +const cachedWakatimeCoding = defineCachedFunction(async (event: H3Event) => { + const config = useRuntimeConfig(event) + + return await $fetch(`https://wakatime.com/share/${config.wakatime.userId}/${config.wakatime.coding}.json`) +}, { + maxAge: 24 * 60 * 60, + name: 'wakatime', + getKey: () => 'coding' +}) + +const cachedWakatimeEditors = defineCachedFunction(async (event: H3Event) => { + const config = useRuntimeConfig(event) + + return await $fetch(`https://wakatime.com/share/${config.wakatime.userId}/${config.wakatime.editors}.json`) +}, { + maxAge: 24 * 60 * 60, + name: 'wakatime', + getKey: () => 'editors' +}) + +const cachedWakatimeOs = defineCachedFunction(async (event: H3Event) => { + const config = useRuntimeConfig(event) + + return await $fetch(`https://wakatime.com/share/${config.wakatime.userId}/${config.wakatime.os}.json`) +}, { + maxAge: 24 * 60 * 60, + name: 'wakatime', + getKey: () => 'os' +}) + +const cachedWakatimeLanguages = defineCachedFunction(async (event: H3Event) => { + const config = useRuntimeConfig(event) + + return await $fetch(`https://wakatime.com/share/${config.wakatime.userId}/${config.wakatime.languages}.json`) +}, { + maxAge: 24 * 60 * 60, + name: 'wakatime', + getKey: () => 'languages' +}) + +export default defineEventHandler(async (event) => { + const [coding, editors, os, languages] = await Promise.all([ + cachedWakatimeCoding(event), + cachedWakatimeEditors(event), + cachedWakatimeOs(event), + cachedWakatimeLanguages(event) + ]) + + return { + coding, + editors, + os, + languages + } +}) diff --git a/server/routes/mcp.ts b/server/routes/mcp.ts index de8876c..33a0a9a 100644 --- a/server/routes/mcp.ts +++ b/server/routes/mcp.ts @@ -104,6 +104,82 @@ function createServer() { } ) + server.registerResource( + 'artmcp-activity', + 'resource://artmcp/activity', + { + title: 'ArtMCP Activity', + description: 'Get realtime activity of Arthur Danjou' + }, + async (uri) => { + const result = await $fetch('/api/activity') + return { + contents: [{ + uri: uri.href, + mimeType: 'application/json', + text: JSON.stringify(result, null, 2) + }] + } + } + ) + + server.registerResource( + 'artmcp-wakatime', + 'resource://artmcp/wakatime', + { + title: 'ArtMCP Wakatime', + description: 'Get Wakatime statistics of Arthur Danjou' + }, + async (uri) => { + const result = await $fetch('/api/wakatime') + return { + contents: [{ + uri: uri.href, + mimeType: 'application/json', + text: JSON.stringify(result, null, 2) + }] + } + } + ) + + server.registerResource( + 'artmcp-contact', + 'resource://artmcp/contact', + { + title: 'ArtMCP Contact', + description: 'Get Contact Information of Arthur Danjou' + }, + async (uri) => { + const result = await $fetch('/api/contact') + return { + contents: [{ + uri: uri.href, + mimeType: 'application/json', + text: JSON.stringify(result, null, 2) + }] + } + } + ) + + server.registerResource( + 'artmcp-contact', + 'resource://artmcp/hobbies', + { + title: 'ArtMCP Hobbies', + description: 'Get Hobbies Information of Arthur Danjou' + }, + async (uri) => { + const result = await $fetch('/api/hobbies') + return { + contents: [{ + uri: uri.href, + mimeType: 'application/json', + text: JSON.stringify(result, null, 2) + }] + } + } + ) + // Tools server.registerTool( 'get_resume_link', @@ -148,6 +224,82 @@ function createServer() { } ) + server.registerPrompt( + 'artmcp-activity', + { + title: 'Get Realtime Activity of Arthur Danjou', + description: 'Get Realtime Activity of Arthur Danjou' + }, + async () => { + return { + messages: [{ + role: 'user', + content: { + type: 'text', + text: `Provide me the realtime activity of Arthur Danjou.` + } + }] + } + } + ) + + server.registerPrompt( + 'artmcp-wakatime', + { + title: 'Get Stats of Arthur Danjou', + description: 'Get Stats of Arthur Danjou powered by Wakatime' + }, + async () => { + return { + messages: [{ + role: 'user', + content: { + type: 'text', + text: `Provide me the stats of Arthur Danjou powered by Wakatime.` + } + }] + } + } + ) + + server.registerPrompt( + 'artmcp-contact', + { + title: 'Get Contact Information of Arthur Danjou', + description: 'Get Contact Information of Arthur Danjou' + }, + async () => { + return { + messages: [{ + role: 'user', + content: { + type: 'text', + text: `How can I contact Arthur Danjou?` + } + }] + } + } + ) + + server.registerPrompt( + 'artmcp-hobbies', + { + title: 'Get Hobbies Information of Arthur Danjou', + description: 'Get Hobbies Information of Arthur Danjou' + }, + async () => { + return { + messages: [{ + role: 'user', + content: { + type: 'text', + text: `What are the hobbies, interests and passions of Arthur Danjou?` + } + }] + } + } + ) + return server }