ワンクリックで
channel-webhooks
Implémentation du webhook Nextcloud Talk Bot. Utilise ce skill pour créer ou modifier app/api/webhook/nextcloud/route.ts.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Implémentation du webhook Nextcloud Talk Bot. Utilise ce skill pour créer ou modifier app/api/webhook/nextcloud/route.ts.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Création et modification des outils smolagents Python de ce projet. Utilise ce skill pour tout ce qui touche à agent/tools/, agent/main.py, agent/gradio_app.py, et les modèles LiteLLM/Ollama/Z.ai.
Patterns pour les routes API Next.js 16 App Router de ce projet — /api/chat, /api/cron, structure des handlers. Utilise ce skill pour créer ou modifier des route.ts.
Patterns Prisma 7 spécifiques à ce projet — gestion conversations, messages, cron jobs. Utilise ce skill pour toute opération DB, migration, ou query Prisma.
| name | channel-webhooks |
| description | Implémentation du webhook Nextcloud Talk Bot. Utilise ce skill pour créer ou modifier app/api/webhook/nextcloud/route.ts. |
import crypto from "crypto"
function verifyNextcloudSignature(req: NextRequest, rawBody: string): boolean {
const random = req.headers.get("X-Nextcloud-Talk-Random")
const signature = req.headers.get("X-Nextcloud-Talk-Signature")
if (!random || !signature) return false
const expected = crypto
.createHmac("sha256", process.env.NEXTCLOUD_BOT_SECRET!)
.update(random + rawBody)
.digest("hex")
return crypto.timingSafeEqual(
Buffer.from(signature.toLowerCase()),
Buffer.from(expected.toLowerCase())
)
}
export async function POST(req: NextRequest) {
const rawBody = await req.text()
if (!verifyNextcloudSignature(req, rawBody)) {
return NextResponse.json({ error: "Invalid signature" }, { status: 401 })
}
const body = JSON.parse(rawBody)
const message = body?.object?.message
const token = body?.object?.token // token de la conversation NC Talk
if (!message) return NextResponse.json({ status: "ignored" })
// Traitement async
processNextcloudMessage(message, token).catch(console.error)
return NextResponse.json({ status: "ok" })
}
async function sendNextcloudMessage(token: string, message: string) {
const url = `${process.env.NEXTCLOUD_BASE_URL}/ocs/v2.php/apps/spreed/api/v1/bot/${process.env.NEXTCLOUD_BOT_ID}/message`
await fetch(url, {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.NEXTCLOUD_BOT_SECRET}`,
"OCS-APIRequest": "true",
"Content-Type": "application/json",
},
body: JSON.stringify({ token, message }),
})
}
crypto.timingSafeEqual pour comparer les signatures (évite timing attacks)