From 3bbb365f53426e7f7894fd70b4b3079d17ffa51d Mon Sep 17 00:00:00 2001 From: alma Date: Sun, 20 Apr 2025 11:51:23 +0200 Subject: [PATCH] carnet api --- app/api/carnet/[date]/route.ts | 45 ++++++++++++++++++++ app/api/carnet/route.ts | 55 ++++++++++++++++++++++++ lib/nextcloud-utils.ts | 17 ++++++++ lib/nextcloud.ts | 76 ++++++++++++++++++++++++++++++++++ 4 files changed, 193 insertions(+) create mode 100644 app/api/carnet/[date]/route.ts create mode 100644 app/api/carnet/route.ts create mode 100644 lib/nextcloud-utils.ts create mode 100644 lib/nextcloud.ts diff --git a/app/api/carnet/[date]/route.ts b/app/api/carnet/[date]/route.ts new file mode 100644 index 00000000..a8c59f92 --- /dev/null +++ b/app/api/carnet/[date]/route.ts @@ -0,0 +1,45 @@ +import { NextResponse } from 'next/server'; +import { getServerSession } from 'next-auth'; +import { getNextCloudService } from '@/lib/nextcloud-utils'; + +export async function GET( + request: Request, + { params }: { params: { date: string } } +) { + try { + const session = await getServerSession(); + if (!session?.user?.email) { + return NextResponse.json( + { error: 'Not authenticated' }, + { status: 401 } + ); + } + + const service = await getNextCloudService(); + const date = new Date(params.date); + + if (isNaN(date.getTime())) { + return NextResponse.json( + { error: 'Invalid date format' }, + { status: 400 } + ); + } + + const content = await service.getNote(session.user.email, date); + + if (!content) { + return NextResponse.json( + { error: 'Note not found' }, + { status: 404 } + ); + } + + return NextResponse.json({ content }); + } catch (error) { + console.error('Failed to get note:', error); + return NextResponse.json( + { error: 'Failed to get note' }, + { status: 500 } + ); + } +} \ No newline at end of file diff --git a/app/api/carnet/route.ts b/app/api/carnet/route.ts new file mode 100644 index 00000000..0580a161 --- /dev/null +++ b/app/api/carnet/route.ts @@ -0,0 +1,55 @@ +import { NextResponse } from 'next/server'; +import { getServerSession } from 'next-auth'; +import { getNextCloudService } from '@/lib/nextcloud-utils'; + +export async function GET(request: Request) { + try { + const session = await getServerSession(); + if (!session?.user?.email) { + return NextResponse.json( + { error: 'Not authenticated' }, + { status: 401 } + ); + } + + const service = await getNextCloudService(); + const notes = await service.listNotes(session.user.email); + + return NextResponse.json({ notes }); + } catch (error) { + console.error('Failed to list notes:', error); + return NextResponse.json( + { error: 'Failed to list notes' }, + { status: 500 } + ); + } +} + +export async function POST(request: Request) { + try { + const session = await getServerSession(); + if (!session?.user?.email) { + return NextResponse.json( + { error: 'Not authenticated' }, + { status: 401 } + ); + } + + const service = await getNextCloudService(); + const { content, date } = await request.json(); + + const fileName = await service.saveNote( + session.user.email, + content, + date ? new Date(date) : undefined + ); + + return NextResponse.json({ fileName }); + } catch (error) { + console.error('Failed to save note:', error); + return NextResponse.json( + { error: 'Failed to save note' }, + { status: 500 } + ); + } +} \ No newline at end of file diff --git a/lib/nextcloud-utils.ts b/lib/nextcloud-utils.ts new file mode 100644 index 00000000..d633dcea --- /dev/null +++ b/lib/nextcloud-utils.ts @@ -0,0 +1,17 @@ +import { getServerSession } from 'next-auth'; +import { NextCloudService } from './nextcloud'; + +export async function getNextCloudService() { + const session = await getServerSession(); + if (!session?.user?.email) { + throw new Error('Not authenticated'); + } + + // Get the NextCloud token from the session + const token = session.accessToken; + if (!token) { + throw new Error('No NextCloud token available'); + } + + return new NextCloudService(token); +} \ No newline at end of file diff --git a/lib/nextcloud.ts b/lib/nextcloud.ts new file mode 100644 index 00000000..1f6423cc --- /dev/null +++ b/lib/nextcloud.ts @@ -0,0 +1,76 @@ +import { WebDAV } from 'webdav'; +import { getSession } from 'next-auth/react'; + +export class NextCloudService { + private webdav: WebDAV; + private basePath: string = '/Personal/Carnet'; + + constructor(token: string) { + this.webdav = new WebDAV( + process.env.NEXTCLOUD_URL + '/remote.php/dav/files', + { + headers: { + Authorization: `Bearer ${token}`, + }, + } + ); + } + + async ensureCarnetFolder(username: string) { + const userPath = `${username}${this.basePath}`; + try { + await this.webdav.exists(userPath); + } catch { + await this.webdav.createDirectory(userPath, { recursive: true }); + } + } + + async saveNote(username: string, content: string, date: Date = new Date()) { + const fileName = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}.md`; + const filePath = `${username}${this.basePath}/${fileName}`; + + await this.ensureCarnetFolder(username); + await this.webdav.putFileContents(filePath, content, { overwrite: true }); + + return fileName; + } + + async getNote(username: string, date: Date) { + const fileName = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}.md`; + const filePath = `${username}${this.basePath}/${fileName}`; + + try { + const content = await this.webdav.getFileContents(filePath, { format: 'text' }); + return content; + } catch (error) { + if (error.response?.status === 404) { + return null; + } + throw error; + } + } + + async listNotes(username: string) { + const userPath = `${username}${this.basePath}`; + try { + const files = await this.webdav.getDirectoryContents(userPath); + return files + .filter(file => file.basename.endsWith('.md')) + .map(file => ({ + date: this.fileNameToDate(file.basename), + name: file.basename, + path: file.filename + })); + } catch (error) { + if (error.response?.status === 404) { + return []; + } + throw error; + } + } + + private fileNameToDate(fileName: string): Date { + const [year, month, day] = fileName.split('.')[0].split('-').map(Number); + return new Date(year, month - 1, day); + } +} \ No newline at end of file