[{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\eslint.config.mjs","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\middleware.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\next.config.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\postcss.config.mjs","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\scripts\\check_port.js","messages":[{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":2,"column":13,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":2,"endColumn":27},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'err' is defined but never used.","line":12,"column":33,"nodeType":"Identifier","messageId":"unusedVar","endLine":12,"endColumn":36}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\r\nconst net = require('net');\r\n\r\nfunction checkConnection(port, host) {\r\n    const client = new net.Socket();\r\n    client.connect(port, host, function() {\r\n        console.log('Connected');\r\n        client.destroy();\r\n        process.exit(0);\r\n    });\r\n\r\n    client.on('error', function(err) {\r\n        console.log('Connection refused/Error. Retrying...');\r\n        client.destroy();\r\n        // Continue but exit with error code if we wanted, but here we just log\r\n    });\r\n}\r\n\r\n// Check repeatedly\r\nlet attempts = 0;\r\nconst interval = setInterval(() => {\r\n    attempts++;\r\n    console.log(`Attempt ${attempts}...`);\r\n    checkConnection(3030, 'localhost');\r\n    if (attempts > 10) {\r\n        console.log(\"Given up.\");\r\n        clearInterval(interval);\r\n        process.exit(1);\r\n    }\r\n}, 2000);\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\scripts\\setup-admin.js","messages":[{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":1,"column":26,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":1,"endColumn":51},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":2,"column":16,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":2,"endColumn":35}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"const { PrismaClient } = require(\"@prisma/client\");\r\nconst bcrypt = require(\"bcryptjs\");\r\n\r\nconst prisma = new PrismaClient();\r\n\r\nasync function main() {\r\n    const email = process.argv[2];\r\n    const password = process.argv[3];\r\n\r\n    if (!email) {\r\n        console.error(\"Please provide email. Usage: node scripts/setup-admin.js <email> [password]\");\r\n        process.exit(1);\r\n    }\r\n\r\n    const existingUser = await prisma.user.findUnique({\r\n        where: { email }\r\n    });\r\n\r\n    if (existingUser) {\r\n        console.log(`User ${email} found. Promoting to SUPERADMIN...`);\r\n        await prisma.user.update({\r\n            where: { email },\r\n            data: { role: 'SUPERADMIN' }\r\n        });\r\n        console.log(\"User promoted successfully!\");\r\n    } else {\r\n        if (!password) {\r\n            console.error(\"Password required for new user. Usage: node scripts/setup-admin.js <email> <password>\");\r\n            process.exit(1);\r\n        }\r\n\r\n        console.log(`Creating new SUPERADMIN user ${email}...`);\r\n        const hashedPassword = await bcrypt.hash(password, 10);\r\n        \r\n        await prisma.user.create({\r\n            data: {\r\n                email,\r\n                name: \"Super Admin\",\r\n                password: hashedPassword,\r\n                role: 'SUPERADMIN'\r\n            }\r\n        });\r\n        console.log(\"Super Admin created successfully!\");\r\n    }\r\n}\r\n\r\nmain()\r\n    .catch((e) => {\r\n        console.error(e);\r\n        process.exit(1);\r\n    })\r\n    .finally(async () => {\r\n        await prisma.$disconnect();\r\n    });\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\scripts\\setup-test-user.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\auth\\[...nextauth]\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\auth\\register\\route.ts","messages":[{"ruleId":"@typescript-eslint/ban-ts-comment","severity":2,"message":"Use \"@ts-expect-error\" instead of \"@ts-ignore\", as \"@ts-ignore\" will do nothing if the following line is error-free.","line":19,"column":9,"nodeType":"Line","messageId":"tsIgnoreInsteadOfExpectError","endLine":19,"endColumn":22,"suggestions":[{"messageId":"replaceTsIgnoreWithTsExpectError","fix":{"range":[602,615],"text":"// @ts-expect-error"},"desc":"Replace \"@ts-ignore\" with \"@ts-expect-error\"."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":56,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":56,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1775,1778],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1775,1778],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse } from \"next/server\";\r\nimport { prisma } from \"@/lib/prisma\";\r\nimport bcrypt from \"bcryptjs\";\r\nimport { z } from \"zod\";\r\n\r\nconst registerSchema = z.object({\r\n    name: z.string().min(2),\r\n    email: z.string().email(),\r\n    password: z.string().min(6),\r\n});\r\n\r\nexport async function POST(req: Request) {\r\n    try {\r\n        const body = await req.json();\r\n        const { email, password, name } = registerSchema.parse(body);\r\n\r\n        // Check if registration is enabled\r\n        const systemConfig = await prisma.systemConfig.findUnique({ where: { id: \"default\" } });\r\n        // @ts-ignore\r\n        if (systemConfig && systemConfig.enableRegistration === false) {\r\n            return NextResponse.json(\r\n                { error: \"Registration is currently disabled by the administrator\" },\r\n                { status: 403 }\r\n            );\r\n        }\r\n\r\n        // Check if user already exists\r\n        const existingUser = await prisma.user.findUnique({\r\n            where: { email },\r\n        });\r\n\r\n        if (existingUser) {\r\n            return NextResponse.json(\r\n                { error: \"User with this email already exists\" },\r\n                { status: 400 }\r\n            );\r\n        }\r\n\r\n        // Hash the password\r\n        const hashedPassword = await bcrypt.hash(password, 10);\r\n\r\n        // Create the user\r\n        const newUser = await prisma.user.create({\r\n            data: {\r\n                name,\r\n                email,\r\n                password: hashedPassword,\r\n            },\r\n        });\r\n\r\n        return NextResponse.json({\r\n            success: true,\r\n            message: \"User registered successfully\",\r\n            user: { id: newUser.id, name: newUser.name, email: newUser.email },\r\n        });\r\n    } catch (error: any) {\r\n        if (error instanceof z.ZodError) {\r\n            return NextResponse.json(\r\n                { error: \"Invalid registration data provided\" },\r\n                { status: 400 }\r\n            );\r\n        }\r\n\r\n        console.error(\"Registration error:\", error);\r\n        return NextResponse.json(\r\n            { error: \"Internal server error during registration\" },\r\n            { status: 500 }\r\n        );\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\autoreplies\\[sessionId]\\[replyId]\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\autoreplies\\[sessionId]\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'isAdmin' is defined but never used.","line":4,"column":50,"nodeType":"Identifier","messageId":"unusedVar","endLine":4,"endColumn":57,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"isAdmin"},"fix":{"range":[187,196],"text":""},"desc":"Remove unused variable \"isAdmin\"."}]},{"ruleId":"@typescript-eslint/ban-ts-comment","severity":2,"message":"Use \"@ts-expect-error\" instead of \"@ts-ignore\", as \"@ts-ignore\" will do nothing if the following line is error-free.","line":87,"column":13,"nodeType":"Line","messageId":"tsIgnoreInsteadOfExpectError","endLine":87,"endColumn":99,"suggestions":[{"messageId":"replaceTsIgnoreWithTsExpectError","fix":{"range":[2957,3043],"text":"// @ts-expect-error: triggerType exists in generated schema but may be stale in editor types"},"desc":"Replace \"@ts-ignore\" with \"@ts-expect-error\"."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'error' is defined but never used.","line":138,"column":14,"nodeType":"Identifier","messageId":"unusedVar","endLine":138,"endColumn":19}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { prisma } from \"@/lib/prisma\";\r\nimport { Prisma } from \"@prisma/client\";\r\nimport { getAuthenticatedUser, canAccessSession, isAdmin } from \"@/lib/api-auth\";\r\n\r\n// GET: List Auto Replies\r\nexport async function GET(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string }> }\r\n) {\r\n    try {\r\n        const { sessionId } = await params;\r\n\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const session = await prisma.session.findUnique({\r\n            where: { sessionId: sessionId },\r\n            select: { id: true }\r\n        });\r\n\r\n        if (!session) {\r\n            return NextResponse.json({ error: \"Session not found\" }, { status: 404 });\r\n        }\r\n\r\n        const rules = await prisma.autoReply.findMany({\r\n            where: { sessionId: session.id },\r\n            orderBy: { createdAt: 'desc' }\r\n        });\r\n\r\n        return NextResponse.json(rules);\r\n\r\n    } catch (error) {\r\n        console.error(\"Fetch auto replies error:\", error);\r\n        return NextResponse.json({ error: \"Internal Server Error\" }, { status: 500 });\r\n    }\r\n}\r\n\r\n// POST: Create Auto Reply\r\nexport async function POST(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string }> }\r\n) {\r\n    try {\r\n        const { sessionId } = await params;\r\n\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const body = await request.json();\r\n        const { keyword, response, matchType, isMedia, mediaUrl } = body;\r\n\r\n        if (!keyword || !response) {\r\n            return NextResponse.json({ error: \"Missing required fields\" }, { status: 400 });\r\n        }\r\n\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const session = await prisma.session.findUnique({\r\n            where: { sessionId: sessionId },\r\n            select: { id: true }\r\n        });\r\n\r\n        if (!session) {\r\n            return NextResponse.json({ error: \"Session not found\" }, { status: 404 });\r\n        }\r\n\r\n        const createData: Prisma.AutoReplyUncheckedCreateInput = {\r\n            sessionId: session.id,\r\n            keyword,\r\n            response,\r\n            matchType: matchType || \"EXACT\",\r\n            isMedia: isMedia || false,\r\n            mediaUrl: mediaUrl || null,\r\n            // @ts-ignore: triggerType exists in generated schema but may be stale in editor types\r\n            triggerType: (body.triggerType as string) || \"ALL\"\r\n        };\r\n\r\n        const newRule = await prisma.autoReply.create({\r\n            data: createData\r\n        });\r\n\r\n        return NextResponse.json(newRule);\r\n\r\n    } catch (error) {\r\n        console.error(\"Create auto reply error:\", error);\r\n        return NextResponse.json({ error: \"Internal Server Error\" }, { status: 500 });\r\n    }\r\n\r\n}\r\n\r\n/**\r\n * @deprecated This endpoint is deprecated. Use DELETE /api/autoreplies/{sessionId}/{replyId} instead.\r\n * This endpoint will be removed in a future version.\r\n */\r\nexport async function DELETE(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string }> }\r\n) {\r\n    console.warn('[DEPRECATED] DELETE /api/autoreplies/{id} is deprecated. Use DELETE /api/autoreplies/{sessionId}/{replyId} instead.');\r\n    const { sessionId: id } = await params;\r\n\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const rule = await prisma.autoReply.findUnique({\r\n            where: { id },\r\n            include: { session: true }\r\n        });\r\n\r\n        if (!rule) {\r\n            return NextResponse.json({ error: \"Rule not found\" }, { status: 404 });\r\n        }\r\n\r\n        const canAccess = await canAccessSession(user.id, user.role, rule.session.sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        await prisma.autoReply.delete({ where: { id } });\r\n        return NextResponse.json({ success: true });\r\n\r\n    } catch (error) {\r\n        return NextResponse.json({ error: \"Internal Server Error\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\autoreplies\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'isAdmin' is defined but never used.","line":3,"column":50,"nodeType":"Identifier","messageId":"unusedVar","endLine":3,"endColumn":57,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"isAdmin"},"fix":{"range":[145,154],"text":""},"desc":"Remove unused variable \"isAdmin\"."}]}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { prisma } from \"@/lib/prisma\";\r\nimport { getAuthenticatedUser, canAccessSession, isAdmin } from \"@/lib/api-auth\";\r\n\r\n/**\r\n * @deprecated These endpoints are deprecated. Use GET/POST /api/autoreplies/{sessionId} instead.\r\n * These endpoints will be removed in a future version.\r\n */\r\n\r\n// GET: List Auto Replies\r\nexport async function GET(request: NextRequest) {\r\n    console.warn('[DEPRECATED] GET /api/autoreplies is deprecated. Use GET /api/autoreplies/{sessionId} instead.');\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const { searchParams } = new URL(request.url);\r\n        const sessionId = searchParams.get(\"sessionId\");\r\n\r\n        if (!sessionId) {\r\n            return NextResponse.json({ error: \"Session ID is required\" }, { status: 400 });\r\n        }\r\n\r\n        // Verify access\r\n        // We need to resolve sessionId (string) to session CUID for permission check? \r\n        // Or canAccessSession takes String? It checks sessionId OR id. So String is fine.\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden\" }, { status: 403 });\r\n        }\r\n\r\n        // Fetch rules\r\n        // AutoReply is linked to Session CUID via `sessionId`.\r\n        // We need to find Session CUID first from the String ID provided in query\r\n        const session = await prisma.session.findUnique({\r\n             where: { sessionId: sessionId },\r\n             select: { id: true }\r\n        });\r\n\r\n        if (!session) {\r\n             return NextResponse.json({ error: \"Session not found\" }, { status: 404 });\r\n        }\r\n\r\n        const rules = await prisma.autoReply.findMany({\r\n            where: { sessionId: session.id },\r\n            orderBy: { createdAt: 'desc' }\r\n        });\r\n\r\n        return NextResponse.json(rules);\r\n\r\n    } catch (error) {\r\n        console.error(\"Fetch auto replies error:\", error);\r\n        return NextResponse.json({ error: \"Internal Server Error\" }, { status: 500 });\r\n    }\r\n}\r\n\r\n// POST: Create Auto Reply\r\nexport async function POST(request: NextRequest) {\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const body = await request.json();\r\n        const { sessionId, keyword, response, matchType } = body;\r\n\r\n        if (!sessionId || !keyword || !response) {\r\n            return NextResponse.json({ error: \"Missing required fields\" }, { status: 400 });\r\n        }\r\n\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden\" }, { status: 403 });\r\n        }\r\n\r\n        // Get Session CUID\r\n        const session = await prisma.session.findUnique({\r\n            where: { sessionId: sessionId },\r\n            select: { id: true }\r\n       });\r\n\r\n       if (!session) {\r\n            return NextResponse.json({ error: \"Session not found\" }, { status: 404 });\r\n       }\r\n\r\n        const newRule = await prisma.autoReply.create({\r\n            data: {\r\n                sessionId: session.id, // Link to CUID\r\n                keyword,\r\n                response,\r\n                matchType: matchType || \"EXACT\",\r\n                isMedia: false\r\n            }\r\n        });\r\n\r\n        return NextResponse.json(newRule);\r\n\r\n    } catch (error) {\r\n        console.error(\"Create auto reply error:\", error);\r\n        return NextResponse.json({ error: \"Internal Server Error\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\chat\\[sessionId]\\[jid]\\archive\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\chat\\[sessionId]\\[jid]\\mute\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\chat\\[sessionId]\\[jid]\\pin\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\chat\\[sessionId]\\[jid]\\presence\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":47,"column":62,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":47,"endColumn":65,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1811,1814],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1811,1814],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\n\r\n// POST: Send presence (typing, recording, online)\r\nexport async function POST(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string; jid: string }> }\r\n) {\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const { sessionId, jid } = await params;\r\n        const body = await request.json();\r\n        const { presence } = body;\r\n\r\n        if (!presence) {\r\n            return NextResponse.json({ \r\n                error: \"presence is required\" \r\n            }, { status: 400 });\r\n        }\r\n\r\n        const validPresences = ['composing', 'recording', 'paused', 'available', 'unavailable'];\r\n        if (!validPresences.includes(presence)) {\r\n            return NextResponse.json({ \r\n                error: `Invalid presence. Must be one of: ${validPresences.join(', ')}` \r\n            }, { status: 400 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        const decodedJid = decodeURIComponent(jid);\r\n\r\n        // Send presence update\r\n        await instance.socket.sendPresenceUpdate(presence as any, decodedJid);\r\n\r\n        return NextResponse.json({ \r\n            success: true,\r\n            message: `Presence '${presence}' sent to ${decodedJid}`\r\n        });\r\n\r\n    } catch (error) {\r\n        console.error(\"Send presence error:\", error);\r\n        return NextResponse.json({ error: \"Failed to send presence\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\chat\\[sessionId]\\[jid]\\profile-picture\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":40,"column":25,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":40,"endColumn":28,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1481,1484],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1481,1484],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\n\r\n// POST: Fetch profile picture URL for a JID\r\nexport async function POST(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string; jid: string }> }\r\n) {\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const { sessionId, jid } = await params;\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        const decodedJid = decodeURIComponent(jid);\r\n\r\n        // Fetch profile picture\r\n        try {\r\n            const profilePicUrl = await instance.socket.profilePictureUrl(decodedJid, 'image');\r\n            \r\n            return NextResponse.json({ \r\n                success: true,\r\n                jid: decodedJid,\r\n                profilePicUrl\r\n            });\r\n        } catch (error: any) {\r\n            // If no profile picture exists\r\n            if (error.message?.includes('404') || error.message?.includes('not-found')) {\r\n                return NextResponse.json({ \r\n                    success: true,\r\n                    jid: decodedJid,\r\n                    profilePicUrl: null,\r\n                    message: \"No profile picture found\"\r\n                });\r\n            }\r\n            throw error;\r\n        }\r\n\r\n    } catch (error) {\r\n        console.error(\"Fetch profile picture error:\", error);\r\n        return NextResponse.json({ error: \"Failed to fetch profile picture\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\chat\\[sessionId]\\[jid]\\read\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\chat\\[sessionId]\\[jid]\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":61,"column":53,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":61,"endColumn":56,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2142,2145],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2142,2145],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":63,"column":61,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":63,"endColumn":64,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2228,2231],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2228,2231],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { prisma } from \"@/lib/prisma\";\r\nimport { NextResponse, NextRequest } from \"next/server\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\n\r\nexport async function GET(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string, jid: string }> }\r\n) {\r\n    const { sessionId, jid } = await params;\r\n    const decodedJid = decodeURIComponent(jid);\r\n\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        // Get the database Session ID (cuid) from the sessionId string\r\n        const session = await prisma.session.findUnique({\r\n            where: { sessionId },\r\n            select: { id: true }\r\n        });\r\n\r\n        if (!session) {\r\n            return NextResponse.json({ error: 'Session not found' }, { status: 404 });\r\n        }\r\n\r\n        const dbSessionId = session.id;\r\n\r\n        const messages = await prisma.message.findMany({\r\n            where: { \r\n                sessionId: dbSessionId,\r\n                remoteJid: decodedJid \r\n            },\r\n            orderBy: { timestamp: 'desc' }, // Fetch NEWEST first\r\n            take: 100\r\n        });\r\n\r\n        // Reverse to show oldest -> newest\r\n        messages.reverse();\r\n\r\n        // Enrich with participant info if it's a group\r\n        if (decodedJid.endsWith('@g.us')) {\r\n            const group = await prisma.group.findUnique({\r\n                where: {\r\n                    sessionId_jid: {\r\n                        sessionId: dbSessionId,\r\n                        jid: decodedJid\r\n                    }\r\n                },\r\n                select: { participants: true }\r\n            });\r\n\r\n            if (group && group.participants) {\r\n                const parts = group.participants as any[];\r\n                \r\n                const enrichedMessages = messages.map((msg: any) => {\r\n                    const sender = msg.senderJid || msg.remoteJid; // Fallback\r\n                    const participant = parts.find(p => p.id === sender);\r\n                    \r\n                    return {\r\n                        ...msg,\r\n                        sender: participant || sender // Replace or add sender field with object or string\r\n                    };\r\n                });\r\n                \r\n                return NextResponse.json(enrichedMessages);\r\n            }\r\n        }\r\n\r\n        return NextResponse.json(messages);\r\n    } catch (error) {\r\n        console.error(\"Fetch messages error:\", error);\r\n        return NextResponse.json({ error: 'Failed to fetch messages' }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\chat\\[sessionId]\\check\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'error' is defined but never used.","line":57,"column":26,"nodeType":"Identifier","messageId":"unusedVar","endLine":57,"endColumn":31}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\n\r\n// POST: Check if number is on WhatsApp\r\nexport async function POST(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string }> }\r\n) {\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const { sessionId } = await params;\r\n        const body = await request.json();\r\n        const { numbers } = body;\r\n\r\n        if (!numbers || !Array.isArray(numbers)) {\r\n            return NextResponse.json({ \r\n                error: \"numbers (array) is required\" \r\n            }, { status: 400 });\r\n        }\r\n\r\n        if (numbers.length === 0) {\r\n            return NextResponse.json({ error: \"At least one number is required\" }, { status: 400 });\r\n        }\r\n\r\n        if (numbers.length > 50) {\r\n            return NextResponse.json({ error: \"Maximum 50 numbers per request\" }, { status: 400 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        // Check numbers on WhatsApp\r\n        const results = await Promise.all(\r\n            numbers.map(async (number: string) => {\r\n                try {\r\n                    const checkResult = await instance.socket!.onWhatsApp(number);\r\n                    // onWhatsApp returns array of results\r\n                    const result = Array.isArray(checkResult) && checkResult.length > 0 ? checkResult[0] : null;\r\n                    return {\r\n                        number,\r\n                        exists: result?.exists || false,\r\n                        jid: result?.jid || null\r\n                    };\r\n                } catch (error) {\r\n                    return {\r\n                        number,\r\n                        exists: false,\r\n                        jid: null,\r\n                        error: \"Invalid number format\"\r\n                    };\r\n                }\r\n            })\r\n        );\r\n\r\n        return NextResponse.json({ \r\n            success: true,\r\n            results\r\n        });\r\n\r\n    } catch (error) {\r\n        console.error(\"Check WhatsApp error:\", error);\r\n        return NextResponse.json({ error: \"Failed to check numbers\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\chat\\[sessionId]\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\chat\\[sessionId]\\send\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":65,"column":97,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":65,"endColumn":100,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2773,2776],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2773,2776],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":75,"column":83,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":75,"endColumn":86,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3176,3179],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3176,3179],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\nimport Sticker from \"wa-sticker-formatter\";\r\n\r\nexport async function POST(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string }> }\r\n) {\r\n    console.warn('[DEPRECATED] POST /api/chat/[sessionId]/send is deprecated. Use POST /api/messages/[sessionId]/[jid]/send instead.');\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const { sessionId } = await params;\r\n        const body = await request.json();\r\n        const { jid, message, mentions } = body;\r\n\r\n        if (!jid || !message) {\r\n            return NextResponse.json({ error: \"jid and message are required\" }, { status: 400 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance) {\r\n            return NextResponse.json({ error: \"Session not found or disconnected\" }, { status: 404 });\r\n        }\r\n\r\n        const socket = instance.socket;\r\n        if (!socket) {\r\n             return NextResponse.json({ error: \"Socket not ready\" }, { status: 503 });\r\n        }\r\n\r\n        // Process Message\r\n        let msgPayload = message;\r\n\r\n        // Custom Handler for Sticker URL\r\n        if (msgPayload.sticker && (msgPayload.sticker.url || typeof msgPayload.sticker === 'string')) {\r\n            const url = msgPayload.sticker.url || msgPayload.sticker;\r\n            \r\n            try {\r\n                const res = await fetch(url);\r\n                if (!res.ok) throw new Error(`Failed to fetch sticker media: ${res.statusText}`);\r\n                const buffer = await res.arrayBuffer();\r\n                \r\n                const sticker = new Sticker(Buffer.from(buffer), {\r\n                    pack: msgPayload.sticker.pack || \"WA-AKG Bot\",\r\n                    author: msgPayload.sticker.author || \"WA-AKG\",\r\n                    type: \"full\",\r\n                    quality: 50\r\n                });\r\n\r\n                const stickerBuffer = await sticker.toBuffer();\r\n                msgPayload = { sticker: stickerBuffer };\r\n\r\n            } catch (e) {\r\n                console.error(\"Sticker generation from URL failed:\", e);\r\n                return NextResponse.json({ error: `Failed to generate sticker from URL: ${(e as any).message}` }, { status: 400 });\r\n            }\r\n        }\r\n\r\n        // Send Message\r\n        // Ensure mentions are passed in options and also in message content if it's a text message\r\n        if (msgPayload.text && mentions && Array.isArray(mentions)) {\r\n             msgPayload.mentions = mentions;\r\n        }\r\n\r\n        await socket.sendMessage(jid, msgPayload, { mentions: mentions || [] } as any);\r\n\r\n        return NextResponse.json({ success: true });\r\n    } catch (error) {\r\n        console.error(\"Send message error:\", error);\r\n        return NextResponse.json({ error: \"Failed to send message\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\chat\\archive\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\chat\\check\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'error' is defined but never used.","line":58,"column":26,"nodeType":"Identifier","messageId":"unusedVar","endLine":58,"endColumn":31}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\n\r\n/**\r\n * @deprecated This endpoint is deprecated. Use POST /api/chat/{sessionId}/check instead.\r\n * This endpoint will be removed in a future version.\r\n */\r\n// POST: Check if number is on WhatsApp\r\nexport async function POST(request: NextRequest) {\r\n    console.warn('[DEPRECATED] POST /api/chat/check is deprecated. Use POST /api/chat/{sessionId}/check instead.');\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const body = await request.json();\r\n        const { sessionId, numbers } = body;\r\n\r\n        if (!sessionId || !numbers || !Array.isArray(numbers)) {\r\n            return NextResponse.json({ \r\n                error: \"sessionId and numbers (array) are required\" \r\n            }, { status: 400 });\r\n        }\r\n\r\n        if (numbers.length === 0) {\r\n            return NextResponse.json({ error: \"At least one number is required\" }, { status: 400 });\r\n        }\r\n\r\n        if (numbers.length > 50) {\r\n            return NextResponse.json({ error: \"Maximum 50 numbers per request\" }, { status: 400 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        // Check numbers on WhatsApp\r\n        const results = await Promise.all(\r\n            numbers.map(async (number: string) => {\r\n                try {\r\n                    const checkResult = await instance.socket!.onWhatsApp(number);\r\n                    // onWhatsApp returns array of results\r\n                    const result = Array.isArray(checkResult) && checkResult.length > 0 ? checkResult[0] : null;\r\n                    return {\r\n                        number,\r\n                        exists: result?.exists || false,\r\n                        jid: result?.jid || null\r\n                    };\r\n                } catch (error) {\r\n                    return {\r\n                        number,\r\n                        exists: false,\r\n                        jid: null,\r\n                        error: \"Invalid number format\"\r\n                    };\r\n                }\r\n            })\r\n        );\r\n\r\n        return NextResponse.json({ \r\n            success: true,\r\n            results\r\n        });\r\n\r\n    } catch (error) {\r\n        console.error(\"Check WhatsApp error:\", error);\r\n        return NextResponse.json({ error: \"Failed to check numbers\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\chat\\mute\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\chat\\pin\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\chat\\presence\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":46,"column":62,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":46,"endColumn":65,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1977,1980],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1977,1980],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\n\r\n/**\r\n * @deprecated This endpoint is deprecated. Use POST /api/chat/{sessionId}/{jid}/presence instead.\r\n * This endpoint will be removed in a future version.\r\n */\r\n// POST: Send presence (typing, recording, online)\r\nexport async function POST(request: NextRequest) {\r\n    console.warn('[DEPRECATED] POST /api/chat/presence is deprecated. Use POST /api/chat/{sessionId}/{jid}/presence instead.');\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const body = await request.json();\r\n        const { sessionId, jid, presence } = body;\r\n\r\n        if (!sessionId || !jid || !presence) {\r\n            return NextResponse.json({ \r\n                error: \"sessionId, jid, and presence are required\" \r\n            }, { status: 400 });\r\n        }\r\n\r\n        const validPresences = ['composing', 'recording', 'paused', 'available', 'unavailable'];\r\n        if (!validPresences.includes(presence)) {\r\n            return NextResponse.json({ \r\n                error: `Invalid presence. Must be one of: ${validPresences.join(', ')}` \r\n            }, { status: 400 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        // Send presence update\r\n        await instance.socket.sendPresenceUpdate(presence as any, jid);\r\n\r\n        return NextResponse.json({ \r\n            success: true,\r\n            message: `Presence '${presence}' sent to ${jid}`\r\n        });\r\n\r\n    } catch (error) {\r\n        console.error(\"Send presence error:\", error);\r\n        return NextResponse.json({ error: \"Failed to send presence\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\chat\\profile-picture\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":47,"column":25,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":47,"endColumn":28,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1857,1860],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1857,1860],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\n\r\n/**\r\n * @deprecated This endpoint is deprecated. Use POST /api/chat/{sessionId}/{jid}/profile-picture instead.\r\n * This endpoint will be removed in a future version.\r\n */\r\n// POST: Fetch profile picture URL for a JID\r\nexport async function POST(request: NextRequest) {\r\n    console.warn('[DEPRECATED] POST /api/chat/profile-picture is deprecated. Use POST /api/chat/{sessionId}/{jid}/profile-picture instead.');\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const body = await request.json();\r\n        const { sessionId, jid } = body;\r\n\r\n        if (!sessionId || !jid) {\r\n            return NextResponse.json({ \r\n                error: \"sessionId and jid are required\" \r\n            }, { status: 400 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        // Fetch profile picture\r\n        try {\r\n            const profilePicUrl = await instance.socket.profilePictureUrl(jid, 'image');\r\n            \r\n            return NextResponse.json({ \r\n                success: true,\r\n                jid,\r\n                profilePicUrl\r\n            });\r\n        } catch (error: any) {\r\n            // If no profile picture exists\r\n            if (error.message?.includes('404') || error.message?.includes('not-found')) {\r\n                return NextResponse.json({ \r\n                    success: true,\r\n                    jid,\r\n                    profilePicUrl: null,\r\n                    message: \"No profile picture found\"\r\n                });\r\n            }\r\n            throw error;\r\n        }\r\n\r\n    } catch (error) {\r\n        console.error(\"Fetch profile picture error:\", error);\r\n        return NextResponse.json({ error: \"Failed to fetch profile picture\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\chat\\read\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\chat\\send\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":67,"column":97,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":67,"endColumn":100,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2881,2884],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2881,2884],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":77,"column":83,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":77,"endColumn":86,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3284,3287],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3284,3287],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\nimport Sticker from \"wa-sticker-formatter\";\r\n\r\n/**\r\n * @deprecated This endpoint is deprecated. Use POST /api/chat/{sessionId}/send instead.\r\n * This endpoint will be removed in a future version.\r\n */\r\nexport async function POST(request: NextRequest) {\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const body = await request.json();\r\n        const { sessionId, jid, message, mentions } = body;\r\n\r\n        // Log deprecation warning\r\n        console.warn('[DEPRECATED] POST /api/chat/send is deprecated. Use POST /api/messages/[sessionId]/[jid]/send instead.');\r\n\r\n        if (!sessionId || !jid || !message) {\r\n            return NextResponse.json({ error: \"sessionId, jid, and message are required\" }, { status: 400 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance) {\r\n            return NextResponse.json({ error: \"Session not found or disconnected\" }, { status: 404 });\r\n        }\r\n\r\n        const socket = instance.socket;\r\n        if (!socket) {\r\n             return NextResponse.json({ error: \"Socket not ready\" }, { status: 503 });\r\n        }\r\n\r\n        // Process Message\r\n        let msgPayload = message;\r\n\r\n        // Custom Handler for Sticker URL\r\n        if (msgPayload.sticker && (msgPayload.sticker.url || typeof msgPayload.sticker === 'string')) {\r\n            const url = msgPayload.sticker.url || msgPayload.sticker;\r\n            \r\n            try {\r\n                const res = await fetch(url);\r\n                if (!res.ok) throw new Error(`Failed to fetch sticker media: ${res.statusText}`);\r\n                const buffer = await res.arrayBuffer();\r\n                \r\n                const sticker = new Sticker(Buffer.from(buffer), {\r\n                    pack: msgPayload.sticker.pack || \"WA-AKG Bot\",\r\n                    author: msgPayload.sticker.author || \"WA-AKG\",\r\n                    type: \"full\",\r\n                    quality: 50\r\n                });\r\n\r\n                const stickerBuffer = await sticker.toBuffer();\r\n                msgPayload = { sticker: stickerBuffer };\r\n\r\n            } catch (e) {\r\n                console.error(\"Sticker generation from URL failed:\", e);\r\n                return NextResponse.json({ error: `Failed to generate sticker from URL: ${(e as any).message}` }, { status: 400 });\r\n            }\r\n        }\r\n\r\n        // Send Message\r\n        // Ensure mentions are passed in options and also in message content if it's a text message\r\n        if (msgPayload.text && mentions && Array.isArray(mentions)) {\r\n             msgPayload.mentions = mentions;\r\n        }\r\n\r\n        await socket.sendMessage(jid, msgPayload, { mentions: mentions || [] } as any);\r\n\r\n        return NextResponse.json({ success: true });\r\n    } catch (error) {\r\n        console.error(\"Send message error:\", error);\r\n        return NextResponse.json({ error: \"Failed to send message\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\chats\\[sessionId]\\by-label\\[labelId]\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\chats\\by-label\\[labelId]\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\contacts\\[sessionId]\\[jid]\\block\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\contacts\\[sessionId]\\[jid]\\unblock\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\contacts\\[sessionId]\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":38,"column":22,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":38,"endColumn":25,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1415,1418],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1415,1418],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\r\nimport { NextRequest, NextResponse } from \"next/server\";\r\nimport { prisma } from \"@/lib/prisma\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\n\r\nexport async function GET(\r\n    req: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string }> }\r\n) {\r\n    try {\r\n        const user = await getAuthenticatedUser(req);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const { sessionId } = await params;\r\n        const { searchParams } = new URL(req.url);\r\n        const page = parseInt(searchParams.get(\"page\") || \"1\");\r\n        const limit = parseInt(searchParams.get(\"limit\") || \"10\");\r\n        const search = searchParams.get(\"search\") || \"\";\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        // Resolve sessionId string to database ID (CUID)\r\n        const sessionData = await prisma.session.findUnique({\r\n            where: { sessionId: sessionId },\r\n            select: { id: true }\r\n        });\r\n\r\n        if (!sessionData) {\r\n            return NextResponse.json({ error: \"Session not found\" }, { status: 404 });\r\n        }\r\n\r\n        const where: any = {\r\n            sessionId: sessionData.id,\r\n        };\r\n\r\n        if (search) {\r\n            where.OR = [\r\n                { name: { contains: search } },\r\n                { notify: { contains: search } },\r\n                { verifiedName: { contains: search } },\r\n                { jid: { contains: search } },\r\n                { remoteJidAlt: { contains: search } }\r\n            ];\r\n        }\r\n\r\n        const [contacts, total] = await Promise.all([\r\n            prisma.contact.findMany({\r\n                where,\r\n                skip: (page - 1) * limit,\r\n                take: limit,\r\n                orderBy: { name: 'asc' }\r\n            }),\r\n            prisma.contact.count({ where })\r\n        ]);\r\n\r\n        return NextResponse.json({\r\n            data: contacts,\r\n            meta: {\r\n                total,\r\n                page,\r\n                limit,\r\n                totalPages: Math.ceil(total / limit)\r\n            }\r\n        });\r\n    } catch (error) {\r\n        console.error(\"Error fetching contacts:\", error);\r\n        return NextResponse.json({ error: \"Internal Server Error\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\contacts\\block\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\contacts\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":35,"column":18,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":35,"endColumn":21,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1249,1252],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1249,1252],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\r\nimport { NextRequest, NextResponse } from \"next/server\";\r\nimport { prisma } from \"@/lib/prisma\";\r\nimport { auth } from \"@/lib/auth\";\r\n\r\nexport async function GET(req: NextRequest) {\r\n    const session = await auth();\r\n    if (!session) return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n\r\n    const { searchParams } = new URL(req.url);\r\n    const sessionIdParam = searchParams.get(\"sessionId\");\r\n\r\n    if (sessionIdParam) {\r\n        console.warn(`[DEPRECATED] GET /api/contacts?sessionId=${sessionIdParam} is deprecated. Use GET /api/contacts/${sessionIdParam} instead.`);\r\n    }\r\n\r\n    const page = parseInt(searchParams.get(\"page\") || \"1\");\r\n    const limit = parseInt(searchParams.get(\"limit\") || \"10\");\r\n    const search = searchParams.get(\"search\") || \"\";\r\n\r\n    if (!sessionIdParam) {\r\n        return NextResponse.json({ error: \"Session ID is required\" }, { status: 400 });\r\n    }\r\n\r\n    // Resolve sessionId string to database ID (CUID)\r\n    const sessionData = await prisma.session.findUnique({\r\n        where: { sessionId: sessionIdParam },\r\n        select: { id: true }\r\n    });\r\n\r\n    if (!sessionData) {\r\n        return NextResponse.json({ error: \"Session not found\" }, { status: 404 });\r\n    }\r\n\r\n    const where: any = {\r\n        sessionId: sessionData.id,\r\n    };\r\n\r\n    if (search) {\r\n        where.OR = [\r\n            { name: { contains: search } }, // Case insensitive usually handled by DB collation or use mode: 'insensitive' if Postgres\r\n            { notify: { contains: search } },\r\n            { verifiedName: { contains: search } },\r\n            { jid: { contains: search } },\r\n            { remoteJidAlt: { contains: search } }\r\n        ];\r\n    }\r\n\r\n    try {\r\n        const [contacts, total] = await Promise.all([\r\n            prisma.contact.findMany({\r\n                where,\r\n                skip: (page - 1) * limit,\r\n                take: limit,\r\n                orderBy: { name: 'asc' } // Default sort\r\n            }),\r\n            prisma.contact.count({ where })\r\n        ]);\r\n\r\n        return NextResponse.json({\r\n            data: contacts,\r\n            meta: {\r\n                total,\r\n                page,\r\n                limit,\r\n                totalPages: Math.ceil(total / limit)\r\n            }\r\n        });\r\n    } catch (error) {\r\n        console.error(\"Error fetching contacts:\", error);\r\n        return NextResponse.json({ error: \"Internal Server Error\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\contacts\\unblock\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\docs\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\groups\\[sessionId]\\[jid]\\description\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":46,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":46,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1834,1837],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1834,1837],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\n\r\n// PUT: Update group description\r\nexport async function PUT(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string; jid: string }> }\r\n) {\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n        \r\n        const { sessionId, jid } = await params;\r\n        const decodedJid = decodeURIComponent(jid);\r\n        const body = await request.json();\r\n        const { description } = body;\r\n\r\n        // Description can be empty string to remove\r\n        if (description && description.length > 512) {\r\n            return NextResponse.json({ error: \"Description must be 512 characters or less\" }, { status: 400 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        // Update group description\r\n        await instance.socket.groupUpdateDescription(decodedJid, description || \"\");\r\n\r\n        return NextResponse.json({ \r\n            success: true, \r\n            message: description ? \"Group description updated successfully\" : \"Group description removed\",\r\n            description: description || null\r\n        });\r\n\r\n    } catch (error: any) {\r\n        console.error(\"Update group description error:\", error);\r\n        \r\n        // Handle specific errors\r\n        if (error.message?.includes(\"not-admin\") || error.message?.includes(\"forbidden\")) {\r\n            return NextResponse.json({ error: \"Bot must be admin to update group description\" }, { status: 403 });\r\n        }\r\n        \r\n        return NextResponse.json({ error: \"Failed to update group description\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\groups\\[sessionId]\\[jid]\\ephemeral\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":63,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":63,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2442,2445],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2442,2445],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\n\r\n// PUT: Toggle ephemeral/disappearing messages\r\nexport async function PUT(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string; jid: string }> }\r\n) {\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n        \r\n        const { sessionId, jid } = await params;\r\n        const decodedJid = decodeURIComponent(jid);\r\n        const body = await request.json();\r\n        const { expiration } = body; // expiration is duration in seconds\r\n\r\n        if (expiration === undefined) {\r\n            return NextResponse.json({ \r\n                error: \"expiration is required\" \r\n            }, { status: 400 });\r\n        }\r\n\r\n        // Expiration values: 0 (off), 86400 (1 day), 604800 (7 days), 7776000 (90 days)\r\n        const validExpirations = [0, 86400, 604800, 7776000];\r\n        if (!validExpirations.includes(expiration)) {\r\n            return NextResponse.json({ \r\n                error: \"Invalid expiration. Must be 0 (off), 86400 (1 day), 604800 (7 days), or 7776000 (90 days)\" \r\n            }, { status: 400 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        // Toggle ephemeral messages\r\n        await instance.socket.groupToggleEphemeral(decodedJid, expiration);\r\n\r\n        const expirationLabels: Record<number, string> = {\r\n            0: 'off',\r\n            86400: '1 day',\r\n            604800: '7 days',\r\n            7776000: '90 days'\r\n        };\r\n\r\n        return NextResponse.json({ \r\n            success: true,\r\n            message: `Disappearing messages ${expiration === 0 ? 'disabled' : 'enabled'}`,\r\n            expiration,\r\n            expirationLabel: expirationLabels[expiration]\r\n        });\r\n\r\n    } catch (error: any) {\r\n        console.error(\"Toggle ephemeral error:\", error);\r\n        \r\n        if (error.message?.includes(\"not-admin\") || error.message?.includes(\"forbidden\")) {\r\n            return NextResponse.json({ \r\n                error: \"Bot must be admin to toggle ephemeral messages\" \r\n            }, { status: 403 });\r\n        }\r\n        \r\n        return NextResponse.json({ error: \"Failed to toggle ephemeral messages\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\groups\\[sessionId]\\[jid]\\invite\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":39,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":39,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1407,1410],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1407,1410],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":85,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":85,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3102,3105],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3102,3105],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\n\r\n// GET: Fetch group invite code\r\nexport async function GET(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string; jid: string }> }\r\n) {\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const { sessionId, jid } = await params;\r\n        const decodedJid = decodeURIComponent(jid);\r\n\r\n        // Check verification\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        // Get invite code\r\n        const inviteCode = await instance.socket.groupInviteCode(decodedJid);\r\n\r\n        return NextResponse.json({ \r\n            success: true,\r\n            inviteCode,\r\n            inviteUrl: `https://chat.whatsapp.com/${inviteCode}`\r\n        });\r\n\r\n    } catch (error: any) {\r\n        console.error(\"Fetch invite code error:\", error);\r\n        \r\n        if (error.message?.includes(\"not-admin\") || error.message?.includes(\"forbidden\")) {\r\n            return NextResponse.json({ error: \"Bot must be admin to fetch invite code\" }, { status: 403 });\r\n        }\r\n        \r\n        return NextResponse.json({ error: \"Failed to fetch invite code\" }, { status: 500 });\r\n    }\r\n}\r\n\r\n// PUT: Revoke group invite code\r\nexport async function PUT(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string; jid: string }> }\r\n) {\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const { sessionId, jid } = await params;\r\n        const decodedJid = decodeURIComponent(jid);\r\n\r\n        // Check verification\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        // Revoke invite code\r\n        const newInviteCode = await instance.socket.groupRevokeInvite(decodedJid);\r\n\r\n        return NextResponse.json({ \r\n            success: true,\r\n            message: \"Invite code revoked successfully\",\r\n            newInviteCode,\r\n            inviteUrl: `https://chat.whatsapp.com/${newInviteCode}`\r\n        });\r\n\r\n    } catch (error: any) {\r\n        console.error(\"Revoke invite code error:\", error);\r\n        \r\n        if (error.message?.includes(\"not-admin\") || error.message?.includes(\"forbidden\")) {\r\n            return NextResponse.json({ error: \"Bot must be admin to revoke invite code\" }, { status: 403 });\r\n        }\r\n        \r\n        return NextResponse.json({ error: \"Failed to revoke invite code\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\groups\\[sessionId]\\[jid]\\leave\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":38,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":38,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1338,1341],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1338,1341],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\n\r\n// POST: Leave group\r\nexport async function POST(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string; jid: string }> }\r\n) {\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n        \r\n        const { sessionId, jid } = await params;\r\n        const decodedJid = decodeURIComponent(jid);\r\n\r\n        // Check verification\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        // Leave group\r\n        await instance.socket.groupLeave(decodedJid);\r\n\r\n        return NextResponse.json({ \r\n            success: true,\r\n            message: \"Successfully left the group\"\r\n        });\r\n\r\n    } catch (error: any) {\r\n        console.error(\"Leave group error:\", error);\r\n        return NextResponse.json({ error: \"Failed to leave group\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\groups\\[sessionId]\\[jid]\\members\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":53,"column":23,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":53,"endColumn":26,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2114,2117],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2114,2117],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":62,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":62,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2316,2319],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2316,2319],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\n\r\n// PUT: Update group members (add, remove, promote, demote)\r\nexport async function PUT(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string; jid: string }> }\r\n) {\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n        \r\n        const { sessionId, jid } = await params;\r\n        const decodedJid = decodeURIComponent(jid);\r\n        const body = await request.json();\r\n        const { action, participants } = body;\r\n\r\n        if (!action || !participants || !Array.isArray(participants)) {\r\n            return NextResponse.json({ \r\n                error: \"action and participants (array) are required\" \r\n            }, { status: 400 });\r\n        }\r\n\r\n        const validActions = ['add', 'remove', 'promote', 'demote'];\r\n        if (!validActions.includes(action)) {\r\n            return NextResponse.json({ \r\n                error: `Invalid action. Must be one of: ${validActions.join(', ')}` \r\n            }, { status: 400 });\r\n        }\r\n\r\n        if (participants.length === 0) {\r\n            return NextResponse.json({ error: \"Participants array cannot be empty\" }, { status: 400 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        // Execute the action\r\n        const result = await instance.socket.groupParticipantsUpdate(\r\n            decodedJid,\r\n            participants,\r\n            action as any\r\n        );\r\n\r\n        return NextResponse.json({ \r\n            success: true,\r\n            message: `Successfully ${action}ed participants`,\r\n            result\r\n        });\r\n\r\n    } catch (error: any) {\r\n        console.error(\"Update group members error:\", error);\r\n        \r\n        if (error.message?.includes(\"not-admin\") || error.message?.includes(\"forbidden\")) {\r\n            return NextResponse.json({ \r\n                error: \"Bot must be admin to update group members\" \r\n            }, { status: 403 });\r\n        }\r\n        \r\n        if (error.message?.includes(\"not-authorized\")) {\r\n            return NextResponse.json({ \r\n                error: \"Not authorized to perform this action\" \r\n            }, { status: 403 });\r\n        }\r\n        \r\n        return NextResponse.json({ error: \"Failed to update group members\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\groups\\[sessionId]\\[jid]\\picture\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":44,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":44,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1680,1683],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1680,1683],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":86,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":86,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3272,3275],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3272,3275],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\n\r\n// PUT: Update group picture\r\nexport async function PUT(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string; jid: string }> }\r\n) {\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const { sessionId, jid } = await params;\r\n        const decodedJid = decodeURIComponent(jid);\r\n        const formData = await request.formData();\r\n        const file = formData.get(\"file\") as File;\r\n\r\n        if (!file) {\r\n            return NextResponse.json({ error: \"file is required\" }, { status: 400 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        // Convert File to Buffer\r\n        const buffer = Buffer.from(await file.arrayBuffer());\r\n\r\n        // Update group picture\r\n        await instance.socket.updateProfilePicture(decodedJid, buffer);\r\n\r\n        return NextResponse.json({ success: true, message: \"Group picture updated successfully\" });\r\n\r\n    } catch (error: any) {\r\n        console.error(\"Update group picture error:\", error);\r\n        \r\n        // Handle specific errors\r\n        if (error.message?.includes(\"not-admin\") || error.message?.includes(\"forbidden\")) {\r\n            return NextResponse.json({ error: \"Bot must be admin to update group picture\" }, { status: 403 });\r\n        }\r\n        \r\n        return NextResponse.json({ error: \"Failed to update group picture\" }, { status: 500 });\r\n    }\r\n}\r\n\r\n// DELETE: Remove group picture\r\nexport async function DELETE(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string; jid: string }> }\r\n) {\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const { sessionId, jid } = await params;\r\n        const decodedJid = decodeURIComponent(jid);\r\n\r\n        // Check verification\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        // Remove group picture\r\n        await instance.socket.removeProfilePicture(decodedJid);\r\n\r\n        return NextResponse.json({ success: true, message: \"Group picture removed successfully\" });\r\n\r\n    } catch (error: any) {\r\n        console.error(\"Remove group picture error:\", error);\r\n        \r\n        if (error.message?.includes(\"not-admin\") || error.message?.includes(\"forbidden\")) {\r\n            return NextResponse.json({ error: \"Bot must be admin to remove group picture\" }, { status: 403 });\r\n        }\r\n        \r\n        return NextResponse.json({ error: \"Failed to remove group picture\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\groups\\[sessionId]\\[jid]\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'e' is defined but never used.","line":43,"column":18,"nodeType":"Identifier","messageId":"unusedVar","endLine":43,"endColumn":19}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\n\r\n// GET: Get group details\r\nexport async function GET(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string; jid: string }> }\r\n) {\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n        \r\n        const { sessionId, jid } = await params;\r\n        const decodedJid = decodeURIComponent(jid);\r\n\r\n        // Check verification\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n             return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n             return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        // Fetch Group Metadata\r\n        let metadata;\r\n        try {\r\n            metadata = await instance.socket.groupMetadata(decodedJid);\r\n        } catch (e) {\r\n            console.error(\"Failed to fetch group metadata:\", e);\r\n             return NextResponse.json({ error: \"Failed to fetch group metadata. Ensure the bot is in the group.\" }, { status: 404 });\r\n        }\r\n\r\n        // Fetch Profile Picture\r\n        let ppUrl = null;\r\n        try {\r\n            ppUrl = await instance.socket.profilePictureUrl(decodedJid, 'image');\r\n        } catch (e) {\r\n            // Ignore error if no PP\r\n        }\r\n\r\n        return NextResponse.json({\r\n            ...metadata,\r\n            pictureUrl: ppUrl\r\n        });\r\n\r\n    } catch (error) {\r\n        console.error(\"Get group details error:\", error);\r\n        return NextResponse.json({ error: \"Internal Server Error\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\groups\\[sessionId]\\[jid]\\settings\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'value' is assigned a value but never used.","line":19,"column":26,"nodeType":"Identifier","messageId":"unusedVar","endLine":19,"endColumn":31},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":47,"column":73,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":47,"endColumn":76,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1942,1945],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1942,1945],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":55,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":55,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2145,2148],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2145,2148],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\n\r\n// PUT: Update group settings\r\nexport async function PUT(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string; jid: string }> }\r\n) {\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const { sessionId, jid } = await params;\r\n        const decodedJid = decodeURIComponent(jid);\r\n        const body = await request.json();\r\n        const { setting, value } = body;\r\n\r\n        if (!setting) {\r\n            return NextResponse.json({ \r\n                error: \"setting is required\" \r\n            }, { status: 400 });\r\n        }\r\n\r\n        // Valid settings: 'announcement' (only admins can send messages), 'locked' (only admins can edit group info), 'not_announcement', 'unlocked'\r\n        const validSettings = ['announcement', 'not_announcement', 'locked', 'unlocked'];\r\n        if (!validSettings.includes(setting)) {\r\n            return NextResponse.json({ \r\n                error: `Invalid setting. Must be one of: ${validSettings.join(', ')}` \r\n            }, { status: 400 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        // Update group setting\r\n        await instance.socket.groupSettingUpdate(decodedJid, setting as any);\r\n\r\n        return NextResponse.json({ \r\n            success: true,\r\n            message: `Group setting '${setting}' updated successfully`,\r\n            setting\r\n        });\r\n\r\n    } catch (error: any) {\r\n        console.error(\"Update group settings error:\", error);\r\n        \r\n        if (error.message?.includes(\"not-admin\") || error.message?.includes(\"forbidden\")) {\r\n            return NextResponse.json({ \r\n                error: \"Bot must be admin to update group settings\" \r\n            }, { status: 403 });\r\n        }\r\n        \r\n        return NextResponse.json({ error: \"Failed to update group settings\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\groups\\[sessionId]\\[jid]\\subject\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":49,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":49,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1784,1787],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1784,1787],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\n\r\n// PUT: Update group subject/name\r\nexport async function PUT(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string; jid: string }> }\r\n) {\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const { sessionId, jid } = await params;\r\n        const decodedJid = decodeURIComponent(jid);\r\n        const body = await request.json();\r\n        const { subject } = body;\r\n\r\n        if (!subject) {\r\n            return NextResponse.json({ error: \"subject is required\" }, { status: 400 });\r\n        }\r\n\r\n        if (subject.length > 100) {\r\n            return NextResponse.json({ error: \"Subject must be 100 characters or less\" }, { status: 400 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        // Update group subject\r\n        await instance.socket.groupUpdateSubject(decodedJid, subject);\r\n\r\n        return NextResponse.json({ \r\n            success: true, \r\n            message: \"Group subject updated successfully\",\r\n            subject \r\n        });\r\n\r\n    } catch (error: any) {\r\n        console.error(\"Update group subject error:\", error);\r\n        \r\n        // Handle specific errors\r\n        if (error.message?.includes(\"not-admin\") || error.message?.includes(\"forbidden\")) {\r\n            return NextResponse.json({ error: \"Bot must be admin to update group subject\" }, { status: 403 });\r\n        }\r\n        \r\n        return NextResponse.json({ error: \"Failed to update group subject\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\groups\\[sessionId]\\create\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\groups\\[sessionId]\\invite\\accept\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":44,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":44,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1571,1574],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1571,1574],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\n\r\n// POST: Accept group invite\r\nexport async function POST(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string }> }\r\n) {\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const { sessionId } = await params;\r\n        const body = await request.json();\r\n        const { inviteCode } = body;\r\n\r\n        if (!inviteCode) {\r\n            return NextResponse.json({ error: \"inviteCode is required\" }, { status: 400 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        // Accept group invite\r\n        const result = await instance.socket.groupAcceptInvite(inviteCode);\r\n\r\n        return NextResponse.json({  \r\n            success: true,\r\n            message: \"Group invite accepted successfully\",\r\n            groupJid: result\r\n        });\r\n\r\n    } catch (error: any) {\r\n        console.error(\"Accept group invite error:\", error);\r\n        \r\n        if (error.message?.includes(\"invalid\") || error.message?.includes(\"expired\")) {\r\n            return NextResponse.json({ error: \"Invalid or expired invite code\" }, { status: 400 });\r\n        }\r\n        \r\n        return NextResponse.json({ error: \"Failed to accept group invite\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\groups\\[sessionId]\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\groups\\create\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\groups\\invite\\accept\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":47,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":47,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1826,1829],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1826,1829],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\n\r\n// POST: Accept group invite using invite code\r\n/**\r\n * @deprecated This endpoint is deprecated. Use POST /api/groups/{sessionId}/invite/accept instead.\r\n * This endpoint will be removed in a future version.\r\n */\r\nexport async function POST(\r\n    request: NextRequest\r\n) {\r\n    console.warn('[DEPRECATED] POST /api/groups/invite/accept is deprecated. Use POST /api/groups/{sessionId}/invite/accept instead.');\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const body = await request.json();\r\n        const { sessionId, inviteCode } = body;\r\n\r\n        if (!sessionId || !inviteCode) {\r\n            return NextResponse.json({ error: \"sessionId and inviteCode are required\" }, { status: 400 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        // Accept group invite\r\n        const result = await instance.socket.groupAcceptInvite(inviteCode);\r\n\r\n        return NextResponse.json({  \r\n            success: true,\r\n            message: \"Group invite accepted successfully\",\r\n            groupJid: result\r\n        });\r\n\r\n    } catch (error: any) {\r\n        console.error(\"Accept group invite error:\", error);\r\n        \r\n        if (error.message?.includes(\"invalid\") || error.message?.includes(\"expired\")) {\r\n            return NextResponse.json({ error: \"Invalid or expired invite code\" }, { status: 400 });\r\n        }\r\n        \r\n        return NextResponse.json({ error: \"Failed to accept group invite\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\groups\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\labels\\[sessionId]\\[labelId]\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":41,"column":27,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":41,"endColumn":30,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1445,1448],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1445,1448],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\nimport { prisma } from \"@/lib/prisma\";\r\n\r\n// PUT: Update label\r\nexport async function PUT(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string, labelId: string }> }\r\n) {\r\n    \r\n    try {\r\n        const { sessionId, labelId } = await params;\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const body = await request.json();\r\n        const { name, color } = body;\r\n\r\n        // Find label and verify access\r\n        const label = await prisma.label.findUnique({\r\n            where: { id: labelId }\r\n        });\r\n\r\n        if (!label) {\r\n            return NextResponse.json({ error: \"Label not found\" }, { status: 404 });\r\n        }\r\n\r\n        if (label.sessionId !== sessionId) {\r\n            return NextResponse.json({ error: \"Label does not belong to this session\" }, { status: 404 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, label.sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this label\" }, { status: 403 });\r\n        }\r\n\r\n        // Prepare update data\r\n        const updateData: any = {};\r\n        if (name) updateData.name = name;\r\n        if (color !== undefined) {\r\n            if (color < 0 || color > 19) {\r\n                return NextResponse.json({ \r\n                    error: \"Color must be between 0 and 19\" \r\n                }, { status: 400 });\r\n            }\r\n            const colorMap = [\r\n                \"#FF0000\", \"#FF7F00\", \"#FFFF00\", \"#00FF00\", \"#0000FF\",\r\n                \"#4B0082\", \"#9400D3\", \"#FF1493\", \"#00CED1\", \"#32CD32\",\r\n                \"#FFD700\", \"#FF69B4\", \"#8B4513\", \"#2F4F4F\", \"#696969\",\r\n                \"#708090\", \"#778899\", \"#B0C4DE\", \"#ADD8E6\", \"#F0E68C\"\r\n            ];\r\n            updateData.color = color;\r\n            updateData.colorHex = colorMap[color];\r\n        }\r\n\r\n        const updatedLabel = await prisma.label.update({\r\n            where: { id: labelId },\r\n            data: updateData\r\n        });\r\n\r\n        return NextResponse.json({ success: true, label: updatedLabel });\r\n\r\n    } catch (error) {\r\n        console.error(\"Update label error:\", error);\r\n        return NextResponse.json({ error: \"Failed to update label\" }, { status: 500 });\r\n    }\r\n}\r\n\r\n// DELETE: Delete label\r\nexport async function DELETE(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string, labelId: string }> }\r\n) {\r\n    try {\r\n        const { sessionId, labelId } = await params;\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        // Find label and verify access\r\n        const label = await prisma.label.findUnique({\r\n            where: { id: labelId }\r\n        });\r\n\r\n        if (!label) {\r\n            return NextResponse.json({ error: \"Label not found\" }, { status: 404 });\r\n        }\r\n\r\n        if (label.sessionId !== sessionId) {\r\n            return NextResponse.json({ error: \"Label does not belong to this session\" }, { status: 404 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, label.sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this label\" }, { status: 403 });\r\n        }\r\n\r\n        // Delete label (cascade will delete chatLabels)\r\n        await prisma.label.delete({\r\n            where: { id: labelId }\r\n        });\r\n\r\n        return NextResponse.json({ \r\n            success: true,\r\n            message: \"Label deleted successfully\"\r\n        });\r\n\r\n    } catch (error) {\r\n        console.error(\"Delete label error:\", error);\r\n        return NextResponse.json({ error: \"Failed to delete label\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\labels\\[sessionId]\\chat\\[jid]\\labels\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\labels\\[sessionId]\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":143,"column":27,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":143,"endColumn":30,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[4944,4947],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[4944,4947],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\nimport { prisma } from \"@/lib/prisma\";\r\n\r\n// GET: Get all labels for a session\r\nexport async function GET(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string }> }\r\n) {\r\n    try {\r\n        const { sessionId } = await params;\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        if (!sessionId) {\r\n            return NextResponse.json({ error: \"sessionId is required\" }, { status: 400 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const labels = await prisma.label.findMany({\r\n            where: { sessionId },\r\n            include: {\r\n                _count: {\r\n                    select: { chatLabels: true }\r\n                }\r\n            },\r\n            orderBy: { createdAt: 'desc' }\r\n        });\r\n\r\n        return NextResponse.json({ success: true, labels });\r\n\r\n    } catch (error) {\r\n        console.error(\"Get labels error:\", error);\r\n        return NextResponse.json({ error: \"Failed to get labels\" }, { status: 500 });\r\n    }\r\n}\r\n\r\n// POST: Create a new label\r\nexport async function POST(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string }> }\r\n) {\r\n    try {\r\n        const { sessionId } = await params;\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const body = await request.json();\r\n        const { name, color } = body;\r\n\r\n        if (!sessionId || !name) {\r\n            return NextResponse.json({ \r\n                error: \"sessionId and name are required\" \r\n            }, { status: 400 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        // Validate color (0-19 for WhatsApp colors)\r\n        const colorValue = color !== undefined ? color : 0;\r\n        if (colorValue < 0 || colorValue > 19) {\r\n            return NextResponse.json({ \r\n                error: \"Color must be between 0 and 19\" \r\n            }, { status: 400 });\r\n        }\r\n\r\n        // Color mapping (WhatsApp internal colors to hex)\r\n        const colorMap = [\r\n            \"#FF0000\", \"#FF7F00\", \"#FFFF00\", \"#00FF00\", \"#0000FF\",\r\n            \"#4B0082\", \"#9400D3\", \"#FF1493\", \"#00CED1\", \"#32CD32\",\r\n            \"#FFD700\", \"#FF69B4\", \"#8B4513\", \"#2F4F4F\", \"#696969\",\r\n            \"#708090\", \"#778899\", \"#B0C4DE\", \"#ADD8E6\", \"#F0E68C\"\r\n        ];\r\n\r\n        const label = await prisma.label.create({\r\n            data: {\r\n                sessionId,\r\n                name,\r\n                color: colorValue,\r\n                colorHex: colorMap[colorValue]\r\n            }\r\n        });\r\n\r\n        return NextResponse.json({ success: true, label });\r\n\r\n    } catch (error) {\r\n        console.error(\"Create label error:\", error);\r\n        return NextResponse.json({ error: \"Failed to create label\" }, { status: 500 });\r\n    }\r\n\r\n}\r\n\r\n/**\r\n * @deprecated This endpoint is deprecated. Use PUT /api/labels/{sessionId}/{labelId} instead.\r\n * This endpoint will be removed in a future version.\r\n */\r\n// PUT: Update label\r\nexport async function PUT(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string }> }\r\n) {\r\n    console.warn('[DEPRECATED] PUT /api/labels/{id} is deprecated. Use PUT /api/labels/{sessionId}/{labelId} instead.');\r\n    const { sessionId: id } = await params;\r\n\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const body = await request.json();\r\n        const { name, color } = body;\r\n\r\n        // Find label and verify access\r\n        const label = await prisma.label.findUnique({\r\n            where: { id }\r\n        });\r\n\r\n        if (!label) {\r\n            return NextResponse.json({ error: \"Label not found\" }, { status: 404 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, label.sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this label\" }, { status: 403 });\r\n        }\r\n\r\n        // Prepare update data\r\n        const updateData: any = {};\r\n        if (name) updateData.name = name;\r\n        if (color !== undefined) {\r\n            if (color < 0 || color > 19) {\r\n                return NextResponse.json({ \r\n                    error: \"Color must be between 0 and 19\" \r\n                }, { status: 400 });\r\n            }\r\n            const colorMap = [\r\n                \"#FF0000\", \"#FF7F00\", \"#FFFF00\", \"#00FF00\", \"#0000FF\",\r\n                \"#4B0082\", \"#9400D3\", \"#FF1493\", \"#00CED1\", \"#32CD32\",\r\n                \"#FFD700\", \"#FF69B4\", \"#8B4513\", \"#2F4F4F\", \"#696969\",\r\n                \"#708090\", \"#778899\", \"#B0C4DE\", \"#ADD8E6\", \"#F0E68C\"\r\n            ];\r\n            updateData.color = color;\r\n            updateData.colorHex = colorMap[color];\r\n        }\r\n\r\n        const updatedLabel = await prisma.label.update({\r\n            where: { id },\r\n            data: updateData\r\n        });\r\n\r\n        return NextResponse.json({ success: true, label: updatedLabel });\r\n\r\n    } catch (error) {\r\n        console.error(\"Update label error:\", error);\r\n        return NextResponse.json({ error: \"Failed to update label\" }, { status: 500 });\r\n    }\r\n}\r\n\r\n/**\r\n * @deprecated This endpoint is deprecated. Use DELETE /api/labels/{sessionId}/{labelId} instead.\r\n * This endpoint will be removed in a future version.\r\n */\r\n// DELETE: Delete label\r\nexport async function DELETE(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string }> }\r\n) {\r\n    console.warn('[DEPRECATED] DELETE /api/labels/{id} is deprecated. Use DELETE /api/labels/{sessionId}/{labelId} instead.');\r\n    const { sessionId: id } = await params;\r\n\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        // Find label and verify access\r\n        const label = await prisma.label.findUnique({\r\n            where: { id }\r\n        });\r\n\r\n        if (!label) {\r\n            return NextResponse.json({ error: \"Label not found\" }, { status: 404 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, label.sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this label\" }, { status: 403 });\r\n        }\r\n\r\n        // Delete label (cascade will delete chatLabels)\r\n        await prisma.label.delete({\r\n            where: { id }\r\n        });\r\n\r\n        return NextResponse.json({ \r\n            success: true,\r\n            message: \"Label deleted successfully\"\r\n        });\r\n\r\n    } catch (error) {\r\n        console.error(\"Delete label error:\", error);\r\n        return NextResponse.json({ error: \"Failed to delete label\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\labels\\chat-labels\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\labels\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\media\\[filename]\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":51,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":51,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1796,1799],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1796,1799],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextRequest, NextResponse } from \"next/server\";\r\nimport { readFile } from \"fs/promises\";\r\nimport path from \"path\";\r\nimport { existsSync } from \"fs\";\r\n\r\nexport async function GET(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ filename: string }> }\r\n) {\r\n    try {\r\n        const { filename } = await params;\r\n        \r\n        // Security: Prevent directory traversal\r\n        if (filename.includes('..') || filename.includes('/') || filename.includes('\\\\')) {\r\n            return NextResponse.json({ error: \"Invalid filename\" }, { status: 400 });\r\n        }\r\n\r\n        const filePath = path.join(process.cwd(), \"public\", \"media\", filename);\r\n        \r\n        if (!existsSync(filePath)) {\r\n            return NextResponse.json({ error: \"File not found\" }, { status: 404 });\r\n        }\r\n\r\n        const fileBuffer = await readFile(filePath);\r\n        \r\n        // Determine content type based on extension\r\n        const ext = path.extname(filename).toLowerCase();\r\n        const contentTypeMap: Record<string, string> = {\r\n            '.jpg': 'image/jpeg',\r\n            '.jpeg': 'image/jpeg',\r\n            '.png': 'image/png',\r\n            '.gif': 'image/gif',\r\n            '.webp': 'image/webp',\r\n            '.mp4': 'video/mp4',\r\n            '.mp3': 'audio/mpeg',\r\n            '.wav': 'audio/wav',\r\n            '.pdf': 'application/pdf',\r\n            '.bin': 'application/octet-stream',\r\n        };\r\n        \r\n        const contentType = contentTypeMap[ext] || 'application/octet-stream';\r\n        \r\n        return new NextResponse(fileBuffer, {\r\n            status: 200,\r\n            headers: {\r\n                'Content-Type': contentType,\r\n                'Cache-Control': 'public, max-age=31536000, immutable',\r\n            },\r\n        });\r\n\r\n    } catch (error: any) {\r\n        console.error(\"Media serve error:\", error);\r\n        return NextResponse.json({ \r\n            error: \"Failed to serve media\",\r\n            details: error.message \r\n        }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\messages\\[sessionId]\\[jid]\\[messageId]\\react\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\messages\\[sessionId]\\[jid]\\[messageId]\\reply\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'fromMe' is assigned a value but never used.","line":25,"column":36,"nodeType":"Identifier","messageId":"unusedVar","endLine":25,"endColumn":42},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":43,"column":29,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":43,"endColumn":32,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1645,1648],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1645,1648],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":49,"column":35,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":49,"endColumn":38,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1824,1827],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1824,1827],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"prefer-const","severity":2,"message":"'msgPayload' is never reassigned. Use 'const' instead.","line":149,"column":13,"nodeType":"Identifier","messageId":"useConst","endLine":149,"endColumn":23,"fix":{"range":[6505,6530],"text":"const msgPayload = message;"}},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":157,"column":34,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":157,"endColumn":37,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[6807,6810],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[6807,6810],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":4,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":1,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\nimport { prisma } from \"@/lib/prisma\";\r\n\r\n/**\r\n * POST /api/messages/{sessionId}/{jid}/{messageId}/reply\r\n * Reply to a specific message (quoted reply)\r\n * Uses same request format as /send: { message, mentions }\r\n */\r\nexport async function POST(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string; jid: string; messageId: string }> }\r\n) {\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const { sessionId, jid: rawJid, messageId } = await params;\r\n        const jid = decodeURIComponent(rawJid);\r\n\r\n        const body = await request.json();\r\n        const { message, mentions, fromMe } = body;\r\n\r\n        if (!message) {\r\n            return NextResponse.json({ error: \"message is required\" }, { status: 400 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        // Construct the quoted message key\r\n        const quotedMsgKey: any = {\r\n            remoteJid: jid,\r\n            fromMe: false, // Default fallback, overridden by DB\r\n            id: messageId\r\n        };\r\n\r\n        let quotedMessageContent: any = { extendedTextMessage: { text: \"\" } }; // Default fallback\r\n        let resolvedParticipant: string | undefined = undefined;\r\n        let originalMsgTimestamp: number | undefined = undefined;\r\n        let originalMsgPushName: string | undefined = undefined;\r\n\r\n        try {\r\n            // First resolve the user-friendly sessionId to the db session CUID\r\n            const sessionData = await prisma.session.findUnique({\r\n                where: { sessionId: sessionId },\r\n                select: { id: true }\r\n            });\r\n            const dbSessionId = sessionData?.id;\r\n\r\n            let originalMsg = null;\r\n            if (dbSessionId) {\r\n                // Always fetch original message to build a proper quoted context for WA Web\r\n                originalMsg = await prisma.message.findUnique({\r\n                    where: {\r\n                        sessionId_keyId: {\r\n                            sessionId: dbSessionId,\r\n                            keyId: messageId\r\n                        }\r\n                    }\r\n                });\r\n            }\r\n\r\n            if (originalMsg && dbSessionId) {\r\n                // CRITICAL: WA Web drops the quote if fromMe does not match the actual sender\r\n                quotedMsgKey.fromMe = originalMsg.fromMe;\r\n\r\n                if (originalMsg.timestamp) {\r\n                    originalMsgTimestamp = Math.floor(new Date(originalMsg.timestamp).getTime() / 1000);\r\n                }\r\n                if (originalMsg.pushName) {\r\n                    originalMsgPushName = originalMsg.pushName;\r\n                }\r\n                // WA Web requires participant field for group chats\r\n                if (jid.endsWith(\"@g.us\") && originalMsg.senderJid) {\r\n                    resolvedParticipant = originalMsg.senderJid;\r\n\r\n                    // Attempt to resolve @lid to @s.whatsapp.net (Standard WA Phone Number)\r\n                    // WA Web often fails to render quotes if the participant is purely a Linked Device ID\r\n                    if (resolvedParticipant.includes(\"@lid\")) {\r\n                        const contact = await prisma.contact.findUnique({\r\n                            where: {\r\n                                sessionId_jid: { sessionId: dbSessionId, jid: resolvedParticipant }\r\n                            },\r\n                            select: { remoteJidAlt: true }\r\n                        });\r\n\r\n                        // Use the real phone number JID if available\r\n                        if (contact?.remoteJidAlt) {\r\n                            resolvedParticipant = contact.remoteJidAlt;\r\n                        }\r\n                    }\r\n\r\n                    quotedMsgKey.participant = resolvedParticipant;\r\n                }\r\n\r\n                // Mock the quoted message content based on DB so WA Web displays the snippet\r\n                switch (originalMsg.type) {\r\n                    case 'TEXT':\r\n                        quotedMessageContent = { extendedTextMessage: { text: originalMsg.content || \"\" } };\r\n                        break;\r\n                    case 'IMAGE':\r\n                        quotedMessageContent = { imageMessage: { caption: originalMsg.content || \"\" } };\r\n                        break;\r\n                    case 'VIDEO':\r\n                        quotedMessageContent = { videoMessage: { caption: originalMsg.content || \"\" } };\r\n                        break;\r\n                    case 'DOCUMENT':\r\n                        quotedMessageContent = { documentMessage: { fileName: originalMsg.content || \"Document\" } };\r\n                        break;\r\n                    case 'AUDIO':\r\n                        quotedMessageContent = { audioMessage: {} };\r\n                        break;\r\n                    case 'STICKER':\r\n                        quotedMessageContent = { stickerMessage: {} };\r\n                        break;\r\n                    case 'CONTACT':\r\n                        quotedMessageContent = { contactMessage: { displayName: originalMsg.content || \"\" } };\r\n                        break;\r\n                    case 'LOCATION':\r\n                        quotedMessageContent = { locationMessage: {} };\r\n                        break;\r\n                }\r\n            }\r\n        } catch (dbError) {\r\n            console.warn(\"Could not fetch original message for quoted reply context:\", dbError);\r\n        }\r\n\r\n        const quotedMsg = {\r\n            key: quotedMsgKey,\r\n            message: quotedMessageContent,\r\n            participant: resolvedParticipant,\r\n            messageTimestamp: originalMsgTimestamp,\r\n            pushName: originalMsgPushName\r\n        };\r\n\r\n        // Process message payload (same as /send)\r\n        let msgPayload = message;\r\n\r\n        if (msgPayload.text && mentions && Array.isArray(mentions)) {\r\n            msgPayload.mentions = mentions;\r\n        }\r\n\r\n        // Send the reply with quoted reference\r\n        await instance.socket.sendMessage(jid, msgPayload, {\r\n            quoted: quotedMsg as any\r\n        });\r\n\r\n        return NextResponse.json({ success: true, message: \"Message sent successfully\" });\r\n\r\n    } catch (error) {\r\n        console.error(\"Reply message error:\", error);\r\n        return NextResponse.json({ error: \"Failed to send reply\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\messages\\[sessionId]\\[jid]\\[messageId]\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":44,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":44,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1571,1574],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1571,1574],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\n\r\n// DELETE: Delete message for everyone\r\nexport async function DELETE(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string; jid: string; messageId: string }> }\r\n) {\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const { sessionId, jid, messageId } = await params;\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        const decodedJid = decodeURIComponent(jid);\r\n\r\n        // Delete message for everyone\r\n        await instance.socket.sendMessage(decodedJid, { delete: {\r\n            remoteJid: decodedJid,\r\n            fromMe: true,\r\n            id: messageId,\r\n            participant: undefined\r\n        }});\r\n\r\n        return NextResponse.json({ \r\n            success: true,\r\n            message: \"Message deleted for everyone\"\r\n        });\r\n\r\n    } catch (error: any) {\r\n        console.error(\"Delete message error:\", error);\r\n        \r\n        if (error.message?.includes(\"too old\") || error.message?.includes(\"time limit\")) {\r\n            return NextResponse.json({ \r\n                error: \"Cannot delete message older than 7 minutes\" \r\n            }, { status: 400 });\r\n        }\r\n        \r\n        return NextResponse.json({ error: \"Failed to delete message\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\messages\\[sessionId]\\[jid]\\[messageId]\\star\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":37,"column":35,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":37,"endColumn":38,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1405,1408],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1405,1408],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\n\r\n/**\r\n * POST /api/messages/{sessionId}/{jid}/{messageId}/star\r\n * Star or unstar a specific message\r\n */\r\nexport async function POST(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string; jid: string; messageId: string }> }\r\n) {\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const { sessionId, jid: rawJid, messageId } = await params;\r\n        const jid = decodeURIComponent(rawJid);\r\n\r\n        const body = await request.json();\r\n        const { star = true, fromMe = false } = body;\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        // Star/unstar the message\r\n        await (instance.socket as any).chatModify({\r\n            star: {\r\n                messages: [{ id: messageId, fromMe }],\r\n                star\r\n            }\r\n        }, jid);\r\n\r\n        return NextResponse.json({\r\n            success: true,\r\n            message: star ? \"Message starred\" : \"Message unstarred\"\r\n        });\r\n\r\n    } catch (error) {\r\n        console.error(\"Star message error:\", error);\r\n        return NextResponse.json({ error: \"Failed to star/unstar message\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\messages\\[sessionId]\\[jid]\\contact\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\messages\\[sessionId]\\[jid]\\list\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\messages\\[sessionId]\\[jid]\\location\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\messages\\[sessionId]\\[jid]\\media\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":44,"column":31,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":44,"endColumn":34,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1663,1666],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1663,1666],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":49,"column":22,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":49,"endColumn":25,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1841,1844],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1841,1844],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\r\nimport { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\n\r\nexport async function POST(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string; jid: string }> }\r\n) {\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const { sessionId, jid } = await params;\r\n        const formData = await request.formData();\r\n        const file = formData.get(\"file\") as File;\r\n        const type = formData.get(\"type\") as string; // image, video, audio, document\r\n        const caption = formData.get(\"caption\") as string || \"\";\r\n        \r\n        if (!file) {\r\n             return NextResponse.json({ error: \"file is required\" }, { status: 400 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        const decodedJid = decodeURIComponent(jid);\r\n\r\n        // Convert File to Buffer\r\n        const buffer = Buffer.from(await file.arrayBuffer());\r\n\r\n        const mimetype = file.type;\r\n        \r\n        const messageOptions: any = {};\r\n        if (caption) messageOptions.caption = caption;\r\n        messageOptions.mimetype = mimetype;\r\n        \r\n        // Handle different types\r\n        let content: any = {};\r\n\r\n        if (type === 'image') {\r\n            content = { image: buffer, ...messageOptions };\r\n        } else if (type === 'video') {\r\n             content = { video: buffer, ...messageOptions };\r\n        } else if (type === 'audio') {\r\n             content = { audio: buffer, mimetype: 'audio/mp4', ptt: false }; // ptt depends on needs\r\n        } else if (type === 'voice') {\r\n             content = { audio: buffer, mimetype: 'audio/mp4', ptt: true };\r\n        } else if (type === 'document') {\r\n             content = { document: buffer, mimetype, fileName: file.name, ...messageOptions };\r\n        } else {\r\n             // Default to document logic if unknown, or maybe image if implicit?\r\n             // Let's assume generic file is document\r\n             content = { document: buffer, mimetype, fileName: file.name, ...messageOptions };\r\n        }\r\n\r\n        const sent = await instance.socket.sendMessage(decodedJid, content);\r\n\r\n        return NextResponse.json({ success: true, data: sent });\r\n\r\n    } catch (e) {\r\n        console.error(\"Media send error\", e);\r\n        return NextResponse.json({ error: \"Failed to send media\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\messages\\[sessionId]\\[jid]\\poll\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\messages\\[sessionId]\\[jid]\\reply\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'fromMe' is assigned a value but never used.","line":25,"column":47,"nodeType":"Identifier","messageId":"unusedVar","endLine":25,"endColumn":53},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":47,"column":29,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":47,"endColumn":32,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1766,1769],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1766,1769],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":53,"column":35,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":53,"endColumn":38,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1945,1948],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1945,1948],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"prefer-const","severity":2,"message":"'msgPayload' is never reassigned. Use 'const' instead.","line":153,"column":13,"nodeType":"Identifier","messageId":"useConst","endLine":153,"endColumn":23,"fix":{"range":[6626,6651],"text":"const msgPayload = message;"}},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":161,"column":34,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":161,"endColumn":37,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[6928,6931],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[6928,6931],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":4,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":1,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\nimport { prisma } from \"@/lib/prisma\";\r\n\r\n/**\r\n * POST /api/messages/{sessionId}/{jid}/reply\r\n * Reply to a message with messageId provided in the request body\r\n * Uses same request format as /send: { message, mentions }\r\n */\r\nexport async function POST(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string; jid: string }> }\r\n) {\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const { sessionId, jid: rawJid } = await params;\r\n        const jid = decodeURIComponent(rawJid);\r\n\r\n        const body = await request.json();\r\n        const { messageId, message, mentions, fromMe } = body;\r\n\r\n        if (!messageId) {\r\n            return NextResponse.json({ error: \"messageId is required\" }, { status: 400 });\r\n        }\r\n\r\n        if (!message) {\r\n            return NextResponse.json({ error: \"message is required\" }, { status: 400 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        // Construct the quoted message key\r\n        const quotedMsgKey: any = {\r\n            remoteJid: jid,\r\n            fromMe: false, // Default fallback, overridden by DB\r\n            id: messageId\r\n        };\r\n\r\n        let quotedMessageContent: any = { extendedTextMessage: { text: \"\" } }; // Default fallback\r\n        let resolvedParticipant: string | undefined = undefined;\r\n        let originalMsgTimestamp: number | undefined = undefined;\r\n        let originalMsgPushName: string | undefined = undefined;\r\n\r\n        try {\r\n            // First resolve the user-friendly sessionId to the db session CUID\r\n            const sessionData = await prisma.session.findUnique({\r\n                where: { sessionId: sessionId },\r\n                select: { id: true }\r\n            });\r\n            const dbSessionId = sessionData?.id;\r\n\r\n            let originalMsg = null;\r\n            if (dbSessionId) {\r\n                // Always fetch original message to build a proper quoted context for WA Web\r\n                originalMsg = await prisma.message.findUnique({\r\n                    where: {\r\n                        sessionId_keyId: {\r\n                            sessionId: dbSessionId,\r\n                            keyId: messageId\r\n                        }\r\n                    }\r\n                });\r\n            }\r\n\r\n            if (originalMsg && dbSessionId) {\r\n                // CRITICAL: WA Web drops the quote if fromMe does not match the actual sender\r\n                quotedMsgKey.fromMe = originalMsg.fromMe;\r\n\r\n                if (originalMsg.timestamp) {\r\n                    originalMsgTimestamp = Math.floor(new Date(originalMsg.timestamp).getTime() / 1000);\r\n                }\r\n                if (originalMsg.pushName) {\r\n                    originalMsgPushName = originalMsg.pushName;\r\n                }\r\n                // WA Web requires participant field for group chats\r\n                if (jid.endsWith(\"@g.us\") && originalMsg.senderJid) {\r\n                    resolvedParticipant = originalMsg.senderJid;\r\n\r\n                    // Attempt to resolve @lid to @s.whatsapp.net (Standard WA Phone Number)\r\n                    // WA Web often fails to render quotes if the participant is purely a Linked Device ID\r\n                    if (resolvedParticipant.includes(\"@lid\")) {\r\n                        const contact = await prisma.contact.findUnique({\r\n                            where: {\r\n                                sessionId_jid: { sessionId: dbSessionId, jid: resolvedParticipant }\r\n                            },\r\n                            select: { remoteJidAlt: true }\r\n                        });\r\n\r\n                        // Use the real phone number JID if available\r\n                        if (contact?.remoteJidAlt) {\r\n                            resolvedParticipant = contact.remoteJidAlt;\r\n                        }\r\n                    }\r\n\r\n                    quotedMsgKey.participant = resolvedParticipant;\r\n                }\r\n\r\n                // Mock the quoted message content based on DB so WA Web displays the snippet\r\n                switch (originalMsg.type) {\r\n                    case 'TEXT':\r\n                        quotedMessageContent = { extendedTextMessage: { text: originalMsg.content || \"\" } };\r\n                        break;\r\n                    case 'IMAGE':\r\n                        quotedMessageContent = { imageMessage: { caption: originalMsg.content || \"\" } };\r\n                        break;\r\n                    case 'VIDEO':\r\n                        quotedMessageContent = { videoMessage: { caption: originalMsg.content || \"\" } };\r\n                        break;\r\n                    case 'DOCUMENT':\r\n                        quotedMessageContent = { documentMessage: { fileName: originalMsg.content || \"Document\" } };\r\n                        break;\r\n                    case 'AUDIO':\r\n                        quotedMessageContent = { audioMessage: {} };\r\n                        break;\r\n                    case 'STICKER':\r\n                        quotedMessageContent = { stickerMessage: {} };\r\n                        break;\r\n                    case 'CONTACT':\r\n                        quotedMessageContent = { contactMessage: { displayName: originalMsg.content || \"\" } };\r\n                        break;\r\n                    case 'LOCATION':\r\n                        quotedMessageContent = { locationMessage: {} };\r\n                        break;\r\n                }\r\n            }\r\n        } catch (dbError) {\r\n            console.warn(\"Could not fetch original message for quoted reply context:\", dbError);\r\n        }\r\n\r\n        const quotedMsg = {\r\n            key: quotedMsgKey,\r\n            message: quotedMessageContent,\r\n            participant: resolvedParticipant,\r\n            messageTimestamp: originalMsgTimestamp,\r\n            pushName: originalMsgPushName\r\n        };\r\n\r\n        // Process message payload (same as /send)\r\n        let msgPayload = message;\r\n\r\n        if (msgPayload.text && mentions && Array.isArray(mentions)) {\r\n            msgPayload.mentions = mentions;\r\n        }\r\n\r\n        // Send the reply with quoted reference\r\n        await instance.socket.sendMessage(jid, msgPayload, {\r\n            quoted: quotedMsg as any\r\n        });\r\n\r\n        return NextResponse.json({ success: true, message: \"Message sent successfully\" });\r\n\r\n    } catch (error) {\r\n        console.error(\"Reply message error:\", error);\r\n        return NextResponse.json({ error: \"Failed to send reply\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\messages\\[sessionId]\\[jid]\\send\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":66,"column":97,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":66,"endColumn":100,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2699,2702],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2699,2702],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":76,"column":83,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":76,"endColumn":86,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3102,3105],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3102,3105],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\nimport Sticker from \"wa-sticker-formatter\";\r\n\r\nexport async function POST(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string, jid: string }> }\r\n) {\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const { sessionId, jid: rawJid } = await params;\r\n        const jid = decodeURIComponent(rawJid);\r\n        \r\n        const body = await request.json();\r\n        const { message, mentions } = body;\r\n\r\n        if (!message) {\r\n            return NextResponse.json({ error: \"message is required\" }, { status: 400 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance) {\r\n            return NextResponse.json({ error: \"Session not found or disconnected\" }, { status: 404 });\r\n        }\r\n\r\n        const socket = instance.socket;\r\n        if (!socket) {\r\n             return NextResponse.json({ error: \"Socket not ready\" }, { status: 503 });\r\n        }\r\n\r\n        // Process Message\r\n        let msgPayload = message;\r\n\r\n        // Custom Handler for Sticker URL\r\n        if (msgPayload.sticker && (msgPayload.sticker.url || typeof msgPayload.sticker === 'string')) {\r\n            const url = msgPayload.sticker.url || msgPayload.sticker;\r\n            \r\n            try {\r\n                const res = await fetch(url);\r\n                if (!res.ok) throw new Error(`Failed to fetch sticker media: ${res.statusText}`);\r\n                const buffer = await res.arrayBuffer();\r\n                \r\n                const sticker = new Sticker(Buffer.from(buffer), {\r\n                    pack: msgPayload.sticker.pack || \"WA-AKG Bot\",\r\n                    author: msgPayload.sticker.author || \"WA-AKG\",\r\n                    type: \"full\",\r\n                    quality: 50\r\n                });\r\n\r\n                const stickerBuffer = await sticker.toBuffer();\r\n                msgPayload = { sticker: stickerBuffer };\r\n\r\n            } catch (e) {\r\n                console.error(\"Sticker generation from URL failed:\", e);\r\n                return NextResponse.json({ error: `Failed to generate sticker from URL: ${(e as any).message}` }, { status: 400 });\r\n            }\r\n        }\r\n\r\n        // Send Message\r\n        // Ensure mentions are passed in options and also in message content if it's a text message\r\n        if (msgPayload.text && mentions && Array.isArray(mentions)) {\r\n             msgPayload.mentions = mentions;\r\n        }\r\n\r\n        await socket.sendMessage(jid, msgPayload, { mentions: mentions || [] } as any);\r\n\r\n        return NextResponse.json({ success: true, message: \"Message sent successfully\" });\r\n    } catch (error) {\r\n        console.error(\"Send message error:\", error);\r\n        return NextResponse.json({ error: \"Failed to send message\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\messages\\[sessionId]\\[jid]\\spam\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\messages\\[sessionId]\\[jid]\\sticker\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":50,"column":27,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":50,"endColumn":30,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1941,1944],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1941,1944],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":51,"column":41,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":51,"endColumn":44,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1987,1990],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1987,1990],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\nimport Sticker from \"wa-sticker-formatter\";\r\n\r\n// POST: Send sticker from image\r\nexport async function POST(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string; jid: string }> }\r\n) {\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const { sessionId, jid } = await params;\r\n        const formData = await request.formData();\r\n        const file = formData.get(\"file\") as File;\r\n        \r\n        if (!file) {\r\n             return NextResponse.json({ error: \"file is required\" }, { status: 400 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        const decodedJid = decodeURIComponent(jid);\r\n\r\n        // Convert File to Buffer\r\n        const buffer = Buffer.from(await file.arrayBuffer());\r\n\r\n        const pack = formData.get(\"pack\") as string || \"WA-AKG\";\r\n        const author = formData.get(\"author\") as string || user.name || \"User\";\r\n        const type = (formData.get(\"type\") as string) || \"full\";\r\n        const quality = parseInt(formData.get(\"quality\") as string) || 50;\r\n\r\n        // Create Sticker\r\n        const sticker = new Sticker(buffer, {\r\n            pack,\r\n            author,\r\n            type: type as any,\r\n            categories: [\"≡ƒñ⌐\", \"≡ƒÄë\"] as any,\r\n            quality,\r\n            background: \"transparent\"\r\n        });\r\n\r\n        const stickerBuffer = await sticker.toBuffer();\r\n\r\n        await instance.socket.sendMessage(decodedJid, { sticker: stickerBuffer });\r\n\r\n        return NextResponse.json({ success: true });\r\n\r\n    } catch (e) {\r\n        console.error(\"Sticker error\", e);\r\n        return NextResponse.json({ error: \"Failed to create sticker\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\messages\\[sessionId]\\broadcast\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\messages\\[sessionId]\\download\\[messageId]\\media\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\messages\\[sessionId]\\forward\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\messages\\[sessionId]\\search\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":54,"column":22,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":54,"endColumn":25,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2007,2010],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2007,2010],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { prisma } from \"@/lib/prisma\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\n\r\n/**\r\n * GET /api/messages/{sessionId}/search\r\n * Search messages stored in database for a session\r\n * Query params: q, jid, type, limit, page, fromMe\r\n */\r\nexport async function GET(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string }> }\r\n) {\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const { sessionId } = await params;\r\n        const { searchParams } = new URL(request.url);\r\n\r\n        const q = searchParams.get(\"q\") || \"\";\r\n        const jid = searchParams.get(\"jid\") || undefined;\r\n        const type = searchParams.get(\"type\") || undefined;\r\n        const fromMeParam = searchParams.get(\"fromMe\");\r\n        const limit = Math.min(parseInt(searchParams.get(\"limit\") || \"20\"), 100);\r\n        const page = Math.max(parseInt(searchParams.get(\"page\") || \"1\"), 1);\r\n        const skip = (page - 1) * limit;\r\n\r\n        if (!q && !jid) {\r\n            return NextResponse.json({\r\n                error: \"At least one of 'q' (search query) or 'jid' is required\"\r\n            }, { status: 400 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        // Get internal session ID\r\n        const session = await prisma.session.findUnique({\r\n            where: { sessionId },\r\n            select: { id: true }\r\n        });\r\n\r\n        if (!session) {\r\n            return NextResponse.json({ error: \"Session not found\" }, { status: 404 });\r\n        }\r\n\r\n        // Build search filters\r\n        const where: any = {\r\n            sessionId: session.id,\r\n        };\r\n\r\n        if (q) {\r\n            where.content = { contains: q };\r\n        }\r\n\r\n        if (jid) {\r\n            where.remoteJid = decodeURIComponent(jid);\r\n        }\r\n\r\n        if (type) {\r\n            where.type = type.toUpperCase();\r\n        }\r\n\r\n        if (fromMeParam !== null && fromMeParam !== undefined) {\r\n            where.fromMe = fromMeParam === \"true\";\r\n        }\r\n\r\n        const [messages, total] = await Promise.all([\r\n            prisma.message.findMany({\r\n                where,\r\n                orderBy: { timestamp: \"desc\" },\r\n                take: limit,\r\n                skip,\r\n                select: {\r\n                    id: true,\r\n                    remoteJid: true,\r\n                    senderJid: true,\r\n                    fromMe: true,\r\n                    keyId: true,\r\n                    pushName: true,\r\n                    type: true,\r\n                    content: true,\r\n                    status: true,\r\n                    timestamp: true,\r\n                    quoteId: true,\r\n                }\r\n            }),\r\n            prisma.message.count({ where })\r\n        ]);\r\n\r\n        return NextResponse.json({\r\n            success: true,\r\n            data: messages,\r\n            pagination: {\r\n                total,\r\n                page,\r\n                limit,\r\n                pages: Math.ceil(total / limit)\r\n            }\r\n        });\r\n\r\n    } catch (error) {\r\n        console.error(\"Message search error:\", error);\r\n        return NextResponse.json({ error: \"Failed to search messages\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\messages\\broadcast\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'delay' is assigned a value but never used.","line":25,"column":49,"nodeType":"Identifier","messageId":"unusedVar","endLine":25,"endColumn":54}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { broadcastSchema } from \"@/lib/validations\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\nimport type { AnyMessageContent } from \"@whiskeysockets/baileys\";\r\n\r\n/**\r\n * @deprecated This endpoint is deprecated. Use POST /api/messages/{sessionId}/broadcast instead.\r\n * This endpoint will be removed in a future version.\r\n */\r\nexport async function POST(request: NextRequest) {\r\n    console.warn('[DEPRECATED] POST /api/messages/broadcast is deprecated. Use POST /api/messages/{sessionId}/broadcast instead.');\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const body = await request.json();\r\n        const parseResult = broadcastSchema.safeParse(body);\r\n        if (!parseResult.success) {\r\n             return NextResponse.json({ error: parseResult.error.flatten() }, { status: 400 });\r\n        }\r\n        \r\n        const { sessionId, recipients, message, delay } = parseResult.data;\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        // Convert string message to AnyMessageContent object\r\n        const messageContent: AnyMessageContent = { text: message };\r\n\r\n        // Process in background to avoid timeout\r\n        (async () => {\r\n             for (const jid of recipients) {\r\n                 try {\r\n                     await instance.socket!.sendMessage(jid, messageContent);\r\n                     \r\n                     // Random delay between 10-20 seconds per message\r\n                     const randomDelay = Math.floor(Math.random() * 10000) + 10000;\r\n                     console.log(`Waiting ${randomDelay / 1000}s before next broadcast message`);\r\n                     await new Promise(r => setTimeout(r, randomDelay));\r\n                 } catch (e) {\r\n                     console.error(`Failed to send broadcast to ${jid}`, e);\r\n                 }\r\n             }\r\n             console.log(`Broadcast completed for ${recipients.length} recipients`);\r\n        })();\r\n        \r\n        return NextResponse.json({ success: true, message: \"Broadcast started in background\" });\r\n\r\n    } catch (e) {\r\n        console.error(\"Broadcast error\", e);\r\n        return NextResponse.json({ error: \"Failed to start broadcast\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\messages\\contact\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\messages\\delete\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":51,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":51,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1960,1963],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1960,1963],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\n\r\n/**\r\n * @deprecated This endpoint is deprecated. Use DELETE /api/messages/{sessionId}/{jid}/{messageId} instead.\r\n * This endpoint will be removed in a future version.\r\n */\r\n// DELETE: Delete message for everyone\r\nexport async function DELETE(request: NextRequest) {\r\n    console.warn('[DEPRECATED] DELETE /api/messages/delete is deprecated. Use DELETE /api/messages/{sessionId}/{jid}/{messageId} instead.');\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const body = await request.json();\r\n        const { sessionId, jid, messageId } = body;\r\n\r\n        if (!sessionId || !jid || !messageId) {\r\n            return NextResponse.json({ \r\n                error: \"sessionId, jid, and messageId are required\" \r\n            }, { status: 400 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        // Delete message for everyone\r\n        await instance.socket.sendMessage(jid, { delete: {\r\n            remoteJid: jid,\r\n            fromMe: true,\r\n            id: messageId,\r\n            participant: undefined\r\n        }});\r\n\r\n        return NextResponse.json({ \r\n            success: true,\r\n            message: \"Message deleted for everyone\"\r\n        });\r\n\r\n    } catch (error: any) {\r\n        console.error(\"Delete message error:\", error);\r\n        \r\n        if (error.message?.includes(\"too old\") || error.message?.includes(\"time limit\")) {\r\n            return NextResponse.json({ \r\n                error: \"Cannot delete message older than 7 minutes\" \r\n            }, { status: 400 });\r\n        }\r\n        \r\n        return NextResponse.json({ error: \"Failed to delete message\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\messages\\forward\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\messages\\list\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\messages\\location\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\messages\\poll\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\messages\\react\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\messages\\spam\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\messages\\sticker\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":46,"column":41,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":46,"endColumn":44,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1949,1952],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1949,1952],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\nimport Sticker from \"wa-sticker-formatter\";\r\n\r\n/**\r\n * @deprecated This endpoint is deprecated. Use POST /api/messages/{sessionId}/{jid}/sticker instead.\r\n * This endpoint will be removed in a future version.\r\n */\r\nexport async function POST(request: NextRequest) {\r\n    console.warn('[DEPRECATED] POST /api/messages/sticker is deprecated. Use POST /api/messages/{sessionId}/{jid}/sticker instead.');\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const formData = await request.formData();\r\n        const sessionId = formData.get(\"sessionId\") as string;\r\n        const jid = formData.get(\"jid\") as string;\r\n        const file = formData.get(\"file\") as File;\r\n        \r\n        if (!sessionId || !jid || !file) {\r\n             return NextResponse.json({ error: \"Missing required fields\" }, { status: 400 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        // Convert File to Buffer\r\n        const buffer = Buffer.from(await file.arrayBuffer());\r\n\r\n        // Create Sticker\r\n        const sticker = new Sticker(buffer, {\r\n            pack: \"WA-AKG\",\r\n            author: user.name || \"User\",\r\n            type: \"full\",\r\n            categories: [\"≡ƒñ⌐\", \"≡ƒÄë\"] as any,\r\n            quality: 50,\r\n            background: \"transparent\"\r\n        });\r\n\r\n        const stickerBuffer = await sticker.toBuffer();\r\n\r\n        await instance.socket.sendMessage(jid, { sticker: stickerBuffer });\r\n\r\n        return NextResponse.json({ success: true });\r\n\r\n    } catch (e) {\r\n        console.error(\"Sticker error\", e);\r\n        return NextResponse.json({ error: \"Failed to create sticker\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\notifications\\delete\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\notifications\\read\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\notifications\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'req' is defined but never used.","line":6,"column":27,"nodeType":"Identifier","messageId":"unusedVar","endLine":6,"endColumn":30},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'e' is defined but never used.","line":17,"column":14,"nodeType":"Identifier","messageId":"unusedVar","endLine":17,"endColumn":15},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":51,"column":35,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":51,"endColumn":38,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1890,1893],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1890,1893],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":80,"column":35,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":80,"endColumn":38,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2951,2954],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2951,2954],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\r\nimport { auth } from \"@/lib/auth\";\r\nimport { prisma } from \"@/lib/prisma\";\r\nimport { NextResponse } from \"next/server\";\r\n\r\nexport async function GET(req: Request) {\r\n    const session = await auth();\r\n    if (!session?.user?.id) return new Response(\"Unauthorized\", { status: 401 });\r\n\r\n    try {\r\n        const notifications = await prisma.notification.findMany({\r\n            where: { userId: session.user.id },\r\n            orderBy: { createdAt: 'desc' },\r\n            take: 50 // Limit to last 50\r\n        });\r\n        return NextResponse.json(notifications);\r\n    } catch (e) {\r\n        return new Response(\"Error fetching notifications\", { status: 500 });\r\n    }\r\n}\r\n\r\nexport async function POST(req: Request) {\r\n    const session = await auth();\r\n    if (!session?.user?.id) return new Response(\"Unauthorized\", { status: 401 });\r\n\r\n    // Only SUPERADMIN can send global notifications\r\n    // But system might trigger it too. For now check role.\r\n    const user = await prisma.user.findUnique({ where: { id: session.user.id } });\r\n    if (user?.role !== \"SUPERADMIN\") {\r\n         return new Response(\"Forbidden: Only Superadmin can send notifications\", { status: 403 });\r\n    }\r\n\r\n    try {\r\n        const { title, message, type, href, targetUserId, broadcast } = await req.json();\r\n\r\n        if (broadcast) {\r\n            // Send to ALL users\r\n            const allUsers = await prisma.user.findMany({ select: { id: true } });\r\n            const notifications = allUsers.map((u: { id: string }) => ({\r\n                userId: u.id,\r\n                title,\r\n                message,\r\n                type: type || \"INFO\",\r\n                href,\r\n                read: false\r\n            }));\r\n            \r\n            await prisma.notification.createMany({ data: notifications });\r\n            \r\n            // Emit Socket.IO event for each user\r\n            const io = (global as any).io;\r\n            if (io) {\r\n                allUsers.forEach((u: { id: string }) => {\r\n                    io.to(`user:${u.id}`).emit('notification:new', {\r\n                        userId: u.id,\r\n                        title,\r\n                        message,\r\n                        type: type || \"INFO\",\r\n                        href,\r\n                        createdAt: new Date().toISOString(),\r\n                        read: false\r\n                    });\r\n                });\r\n            }\r\n            \r\n            return NextResponse.json({ success: true, count: allUsers.length });\r\n        } else if (targetUserId) {\r\n            // Send to specific user\r\n            const notification = await prisma.notification.create({\r\n                data: {\r\n                    userId: targetUserId,\r\n                    title,\r\n                    message,\r\n                    type: type || \"INFO\",\r\n                    href,\r\n                }\r\n            });\r\n            \r\n            // Emit Socket.IO event\r\n            const io = (global as any).io;\r\n            if (io) {\r\n                io.to(`user:${targetUserId}`).emit('notification:new', {\r\n                    id: notification.id,\r\n                    userId: targetUserId,\r\n                    title,\r\n                    message,\r\n                    type: type || \"INFO\",\r\n                    href,\r\n                    createdAt: notification.createdAt\r\n                });\r\n            }\r\n            \r\n             return NextResponse.json({ success: true });\r\n        }\r\n        \r\n        return new Response(\"Invalid Request: Provide targetUserId or broadcast=true\", { status: 400 });\r\n\r\n    } catch (e) {\r\n        console.error(e);\r\n        return new Response(\"Error creating notification\", { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\profile\\[sessionId]\\name\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\profile\\[sessionId]\\picture\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\profile\\[sessionId]\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'error' is defined but never used.","line":44,"column":18,"nodeType":"Identifier","messageId":"unusedVar","endLine":44,"endColumn":23}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\n\r\n// GET: Fetch own profile\r\nexport async function GET(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string }> }\r\n) {\r\n    try {\r\n        const { sessionId } = await params;\r\n\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        // Get own JID\r\n        const meJid = instance.socket.user?.id;\r\n        if (!meJid) {\r\n            return NextResponse.json({ error: \"Unable to get own JID\" }, { status: 500 });\r\n        }\r\n\r\n        // Fetch profile status\r\n        try {\r\n            const statusInfo = await instance.socket.fetchStatus(meJid);\r\n            \r\n            return NextResponse.json({ \r\n                success: true,\r\n                jid: meJid,\r\n                status: statusInfo || null\r\n            });\r\n        } catch (error) {\r\n            // If status fetch fails, return basic info\r\n            return NextResponse.json({ \r\n                success: true,\r\n                jid: meJid,\r\n                status: null\r\n            });\r\n        }\r\n\r\n    } catch (error) {\r\n        console.error(\"Fetch profile error:\", error);\r\n        return NextResponse.json({ error: \"Failed to fetch profile\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\profile\\[sessionId]\\status\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\profile\\name\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\profile\\picture\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\profile\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'error' is defined but never used.","line":51,"column":18,"nodeType":"Identifier","messageId":"unusedVar","endLine":51,"endColumn":23}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\n\r\n/**\r\n * @deprecated This endpoint is deprecated. Use GET /api/profile/{sessionId} instead.\r\n * This endpoint will be removed in a future version.\r\n */\r\n// GET: Fetch own profile\r\nexport async function GET(request: NextRequest) {\r\n    console.warn('[DEPRECATED] GET /api/profile is deprecated. Use GET /api/profile/{sessionId} instead.');\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const { searchParams } = new URL(request.url);\r\n        const sessionId = searchParams.get(\"sessionId\");\r\n\r\n        if (!sessionId) {\r\n            return NextResponse.json({ error: \"sessionId is required\" }, { status: 400 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        // Get own JID\r\n        const meJid = instance.socket.user?.id;\r\n        if (!meJid) {\r\n            return NextResponse.json({ error: \"Unable to get own JID\" }, { status: 500 });\r\n        }\r\n\r\n        // Fetch profile status\r\n        try {\r\n            const statusInfo = await instance.socket.fetchStatus(meJid);\r\n            \r\n            return NextResponse.json({ \r\n                success: true,\r\n                jid: meJid,\r\n                status: statusInfo || null\r\n            });\r\n        } catch (error) {\r\n            // If status fetch fails, return basic info\r\n            return NextResponse.json({ \r\n                success: true,\r\n                jid: meJid,\r\n                status: null\r\n            });\r\n        }\r\n\r\n    } catch (error) {\r\n        console.error(\"Fetch profile error:\", error);\r\n        return NextResponse.json({ error: \"Failed to fetch profile\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\profile\\status\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\scheduler\\[sessionId]\\[scheduleId]\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'error' is defined but never used.","line":78,"column":14,"nodeType":"Identifier","messageId":"unusedVar","endLine":78,"endColumn":19}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { prisma } from \"@/lib/prisma\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\n\r\nexport async function PUT(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string; scheduleId: string }> }\r\n) {\r\n    try {\r\n        const { sessionId, scheduleId } = await params;\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const body = await request.json();\r\n        const { jid, content, sendAt } = body;\r\n\r\n        if (!jid || !content || !sendAt) {\r\n            return NextResponse.json({ error: \"JID, content, and sendAt are required\" }, { status: 400 });\r\n        }\r\n\r\n        const updated = await prisma.scheduledMessage.update({\r\n            where: { id: scheduleId },\r\n            data: {\r\n                jid,\r\n                content,\r\n                sendAt: new Date(sendAt)\r\n            }\r\n        });\r\n\r\n        return NextResponse.json(updated);\r\n    } catch (error) {\r\n        console.error(\"Update schedule error:\", error);\r\n        return NextResponse.json({ error: \"Internal Server Error\" }, { status: 500 });\r\n    }\r\n}\r\n\r\nexport async function DELETE(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string; scheduleId: string }> }\r\n) {\r\n    try {\r\n        const { sessionId, scheduleId } = await params;\r\n\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const msg = await prisma.scheduledMessage.findUnique({\r\n            where: { id: scheduleId },\r\n            include: { session: true }\r\n        });\r\n\r\n        if (!msg) {\r\n            return NextResponse.json({ error: \"Message not found\" }, { status: 404 });\r\n        }\r\n\r\n        // Verify the schedule belongs to this session\r\n        if (msg.session.sessionId !== sessionId) {\r\n            return NextResponse.json({ error: \"Schedule not found in this session\" }, { status: 404 });\r\n        }\r\n\r\n        await prisma.scheduledMessage.delete({ where: { id: scheduleId } });\r\n        return NextResponse.json({ success: true });\r\n\r\n    } catch (error) {\r\n        return NextResponse.json({ error: \"Internal Server Error\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\scheduler\\[sessionId]\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'error' is defined but never used.","line":40,"column":14,"nodeType":"Identifier","messageId":"unusedVar","endLine":40,"endColumn":19},{"ruleId":"@typescript-eslint/ban-ts-comment","severity":2,"message":"Use \"@ts-expect-error\" instead of \"@ts-ignore\", as \"@ts-ignore\" will do nothing if the following line is error-free.","line":79,"column":9,"nodeType":"Line","messageId":"tsIgnoreInsteadOfExpectError","endLine":79,"endColumn":22,"suggestions":[{"messageId":"replaceTsIgnoreWithTsExpectError","fix":{"range":[2627,2640],"text":"// @ts-expect-error"},"desc":"Replace \"@ts-ignore\" with \"@ts-expect-error\"."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'error' is defined but never used.","line":141,"column":14,"nodeType":"Identifier","messageId":"unusedVar","endLine":141,"endColumn":19}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { prisma } from \"@/lib/prisma\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\nimport moment from \"moment-timezone\";\r\n\r\n// GET: List Scheduled Messages\r\nexport async function GET(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string }> }\r\n) {\r\n    try {\r\n        const { sessionId } = await params;\r\n\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const session = await prisma.session.findUnique({\r\n            where: { sessionId: sessionId },\r\n            select: { id: true }\r\n        });\r\n\r\n        if (!session) {\r\n            return NextResponse.json({ error: \"Session not found\" }, { status: 404 });\r\n        }\r\n\r\n        const messages = await prisma.scheduledMessage.findMany({\r\n            where: { sessionId: session.id },\r\n            orderBy: { sendAt: 'asc' }\r\n        });\r\n\r\n        return NextResponse.json(messages);\r\n\r\n    } catch (error) {\r\n        return NextResponse.json({ error: \"Internal Server Error\" }, { status: 500 });\r\n    }\r\n}\r\n\r\n// POST: Create Scheduled Message\r\nexport async function POST(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string }> }\r\n) {\r\n    try {\r\n        const { sessionId } = await params;\r\n\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const body = await request.json();\r\n        const { jid, content, sendAt, mediaUrl, mediaType } = body;\r\n\r\n        if (!jid || !content || !sendAt) {\r\n            return NextResponse.json({ error: \"Missing required fields\" }, { status: 400 });\r\n        }\r\n\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const session = await prisma.session.findUnique({\r\n            where: { sessionId: sessionId },\r\n            select: { id: true }\r\n        });\r\n\r\n        if (!session) {\r\n            return NextResponse.json({ error: \"Session not found\" }, { status: 404 });\r\n        }\r\n\r\n        // @ts-ignore\r\n        const systemConfig = await prisma.systemConfig.findUnique({ where: { id: \"default\" } });\r\n        const timezone = systemConfig?.timezone || \"Asia/Jakarta\";\r\n\r\n        const utcDate = moment.tz(sendAt, timezone).toDate();\r\n\r\n        const scheduled = await prisma.scheduledMessage.create({\r\n            data: {\r\n                sessionId: session.id,\r\n                jid,\r\n                content,\r\n                mediaUrl,\r\n                mediaType,\r\n                sendAt: utcDate,\r\n                status: \"PENDING\"\r\n            }\r\n        });\r\n\r\n        return NextResponse.json(scheduled);\r\n\r\n    } catch (error) {\r\n        console.error(\"Schedule error:\", error);\r\n        return NextResponse.json({ error: \"Internal Server Error\" }, { status: 500 });\r\n    }\r\n\r\n}\r\n\r\n/**\r\n * @deprecated This endpoint is deprecated. Use DELETE /api/scheduler/{sessionId}/{scheduleId} instead.\r\n * This endpoint will be removed in a future version.\r\n */\r\nexport async function DELETE(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string }> }\r\n) {\r\n    console.warn('[DEPRECATED] DELETE /api/scheduler/{id} is deprecated. Use DELETE /api/scheduler/{sessionId}/{scheduleId} instead.');\r\n    // In legacy route this param was 'id', now it acts as the id (scheduleId)\r\n    const { sessionId: id } = await params;\r\n\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const msg = await prisma.scheduledMessage.findUnique({\r\n            where: { id },\r\n            include: { session: true }\r\n        });\r\n\r\n        if (!msg) {\r\n            return NextResponse.json({ error: \"Message not found\" }, { status: 404 });\r\n        }\r\n\r\n        const canAccess = await canAccessSession(user.id, user.role, msg.session.sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        await prisma.scheduledMessage.delete({ where: { id } });\r\n        return NextResponse.json({ success: true });\r\n\r\n    } catch (error) {\r\n        return NextResponse.json({ error: \"Internal Server Error\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\scheduler\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'error' is defined but never used.","line":49,"column":14,"nodeType":"Identifier","messageId":"unusedVar","endLine":49,"endColumn":19},{"ruleId":"@typescript-eslint/ban-ts-comment","severity":2,"message":"Use \"@ts-expect-error\" instead of \"@ts-ignore\", as \"@ts-ignore\" will do nothing if the following line is error-free.","line":85,"column":9,"nodeType":"Line","messageId":"tsIgnoreInsteadOfExpectError","endLine":85,"endColumn":22,"suggestions":[{"messageId":"replaceTsIgnoreWithTsExpectError","fix":{"range":[2922,2935],"text":"// @ts-expect-error"},"desc":"Replace \"@ts-ignore\" with \"@ts-expect-error\"."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { prisma } from \"@/lib/prisma\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\nimport moment from \"moment-timezone\";\r\n\r\n/**\r\n * @deprecated These endpoints are deprecated. Use GET/POST /api/scheduler/{sessionId} instead.\r\n * These endpoints will be removed in a future version.\r\n */\r\n\r\n// GET: List Scheduled Messages\r\nexport async function GET(request: NextRequest) {\r\n    console.warn('[DEPRECATED] GET /api/scheduler is deprecated. Use GET /api/scheduler/{sessionId} instead.');\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const { searchParams } = new URL(request.url);\r\n        const sessionId = searchParams.get(\"sessionId\");\r\n\r\n        if (!sessionId) {\r\n            return NextResponse.json({ error: \"Session ID is required\" }, { status: 400 });\r\n        }\r\n\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n             return NextResponse.json({ error: \"Forbidden\" }, { status: 403 });\r\n        }\r\n\r\n        // Get session ID (CUID)\r\n        const session = await prisma.session.findUnique({\r\n            where: { sessionId: sessionId },\r\n            select: { id: true }\r\n        });\r\n\r\n        if (!session) {\r\n             return NextResponse.json({ error: \"Session not found\" }, { status: 404 });\r\n        }\r\n\r\n        const messages = await prisma.scheduledMessage.findMany({\r\n            where: { sessionId: session.id },\r\n            orderBy: { sendAt: 'asc' }\r\n        });\r\n\r\n        return NextResponse.json(messages);\r\n\r\n    } catch (error) {\r\n        return NextResponse.json({ error: \"Internal Server Error\" }, { status: 500 });\r\n    }\r\n}\r\n\r\n// POST: Create Scheduled Message\r\nexport async function POST(request: NextRequest) {\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const body = await request.json();\r\n        const { sessionId, jid, content, sendAt, mediaUrl } = body;\r\n\r\n        if (!sessionId || !jid || !content || !sendAt) {\r\n            return NextResponse.json({ error: \"Missing required fields\" }, { status: 400 });\r\n        }\r\n\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden\" }, { status: 403 });\r\n        }\r\n\r\n        const session = await prisma.session.findUnique({\r\n             where: { sessionId: sessionId },\r\n             select: { id: true }\r\n        });\r\n\r\n        if (!session) {\r\n             return NextResponse.json({ error: \"Session not found\" }, { status: 404 });\r\n        }\r\n\r\n\r\n\r\n        // @ts-ignore\r\n        const systemConfig = await prisma.systemConfig.findUnique({ where: { id: \"default\" } });\r\n        const timezone = systemConfig?.timezone || \"Asia/Jakarta\";\r\n\r\n        // Convert local time (sendAt) to UTC Date object using moment-timezone\r\n        // sendAt is \"YYYY-MM-DDTHH:mm\" (local time string from input type=\"datetime-local\")\r\n        const utcDate = moment.tz(sendAt, timezone).toDate();\r\n\r\n        const scheduled = await prisma.scheduledMessage.create({\r\n            data: {\r\n                sessionId: session.id,\r\n                jid,\r\n                content,\r\n                mediaUrl,\r\n                sendAt: utcDate,\r\n                status: \"PENDING\"\r\n            }\r\n        });\r\n\r\n        return NextResponse.json(scheduled);\r\n\r\n    } catch (error) {\r\n        console.error(\"Schedule error:\", error);\r\n        return NextResponse.json({ error: \"Internal Server Error\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\sessions\\[id]\\[action]\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":61,"column":66,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":61,"endColumn":69,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2394,2397],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2394,2397],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\nimport { prisma } from \"@/lib/prisma\";\r\n\r\nexport async function POST(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ id: string, action: string }> }\r\n) {\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const resolvedParams = await params;\r\n        const sessionId = resolvedParams.id; // Renamed to id\r\n        const action = resolvedParams.action;\r\n\r\n        // Verify access\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n             return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        // Validate Action\r\n        const validActions = [\"start\", \"stop\", \"restart\", \"logout\"];\r\n        if (!validActions.includes(action)) {\r\n            return NextResponse.json({ error: \"Invalid action\" }, { status: 400 });\r\n        }\r\n\r\n        switch (action) {\r\n            case \"start\":\r\n                await waManager.startSession(sessionId);\r\n                break;\r\n            case \"stop\":\r\n                await waManager.stopSession(sessionId);\r\n                break;\r\n            case \"restart\":\r\n                await waManager.restartSession(sessionId);\r\n                break;\r\n            case \"logout\":\r\n                // Retrieve instance to logout properly\r\n                const instance = waManager.getInstance(sessionId);\r\n                if (instance?.socket) {\r\n                    await instance.socket.logout();\r\n                } else {\r\n                    // Fallback DB update if instance not running\r\n                    await prisma.session.update({\r\n                        where: { sessionId },\r\n                        data: { status: \"LOGGED_OUT\", qr: null }\r\n                    });\r\n                }\r\n                break;\r\n        }\r\n\r\n        return NextResponse.json({ success: true, message: `Session ${action}ed successfully` });\r\n\r\n    } catch (error) {\r\n        console.error(\"Session action error:\", error);\r\n        return NextResponse.json({ error: `Failed to ${(error as any).message || \"perform action\"}` }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\sessions\\[id]\\bot-config\\route.ts","messages":[{"ruleId":"@typescript-eslint/ban-ts-comment","severity":2,"message":"Use \"@ts-expect-error\" instead of \"@ts-ignore\", as \"@ts-ignore\" will do nothing if the following line is error-free.","line":22,"column":9,"nodeType":"Line","messageId":"tsIgnoreInsteadOfExpectError","endLine":22,"endColumn":22,"suggestions":[{"messageId":"replaceTsIgnoreWithTsExpectError","fix":{"range":[761,774],"text":"// @ts-expect-error"},"desc":"Replace \"@ts-ignore\" with \"@ts-expect-error\"."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":23,"column":42,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":23,"endColumn":45,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[817,820],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[817,820],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/ban-ts-comment","severity":2,"message":"Use \"@ts-expect-error\" instead of \"@ts-ignore\", as \"@ts-ignore\" will do nothing if the following line is error-free.","line":81,"column":9,"nodeType":"Line","messageId":"tsIgnoreInsteadOfExpectError","endLine":81,"endColumn":22,"suggestions":[{"messageId":"replaceTsIgnoreWithTsExpectError","fix":{"range":[2779,2792],"text":"// @ts-expect-error"},"desc":"Replace \"@ts-ignore\" with \"@ts-expect-error\"."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":82,"column":41,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":82,"endColumn":44,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2834,2837],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2834,2837],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":4,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { prisma } from \"@/lib/prisma\";\r\nimport { NextResponse, NextRequest } from \"next/server\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\n\r\nexport async function GET(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ id: string }> }\r\n) {\r\n    const { id: sessionId } = await params;\r\n\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        // @ts-ignore\r\n        const session = await (prisma as any).session.findUnique({\r\n            where: { sessionId },\r\n            select: { id: true, botConfig: true }\r\n        });\r\n\r\n        if (!session) {\r\n            return NextResponse.json({ error: \"Session not found\" }, { status: 404 });\r\n        }\r\n\r\n        // Return config or default if null\r\n        session.botConfig = session.botConfig || {\r\n            enabled: true,\r\n            botMode: 'OWNER',\r\n            botAllowedJids: [],\r\n            botBlockedJids: [],\r\n            autoReplyMode: 'ALL',\r\n            autoReplyAllowedJids: [],\r\n            autoReplyBlockedJids: [],\r\n            enableSticker: true,\r\n            enablePing: true,\r\n            enableUptime: true,\r\n            botName: \"WA-AKG Bot\",\r\n            removeBgApiKey: null,\r\n            enableVideoSticker: true,\r\n            maxStickerDuration: 10\r\n        };\r\n\r\n        return NextResponse.json(session.botConfig);\r\n    } catch (error) {\r\n        console.error(\"Get Bot Config Error:\", error);\r\n        return NextResponse.json({ error: \"Internal Server Error\" }, { status: 500 });\r\n    }\r\n}\r\n\r\nexport async function POST(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ id: string }> }\r\n) {\r\n    const { id: sessionId } = await params;\r\n\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n\r\n        const body = await request.json();\r\n\r\n        // Find session DB ID\r\n        const session = await prisma.session.findUnique({\r\n            where: { sessionId },\r\n            select: { id: true }\r\n        });\r\n\r\n        if (!session) return NextResponse.json({ error: \"Session not found\" }, { status: 404 });\r\n\r\n        // Upsert Config\r\n        // @ts-ignore\r\n        const config = await (prisma as any).botConfig.upsert({\r\n            where: { sessionId: session.id },\r\n            create: {\r\n                sessionId: session.id,\r\n                enabled: body.enabled ?? true,\r\n                botMode: body.botMode || 'OWNER',\r\n                botAllowedJids: body.botAllowedJids || [],\r\n                botBlockedJids: body.botBlockedJids || [],\r\n                autoReplyMode: body.autoReplyMode || 'ALL',\r\n                autoReplyAllowedJids: body.autoReplyAllowedJids || [],\r\n                autoReplyBlockedJids: body.autoReplyBlockedJids || [],\r\n\r\n                enableSticker: body.enableSticker ?? true,\r\n                enableVideoSticker: body.enableVideoSticker ?? true,\r\n                maxStickerDuration: body.maxStickerDuration || 10,\r\n                enablePing: body.enablePing ?? true,\r\n                enableUptime: body.enableUptime ?? true,\r\n                removeBgApiKey: body.removeBgApiKey || null,\r\n            },\r\n            update: {\r\n                botMode: body.botMode,\r\n                botAllowedJids: body.botAllowedJids,\r\n                botBlockedJids: body.botBlockedJids,\r\n                autoReplyMode: body.autoReplyMode,\r\n                autoReplyAllowedJids: body.autoReplyAllowedJids,\r\n                autoReplyBlockedJids: body.autoReplyBlockedJids,\r\n                botName: body.botName,\r\n                enableSticker: body.enableSticker,\r\n                enableVideoSticker: body.enableVideoSticker,\r\n                maxStickerDuration: body.maxStickerDuration,\r\n                enablePing: body.enablePing,\r\n                enableUptime: body.enableUptime,\r\n                removeBgApiKey: body.removeBgApiKey || null,\r\n            }\r\n        });\r\n\r\n        return NextResponse.json(config);\r\n    } catch (error) {\r\n        console.error(\"Update Bot Config Error:\", error);\r\n        return NextResponse.json({ error: \"Failed to update config\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\sessions\\[id]\\qr\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\sessions\\[id]\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\sessions\\[id]\\settings\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'isAdmin' is defined but never used.","line":4,"column":50,"nodeType":"Identifier","messageId":"unusedVar","endLine":4,"endColumn":57,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"isAdmin"},"fix":{"range":[202,211],"text":""},"desc":"Remove unused variable \"isAdmin\"."}]}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { prisma } from \"@/lib/prisma\";\r\nimport { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { getAuthenticatedUser, canAccessSession, isAdmin } from \"@/lib/api-auth\";\r\n\r\n// PATCH: Update session settings\r\nexport async function PATCH(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ id: string }> }\r\n) {\r\n    const { id: sessionId } = await params;\r\n    \r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const body = await request.json();\r\n        const { config } = body;\r\n\r\n        const updated = await prisma.session.update({\r\n            where: { sessionId },\r\n            data: { config }\r\n        });\r\n\r\n        // Update active instance if exists\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (instance) {\r\n             // In a real app we might update internal instance state\r\n        }\r\n\r\n        return NextResponse.json(updated);\r\n\r\n    } catch (e) {\r\n        console.error(\"Update session settings error:\", e);\r\n        return NextResponse.json({ error: \"Failed to update settings\" }, { status: 500 });\r\n    }\r\n}\r\n\r\n// DELETE: Delete a session\r\nexport async function DELETE(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ id: string }> }\r\n) {\r\n    const { id: sessionId } = await params;\r\n    \r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot delete this session\" }, { status: 403 });\r\n        }\r\n\r\n        // Disconnect WhatsApp session first\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (instance?.socket) {\r\n            try {\r\n                await instance.socket.logout();\r\n            } catch (e) {\r\n                console.log(\"Session logout error (might be already disconnected):\", e);\r\n            }\r\n        }\r\n        waManager.deleteSession(sessionId);\r\n\r\n        // Delete from database\r\n        await prisma.session.delete({\r\n            where: { sessionId }\r\n        });\r\n\r\n        return NextResponse.json({ success: true });\r\n\r\n    } catch (e) {\r\n        console.error(\"Delete session error:\", e);\r\n        return NextResponse.json({ error: \"Failed to delete session\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\sessions\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'prisma' is defined but never used.","line":3,"column":10,"nodeType":"Identifier","messageId":"unusedVar","endLine":3,"endColumn":16,"suggestions":[{"messageId":"removeUnusedImportDeclaration","data":{"varName":"prisma"},"fix":{"range":[115,153],"text":""},"desc":"Remove unused import declaration."}]}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { prisma } from \"@/lib/prisma\";\r\nimport { getAuthenticatedUser, getAccessibleSessions } from \"@/lib/api-auth\";\r\n\r\nexport const dynamic = 'force-dynamic';\r\n\r\n// GET: Fetch sessions (filtered by user role)\r\nexport async function GET(request: NextRequest) {\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        // Get sessions based on user role\r\n        const sessions = await getAccessibleSessions(user.id, user.role);\r\n        return NextResponse.json(sessions);\r\n    } catch (error) {\r\n        console.error(\"Get sessions error:\", error);\r\n        return NextResponse.json({ error: \"Failed to fetch sessions\" }, { status: 500 });\r\n    }\r\n}\r\n\r\n// POST: Create new session (always for the authenticated user)\r\nexport async function POST(request: NextRequest) {\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const body = await request.json();\r\n        const { name, sessionId } = body;\r\n\r\n        if (!name) {\r\n            return NextResponse.json({ error: \"Session name is required\" }, { status: 400 });\r\n        }\r\n\r\n        // Create session for the authenticated user\r\n        const session = await waManager.createSession(user.id, name, sessionId);\r\n        return NextResponse.json(session);\r\n    } catch (error) {\r\n        console.error(\"Create session error:\", error);\r\n        return NextResponse.json({ error: \"Failed to create session\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\settings\\system\\route.ts","messages":[{"ruleId":"@typescript-eslint/ban-ts-comment","severity":2,"message":"Use \"@ts-expect-error\" instead of \"@ts-ignore\", as \"@ts-ignore\" will do nothing if the following line is error-free.","line":7,"column":9,"nodeType":"Line","messageId":"tsIgnoreInsteadOfExpectError","endLine":7,"endColumn":22,"suggestions":[{"messageId":"replaceTsIgnoreWithTsExpectError","fix":{"range":[193,206],"text":"// @ts-expect-error"},"desc":"Replace \"@ts-ignore\" with \"@ts-expect-error\"."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'error' is defined but never used.","line":13,"column":14,"nodeType":"Identifier","messageId":"unusedVar","endLine":13,"endColumn":19},{"ruleId":"@typescript-eslint/ban-ts-comment","severity":2,"message":"Use \"@ts-expect-error\" instead of \"@ts-ignore\", as \"@ts-ignore\" will do nothing if the following line is error-free.","line":20,"column":9,"nodeType":"Line","messageId":"tsIgnoreInsteadOfExpectError","endLine":20,"endColumn":22,"suggestions":[{"messageId":"replaceTsIgnoreWithTsExpectError","fix":{"range":[581,594],"text":"// @ts-expect-error"},"desc":"Replace \"@ts-ignore\" with \"@ts-expect-error\"."}]},{"ruleId":"@typescript-eslint/ban-ts-comment","severity":2,"message":"Use \"@ts-expect-error\" instead of \"@ts-ignore\", as \"@ts-ignore\" will do nothing if the following line is error-free.","line":29,"column":9,"nodeType":"Line","messageId":"tsIgnoreInsteadOfExpectError","endLine":29,"endColumn":22,"suggestions":[{"messageId":"replaceTsIgnoreWithTsExpectError","fix":{"range":[950,963],"text":"// @ts-expect-error"},"desc":"Replace \"@ts-ignore\" with \"@ts-expect-error\"."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'error' is defined but never used.","line":37,"column":14,"nodeType":"Identifier","messageId":"unusedVar","endLine":37,"endColumn":19}],"suppressedMessages":[],"errorCount":3,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse } from \"next/server\";\r\nimport { prisma } from \"@/lib/prisma\";\r\nimport { getAuthenticatedUser } from \"@/lib/api-auth\";\r\n\r\nexport async function GET() {\r\n    try {\r\n        // @ts-ignore\r\n        const config = await prisma.systemConfig.findUnique({\r\n            where: { id: \"default\" }\r\n        });\r\n\r\n        return NextResponse.json(config || { appName: \"WA-AKG\" });\r\n    } catch (error) {\r\n        return NextResponse.json({ error: \"Failed to fetch settings\" }, { status: 500 });\r\n    }\r\n}\r\n\r\nexport async function POST(req: Request) {\r\n    try {\r\n        // @ts-ignore\r\n        const user = await getAuthenticatedUser(req);\r\n        if (!user || (user.role !== \"SUPERADMIN\" && user.role !== \"OWNER\")) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const body = await req.json();\r\n        const { appName, logoUrl, timezone, enableRegistration } = body;\r\n\r\n        // @ts-ignore\r\n        const config = await prisma.systemConfig.upsert({\r\n            where: { id: \"default\" },\r\n            update: { appName, logoUrl, timezone, enableRegistration: enableRegistration ?? true },\r\n            create: { id: \"default\", appName, logoUrl: logoUrl || \"\", timezone: timezone || \"Asia/Jakarta\", enableRegistration: enableRegistration ?? true }\r\n        });\r\n\r\n        return NextResponse.json(config);\r\n    } catch (error) {\r\n        return NextResponse.json({ error: \"Failed to update settings\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\status\\[sessionId]\\update\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":56,"column":35,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":56,"endColumn":38,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2201,2204],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2201,2204],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-non-null-asserted-optional-chain","severity":2,"message":"Optional chain expressions can return undefined by design - using a non-null assertion is unsafe and wrong.","line":97,"column":24,"nodeType":"TSNonNullExpression","messageId":"noNonNullOptionalChain","endLine":97,"endColumn":40,"suggestions":[{"messageId":"suggestRemovingNonNull","fix":{"range":[4083,4084],"text":""},"desc":"You should remove the non-null assertion."}]},{"ruleId":"@typescript-eslint/no-non-null-asserted-optional-chain","severity":2,"message":"Optional chain expressions can return undefined by design - using a non-null assertion is unsafe and wrong.","line":109,"column":25,"nodeType":"TSNonNullExpression","messageId":"noNonNullOptionalChain","endLine":109,"endColumn":41,"suggestions":[{"messageId":"suggestRemovingNonNull","fix":{"range":[4670,4671],"text":""},"desc":"You should remove the non-null assertion."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":136,"column":17,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":136,"endColumn":20,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[5403,5406],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[5403,5406],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":4,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { prisma } from \"@/lib/prisma\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\nimport { generateWAMessageFromContent } from \"@whiskeysockets/baileys\";\r\n\r\n// Simple mime type guesser\r\nconst getMimeType = (url: string) => {\r\n    if (url.endsWith('.png')) return 'image/png';\r\n    if (url.endsWith('.jpg') || url.endsWith('.jpeg')) return 'image/jpeg';\r\n    if (url.endsWith('.mp4')) return 'video/mp4';\r\n    return undefined; // Let Baileys guess\r\n};\r\n\r\nexport async function POST(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string }> }\r\n) {\r\n    try {\r\n        const { sessionId } = await params;\r\n\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const body = await request.json();\r\n        const { content, type = \"TEXT\", mediaUrl, backgroundColor, font, mentions } = body; \r\n        \r\n        if (!content) {\r\n             return NextResponse.json({ error: \"Missing required fields\" }, { status: 400 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        const statusJid = 'status@broadcast';\r\n        const userJid = instance.socket.user?.id || (instance.socket.authState.creds.me?.id);\r\n\r\n        if (!userJid) {\r\n             return NextResponse.json({ error: \"Session not fully connected (User JID missing)\" }, { status: 503 });\r\n        }\r\n\r\n        let resultId: string | undefined;\r\n\r\n        if (type === 'TEXT') {\r\n            // Use relayMessage for TEXT to support background color/font\r\n            const messageContent: any = { \r\n                extendedTextMessage: {\r\n                    text: content,\r\n                    backgroundArgb: backgroundColor || 0xff000000,\r\n                    font: font || 0,\r\n                    contextInfo: {\r\n                        mentionedJid: mentions && Array.isArray(mentions) ? mentions : [],\r\n                        externalAdReply: { \r\n                            title: content,\r\n                            body: \"\",\r\n                            previewType: \"PHOTO\",\r\n                            thumbnailUrl: \"\", \r\n                            sourceUrl: \"\"\r\n                        }\r\n                    }\r\n                }\r\n            };\r\n             // Clean up\r\n            if (!messageContent.extendedTextMessage.contextInfo.externalAdReply.sourceUrl) {\r\n                delete messageContent.extendedTextMessage.contextInfo.externalAdReply;\r\n            }\r\n\r\n            const msg = generateWAMessageFromContent(statusJid, messageContent, { \r\n                userJid: userJid\r\n            });\r\n\r\n            resultId = await instance.socket.relayMessage(statusJid, msg.message!, { \r\n                messageId: msg.key.id!, \r\n                statusJidList: mentions && Array.isArray(mentions) && mentions.length > 0 ? mentions : undefined,\r\n            });\r\n\r\n        } else if (type === 'IMAGE') {\r\n            if (!mediaUrl) return NextResponse.json({ error: \"Media URL required for image status\" }, { status: 400 });\r\n            \r\n            const sentMsg = await instance.socket.sendMessage(statusJid, {\r\n                image: { url: mediaUrl },\r\n                caption: content,\r\n                mimetype: getMimeType(mediaUrl) || 'image/jpeg'\r\n            }, {\r\n                statusJidList: mentions && Array.isArray(mentions) && mentions.length > 0 ? mentions : undefined\r\n            });\r\n            resultId = sentMsg?.key.id!;\r\n\r\n        } else if (type === 'VIDEO') {\r\n            if (!mediaUrl) return NextResponse.json({ error: \"Media URL required for video status\" }, { status: 400 });\r\n            \r\n            const sentMsg = await instance.socket.sendMessage(statusJid, {\r\n                video: { url: mediaUrl },\r\n                caption: content,\r\n                mimetype: getMimeType(mediaUrl) || 'video/mp4'\r\n            }, {\r\n                statusJidList: mentions && Array.isArray(mentions) && mentions.length > 0 ? mentions : undefined\r\n            });\r\n             resultId = sentMsg?.key.id!;\r\n\r\n        } else {\r\n             return NextResponse.json({ error: \"Invalid status type\" }, { status: 400 });\r\n        }\r\n        \r\n        console.log(\"Status Sent ID:\", resultId);\r\n\r\n         const dbSession = await prisma.session.findUnique({\r\n            where: { sessionId },\r\n            select: { id: true }\r\n        });\r\n\r\n        if (dbSession) {\r\n             await prisma.story.create({\r\n                data: {\r\n                    sessionId: dbSession.id,\r\n                    jid: statusJid,\r\n                    content,\r\n                    mediaUrl,\r\n                    type\r\n                }\r\n            });\r\n        }\r\n\r\n        return NextResponse.json({ success: true, id: resultId });\r\n\r\n    } catch (e: any) {\r\n        console.error(\"Post status error details:\", {\r\n            message: e.message,\r\n            stack: e.stack,\r\n            name: e.name,\r\n            cause: e.cause\r\n        });\r\n        return NextResponse.json({ \r\n            error: \"Failed to post status\", \r\n            details: e.message \r\n        }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\status\\update\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":56,"column":35,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":56,"endColumn":38,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2392,2395],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2392,2395],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-non-null-asserted-optional-chain","severity":2,"message":"Optional chain expressions can return undefined by design - using a non-null assertion is unsafe and wrong.","line":97,"column":24,"nodeType":"TSNonNullExpression","messageId":"noNonNullOptionalChain","endLine":97,"endColumn":40,"suggestions":[{"messageId":"suggestRemovingNonNull","fix":{"range":[4274,4275],"text":""},"desc":"You should remove the non-null assertion."}]},{"ruleId":"@typescript-eslint/no-non-null-asserted-optional-chain","severity":2,"message":"Optional chain expressions can return undefined by design - using a non-null assertion is unsafe and wrong.","line":109,"column":25,"nodeType":"TSNonNullExpression","messageId":"noNonNullOptionalChain","endLine":109,"endColumn":41,"suggestions":[{"messageId":"suggestRemovingNonNull","fix":{"range":[4861,4862],"text":""},"desc":"You should remove the non-null assertion."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":140,"column":17,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":140,"endColumn":20,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[5843,5846],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[5843,5846],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":4,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { waManager } from \"@/modules/whatsapp/manager\";\r\nimport { prisma } from \"@/lib/prisma\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\nimport { generateWAMessageFromContent } from \"@whiskeysockets/baileys\";\r\n\r\n// Simple mime type guesser\r\nconst getMimeType = (url: string) => {\r\n    if (url.endsWith('.png')) return 'image/png';\r\n    if (url.endsWith('.jpg') || url.endsWith('.jpeg')) return 'image/jpeg';\r\n    if (url.endsWith('.mp4')) return 'video/mp4';\r\n    return undefined; // Let Baileys guess\r\n};\r\n\r\n/**\r\n * @deprecated This endpoint is deprecated. Use POST /api/status/{sessionId}/update instead.\r\n * This endpoint will be removed in a future version.\r\n */\r\nexport async function POST(request: NextRequest) {\r\n    console.warn('[DEPRECATED] POST /api/status/update is deprecated. Use POST /api/status/{sessionId}/update instead.');\r\n    try {\r\n        const user = await getAuthenticatedUser(request);\r\n        if (!user) {\r\n            return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n        }\r\n\r\n        const body = await request.json();\r\n        const { sessionId, content, type = \"TEXT\", mediaUrl, backgroundColor, font, mentions } = body; \r\n        \r\n        if (!sessionId || !content) {\r\n             return NextResponse.json({ error: \"Missing required fields\" }, { status: 400 });\r\n        }\r\n\r\n        // Check if user can access this session\r\n        const canAccess = await canAccessSession(user.id, user.role, sessionId);\r\n        if (!canAccess) {\r\n            return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n        }\r\n\r\n        const instance = waManager.getInstance(sessionId);\r\n        if (!instance?.socket) {\r\n            return NextResponse.json({ error: \"Session not ready\" }, { status: 503 });\r\n        }\r\n\r\n        const statusJid = 'status@broadcast';\r\n        const userJid = instance.socket.user?.id || (instance.socket.authState.creds.me?.id);\r\n\r\n        if (!userJid) {\r\n             return NextResponse.json({ error: \"Session not fully connected (User JID missing)\" }, { status: 503 });\r\n        }\r\n\r\n        let resultId: string | undefined;\r\n\r\n        if (type === 'TEXT') {\r\n            // Use relayMessage for TEXT to support background color/font\r\n            const messageContent: any = { \r\n                extendedTextMessage: {\r\n                    text: content,\r\n                    backgroundArgb: backgroundColor || 0xff000000,\r\n                    font: font || 0,\r\n                    contextInfo: {\r\n                        mentionedJid: mentions && Array.isArray(mentions) ? mentions : [],\r\n                        externalAdReply: { \r\n                            title: content,\r\n                            body: \"\",\r\n                            previewType: \"PHOTO\",\r\n                            thumbnailUrl: \"\", \r\n                            sourceUrl: \"\"\r\n                        }\r\n                    }\r\n                }\r\n            };\r\n             // Clean up\r\n            if (!messageContent.extendedTextMessage.contextInfo.externalAdReply.sourceUrl) {\r\n                delete messageContent.extendedTextMessage.contextInfo.externalAdReply;\r\n            }\r\n\r\n            const msg = generateWAMessageFromContent(statusJid, messageContent, { \r\n                userJid: userJid\r\n            });\r\n\r\n            resultId = await instance.socket.relayMessage(statusJid, msg.message!, { \r\n                messageId: msg.key.id!, \r\n                statusJidList: mentions && Array.isArray(mentions) && mentions.length > 0 ? mentions : undefined,\r\n            });\r\n\r\n        } else if (type === 'IMAGE') {\r\n            if (!mediaUrl) return NextResponse.json({ error: \"Media URL required for image status\" }, { status: 400 });\r\n            \r\n            const sentMsg = await instance.socket.sendMessage(statusJid, {\r\n                image: { url: mediaUrl },\r\n                caption: content,\r\n                mimetype: getMimeType(mediaUrl) || 'image/jpeg'\r\n            }, {\r\n                statusJidList: mentions && Array.isArray(mentions) && mentions.length > 0 ? mentions : undefined\r\n            });\r\n            resultId = sentMsg?.key.id!;\r\n\r\n        } else if (type === 'VIDEO') {\r\n            if (!mediaUrl) return NextResponse.json({ error: \"Media URL required for video status\" }, { status: 400 });\r\n            \r\n            const sentMsg = await instance.socket.sendMessage(statusJid, {\r\n                video: { url: mediaUrl },\r\n                caption: content,\r\n                mimetype: getMimeType(mediaUrl) || 'video/mp4'\r\n            }, {\r\n                statusJidList: mentions && Array.isArray(mentions) && mentions.length > 0 ? mentions : undefined\r\n            });\r\n             resultId = sentMsg?.key.id!;\r\n\r\n        } else {\r\n             return NextResponse.json({ error: \"Invalid status type\" }, { status: 400 });\r\n        }\r\n        \r\n        console.log(\"Status Sent ID:\", resultId);\r\n\r\n        // Get database session ID for foreign key logic (unchanged)\r\n        // Note: moved this down to avoid DB call if send fails, but verifying session existence at start is better.\r\n        // Re-fetching or just using logic below.\r\n        \r\n         const dbSession = await prisma.session.findUnique({\r\n            where: { sessionId },\r\n            select: { id: true }\r\n        });\r\n\r\n        if (dbSession) {\r\n             await prisma.story.create({\r\n                data: {\r\n                    sessionId: dbSession.id,\r\n                    jid: statusJid,\r\n                    content,\r\n                    mediaUrl,\r\n                    type\r\n                }\r\n            });\r\n        }\r\n\r\n        return NextResponse.json({ success: true, id: resultId });\r\n\r\n    } catch (e: any) {\r\n        console.error(\"Post status error details:\", {\r\n            message: e.message,\r\n            stack: e.stack,\r\n            name: e.name,\r\n            cause: e.cause\r\n        });\r\n        return NextResponse.json({ \r\n            error: \"Failed to post status\", \r\n            details: e.message \r\n        }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\system\\check-updates\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":54,"column":31,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":54,"endColumn":34,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2221,2224],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2221,2224],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { prisma } from \"@/lib/prisma\";\r\nimport { getLatestRelease } from \"@/lib/github\";\r\nimport { NextResponse } from \"next/server\";\r\nimport { getAuthenticatedUser } from \"@/lib/api-auth\";\r\n\r\n// We'll store the last check time or version in memory or rely on Notification existence\r\n// For simplicity, we just check if a notification with this version title exists for the user.\r\n\r\nconst REPO_OWNER = \"mrifqidaffaaditya\";\r\nconst REPO_NAME = \"WA-AKG\";\r\n\r\nimport { NextRequest } from \"next/server\";\r\n\r\nexport async function POST(req: NextRequest) {\r\n    const user = await getAuthenticatedUser(req); // Support API Key\r\n    if (!user) return new Response(\"Unauthorized\", { status: 401 });\r\n    \r\n    // Check for SUPERADMIN role? Original code didn't check, but usually system updates are restricted.\r\n    // Ideally we should check user.role === 'SUPERADMIN'\r\n    // But let's stick to making it work first.\r\n    const session = { user }; // Mock session structure for compatibility if needed, or just use user.id\r\n\r\n    try {\r\n        const release = await getLatestRelease(REPO_OWNER, REPO_NAME);\r\n        if (!release) return NextResponse.json({ success: false, message: \"Could not fetch release\" });\r\n\r\n        const version = release.tag_name;\r\n        const title = `New Update Available: ${version}`;\r\n        \r\n        // Check if we already notified this user about this version\r\n        const existing = await prisma.notification.findFirst({\r\n            where: {\r\n                userId: session.user.id,\r\n                title: title\r\n            }\r\n        });\r\n\r\n        if (existing) {\r\n            return NextResponse.json({ success: true, message: \"Already up to date (notification exists)\", version });\r\n        }\r\n\r\n        // Create notification\r\n        const notification = await prisma.notification.create({\r\n            data: {\r\n                userId: session.user.id,\r\n                title: title,\r\n                message: `A new version (${version}) of ${REPO_NAME} is available! Check it out on GitHub.\\n\\n${release.name}`,\r\n                type: \"SYSTEM\",\r\n                href: release.html_url\r\n            }\r\n        });\r\n\r\n        // Emit Socket.IO event\r\n        const io = (global as any).io;\r\n        if (io) {\r\n            io.to(`user:${session.user.id}`).emit('notification:new', {\r\n                id: notification.id,\r\n                userId: session.user.id,\r\n                title,\r\n                message: notification.message,\r\n                type: \"SYSTEM\",\r\n                href: release.html_url,\r\n                createdAt: notification.createdAt\r\n            });\r\n        }\r\n\r\n        return NextResponse.json({ success: true, message: \"Notification sent\", version });\r\n\r\n    } catch (e) {\r\n        console.error(e);\r\n        return new Response(\"Error checking updates\", { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\user\\api-key\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'error' is defined but never used.","line":18,"column":14,"nodeType":"Identifier","messageId":"unusedVar","endLine":18,"endColumn":19},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'error' is defined but never used.","line":55,"column":14,"nodeType":"Identifier","messageId":"unusedVar","endLine":55,"endColumn":19}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse } from \"next/server\";\r\nimport { prisma } from \"@/lib/prisma\";\r\nimport { auth } from \"@/lib/auth\";\r\nimport { generateApiKey } from \"@/lib/api-auth\";\r\n\r\n// Get current user's API key\r\nexport async function GET() {\r\n    const session = await auth();\r\n    if (!session?.user?.id) return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n\r\n    try {\r\n        const user = await prisma.user.findUnique({\r\n            where: { id: session.user.id },\r\n            select: { apiKey: true }\r\n        });\r\n\r\n        return NextResponse.json({ apiKey: user?.apiKey || null });\r\n    } catch (error) {\r\n        return NextResponse.json({ error: \"Failed to fetch API key\" }, { status: 500 });\r\n    }\r\n}\r\n\r\n// Generate new API key\r\nexport async function POST() {\r\n    const session = await auth();\r\n    if (!session?.user?.id) return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n\r\n    try {\r\n        const newApiKey = generateApiKey();\r\n\r\n        await prisma.user.update({\r\n            where: { id: session.user.id },\r\n            data: { apiKey: newApiKey }\r\n        });\r\n\r\n        return NextResponse.json({ apiKey: newApiKey });\r\n    } catch (error) {\r\n        console.error(\"Generate API key error:\", error);\r\n        return NextResponse.json({ error: \"Failed to generate API key\" }, { status: 500 });\r\n    }\r\n}\r\n\r\n// Delete/revoke API key\r\nexport async function DELETE() {\r\n    const session = await auth();\r\n    if (!session?.user?.id) return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n\r\n    try {\r\n        await prisma.user.update({\r\n            where: { id: session.user.id },\r\n            data: { apiKey: null }\r\n        });\r\n\r\n        return NextResponse.json({ success: true });\r\n    } catch (error) {\r\n        return NextResponse.json({ error: \"Failed to revoke API key\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\users\\[id]\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":28,"column":27,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":28,"endColumn":30,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[940,943],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[940,943],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { prisma } from \"@/lib/prisma\";\r\nimport { getAuthenticatedUser, isAdmin } from \"@/lib/api-auth\";\r\nimport bcrypt from \"bcryptjs\";\r\n\r\nexport async function PATCH(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ id: string }> }\r\n) {\r\n    const user = await getAuthenticatedUser(request);\r\n    \r\n    // Only SUPERADMIN can update users\r\n    if (!user || !isAdmin(user.role)) {\r\n        return NextResponse.json({ error: \"Unauthorized\" }, { status: 403 });\r\n    }\r\n    \r\n    const { id } = await params;\r\n\r\n    try {\r\n        const body = await request.json();\r\n        const { name, email, password, role } = body;\r\n\r\n        // Prevent modifying own role to lock oneself out (optional safety)\r\n        if (id === user.id && role && role !== \"SUPERADMIN\") {\r\n             // Allow update but maybe warn? For now let it be.\r\n        }\r\n\r\n        const updateData: any = {};\r\n        if (name) updateData.name = name;\r\n        if (email) updateData.email = email;\r\n        if (role) updateData.role = role;\r\n        if (password) {\r\n            updateData.password = await bcrypt.hash(password, 10);\r\n        }\r\n\r\n        const updatedUser = await prisma.user.update({\r\n            where: { id },\r\n            data: updateData,\r\n            select: {\r\n                id: true,\r\n                name: true,\r\n                email: true,\r\n                role: true,\r\n                updatedAt: true\r\n            }\r\n        });\r\n\r\n        return NextResponse.json(updatedUser);\r\n\r\n    } catch (error) {\r\n        console.error(\"Update user error:\", error);\r\n        return NextResponse.json({ error: \"Failed to update user\" }, { status: 500 });\r\n    }\r\n}\r\n\r\nexport async function DELETE(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ id: string }> }\r\n) {\r\n    const user = await getAuthenticatedUser(request);\r\n    \r\n    // Only SUPERADMIN can delete users\r\n    if (!user || !isAdmin(user.role)) {\r\n        return NextResponse.json({ error: \"Unauthorized\" }, { status: 403 });\r\n    }\r\n    \r\n    const { id } = await params;\r\n\r\n    if (id === user.id) {\r\n        return NextResponse.json({ error: \"Cannot delete yourself\" }, { status: 400 });\r\n    }\r\n\r\n    try {\r\n        await prisma.user.delete({ where: { id } });\r\n        return NextResponse.json({ success: true });\r\n    } catch (error) {\r\n        console.error(\"Delete user error:\", error);\r\n        return NextResponse.json({ error: \"Failed to delete user\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\users\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'error' is defined but never used.","line":38,"column":14,"nodeType":"Identifier","messageId":"unusedVar","endLine":38,"endColumn":19},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":74,"column":31,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":74,"endColumn":34,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2409,2412],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2409,2412],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { prisma } from \"@/lib/prisma\";\r\nimport { getAuthenticatedUser, isAdmin } from \"@/lib/api-auth\";\r\nimport bcrypt from \"bcryptjs\";\r\nimport { z } from \"zod\";\r\n\r\nconst createUserSchema = z.object({\r\n    name: z.string().min(2),\r\n    email: z.string().email(),\r\n    password: z.string().min(6),\r\n    role: z.enum([\"SUPERADMIN\", \"OWNER\", \"STAFF\"]).default(\"OWNER\"),\r\n});\r\n\r\nexport async function GET(request: NextRequest) {\r\n    const user = await getAuthenticatedUser(request);\r\n    \r\n    // Only SUPERADMIN can list users\r\n    if (!user || !isAdmin(user.role)) {\r\n        return NextResponse.json({ error: \"Unauthorized\" }, { status: 403 });\r\n    }\r\n\r\n    try {\r\n        const users = await prisma.user.findMany({\r\n            orderBy: { createdAt: 'desc' },\r\n            select: {\r\n                id: true,\r\n                name: true,\r\n                email: true,\r\n                role: true,\r\n                createdAt: true,\r\n                _count: {\r\n                    select: { sessions: true }\r\n                }\r\n            }\r\n        });\r\n\r\n        return NextResponse.json(users);\r\n    } catch (error) {\r\n        return NextResponse.json({ error: \"Failed to fetch users\" }, { status: 500 });\r\n    }\r\n}\r\n\r\nexport async function POST(request: NextRequest) {\r\n    const user = await getAuthenticatedUser(request);\r\n    \r\n    // Only SUPERADMIN can create users\r\n    if (!user || !isAdmin(user.role)) {\r\n        return NextResponse.json({ error: \"Unauthorized\" }, { status: 403 });\r\n    }\r\n\r\n    try {\r\n        const body = await request.json();\r\n        const parseResult = createUserSchema.safeParse(body);\r\n        \r\n        if (!parseResult.success) {\r\n            return NextResponse.json({ error: parseResult.error.flatten() }, { status: 400 });\r\n        }\r\n\r\n        const { name, email, password, role } = parseResult.data;\r\n\r\n        // Check if email exists\r\n        const existing = await prisma.user.findUnique({ where: { email } });\r\n        if (existing) {\r\n            return NextResponse.json({ error: \"Email already exists\" }, { status: 400 });\r\n        }\r\n\r\n        const hashedPassword = await bcrypt.hash(password, 10);\r\n\r\n        const newUser = await prisma.user.create({\r\n            data: {\r\n                name,\r\n                email,\r\n                password: hashedPassword,\r\n                role: role as any\r\n            },\r\n            select: {\r\n                id: true,\r\n                name: true,\r\n                email: true,\r\n                role: true,\r\n                createdAt: true\r\n            }\r\n        });\r\n\r\n        return NextResponse.json(newUser);\r\n\r\n    } catch (error) {\r\n        console.error(\"Create user error:\", error);\r\n        return NextResponse.json({ error: \"Failed to create user\" }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\webhooks\\[sessionId]\\[id]\\route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\webhooks\\[sessionId]\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":98,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":98,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3335,3338],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3335,3338],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { prisma } from \"@/lib/prisma\";\r\nimport { getAuthenticatedUser, canAccessSession } from \"@/lib/api-auth\";\r\n\r\nexport async function GET(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string }> }\r\n) {\r\n    const user = await getAuthenticatedUser(request);\r\n    if (!user) {\r\n        return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n    }\r\n\r\n    const { sessionId } = await params;\r\n\r\n    // Verify access to session\r\n    const hasAccess = await canAccessSession(user.id, user.role, sessionId);\r\n    if (!hasAccess) {\r\n        return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n    }\r\n\r\n    try {\r\n        // Resolve session string ID to internal ID if needed, or just look up webhooks\r\n        // We need the internal ID to query the Webhook table\r\n        const session = await prisma.session.findUnique({\r\n            where: { sessionId: sessionId },\r\n            select: { id: true }\r\n        });\r\n\r\n        if (!session) {\r\n             return NextResponse.json({ error: \"Session not found\" }, { status: 404 });\r\n        }\r\n\r\n        const webhooks = await prisma.webhook.findMany({\r\n            where: {\r\n                userId: user.id,\r\n                OR: [\r\n                    { sessionId: session.id }, // Specific to this session\r\n                    { sessionId: null }        // Global webhooks\r\n                ]\r\n            },\r\n            orderBy: { createdAt: 'desc' }\r\n        });\r\n\r\n        return NextResponse.json(webhooks);\r\n    } catch (error) {\r\n        console.error(\"Fetch webhooks error:\", error);\r\n        return NextResponse.json({ error: \"Failed to fetch webhooks\" }, { status: 500 });\r\n    }\r\n}\r\n\r\nexport async function POST(\r\n    request: NextRequest,\r\n    { params }: { params: Promise<{ sessionId: string }> }\r\n) {\r\n    const user = await getAuthenticatedUser(request);\r\n    if (!user) {\r\n        return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n    }\r\n\r\n    const { sessionId } = await params;\r\n\r\n    const hasAccess = await canAccessSession(user.id, user.role, sessionId);\r\n    if (!hasAccess) {\r\n        return NextResponse.json({ error: \"Forbidden - Cannot access this session\" }, { status: 403 });\r\n    }\r\n\r\n    try {\r\n        const body = await request.json();\r\n        const { name, url, secret, events } = body;\r\n\r\n        if (!name || !url || !events || events.length === 0) {\r\n            return NextResponse.json({ error: \"Name, URL, and at least one event are required\" }, { status: 400 });\r\n        }\r\n\r\n        const session = await prisma.session.findUnique({\r\n            where: { sessionId: sessionId },\r\n            select: { id: true }\r\n        });\r\n\r\n        if (!session) {\r\n            return NextResponse.json({ error: \"Session not found\" }, { status: 404 });\r\n        }\r\n\r\n        const webhook = await prisma.webhook.create({\r\n            data: {\r\n                userId: user.id,\r\n                name,\r\n                url,\r\n                secret: secret || null,\r\n                sessionId: session.id, // Strictly link to this session\r\n                events,\r\n                isActive: true\r\n            }\r\n        });\r\n\r\n        return NextResponse.json(webhook);\r\n    } catch (error: any) {\r\n        console.error(\"Create webhook error detailed:\", error);\r\n        return NextResponse.json({ error: \"Failed to create webhook\", details: error.message }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\api\\webhooks\\route.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'error' is defined but never used.","line":19,"column":14,"nodeType":"Identifier","messageId":"unusedVar","endLine":19,"endColumn":19},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":64,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":64,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2275,2278],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2275,2278],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NextResponse, NextRequest } from \"next/server\";\r\nimport { prisma } from \"@/lib/prisma\";\r\nimport { getAuthenticatedUser } from \"@/lib/api-auth\";\r\n\r\nexport async function GET(request: NextRequest) {\r\n    console.warn('[DEPRECATED] GET /api/webhooks is deprecated. Use GET /api/webhooks/{sessionId} instead.');\r\n    const user = await getAuthenticatedUser(request);\r\n    if (!user) {\r\n        return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n    }\r\n\r\n    try {\r\n        const webhooks = await prisma.webhook.findMany({\r\n            where: { userId: user.id },\r\n            orderBy: { createdAt: 'desc' }\r\n        });\r\n\r\n        return NextResponse.json(webhooks);\r\n    } catch (error) {\r\n        return NextResponse.json({ error: \"Failed to fetch webhooks\" }, { status: 500 });\r\n    }\r\n}\r\n\r\nexport async function POST(request: NextRequest) {\r\n    console.warn('[DEPRECATED] POST /api/webhooks is deprecated. Use POST /api/webhooks/{sessionId} instead.');\r\n    const user = await getAuthenticatedUser(request);\r\n    if (!user) {\r\n        return NextResponse.json({ error: \"Unauthorized\" }, { status: 401 });\r\n    }\r\n\r\n    try {\r\n        const body = await request.json();\r\n        const { name, url, secret, sessionId, events } = body;\r\n\r\n        if (!name || !url || !events || events.length === 0) {\r\n            return NextResponse.json({ error: \"Name, URL, and at least one event are required\" }, { status: 400 });\r\n        }\r\n\r\n        let targetSessionId = null;\r\n        if (sessionId) {\r\n            const session = await prisma.session.findUnique({\r\n                where: { sessionId: sessionId },\r\n                select: { id: true }\r\n            });\r\n            if (!session) {\r\n                return NextResponse.json({ error: \"Session not found\" }, { status: 404 });\r\n            }\r\n            targetSessionId = session.id;\r\n        }\r\n\r\n        const webhook = await prisma.webhook.create({\r\n            data: {\r\n                userId: user.id,\r\n                name,\r\n                url,\r\n                secret: secret || null,\r\n                sessionId: targetSessionId,\r\n                events,\r\n                isActive: true\r\n            }\r\n        });\r\n\r\n        return NextResponse.json(webhook);\r\n    } catch (error: any) {\r\n        console.error(\"Create webhook error detailed:\", error);\r\n        return NextResponse.json({ error: \"Failed to create webhook\", details: error.message }, { status: 500 });\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\auth\\login\\page.tsx","messages":[{"ruleId":"react-hooks/rules-of-hooks","severity":2,"message":"React Hook \"useEffect\" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function.","line":36,"column":5,"nodeType":"Identifier","endLine":36,"endColumn":14},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'err' is defined but never used.","line":70,"column":14,"nodeType":"Identifier","messageId":"unusedVar","endLine":70,"endColumn":17},{"ruleId":"react/no-unescaped-entities","severity":2,"message":"`'` can be escaped with `&apos;`, `&lsquo;`, `&#39;`, `&rsquo;`.","line":155,"column":16,"nodeType":"JSXText","messageId":"unescapedEntityAlts","suggestions":[{"messageId":"replaceWithAlt","data":{"alt":"&apos;"},"fix":{"range":[5981,6017],"text":"\r\n            Don&apos;t have an account?"},"desc":"Replace with `&apos;`."},{"messageId":"replaceWithAlt","data":{"alt":"&lsquo;"},"fix":{"range":[5981,6017],"text":"\r\n            Don&lsquo;t have an account?"},"desc":"Replace with `&lsquo;`."},{"messageId":"replaceWithAlt","data":{"alt":"&#39;"},"fix":{"range":[5981,6017],"text":"\r\n            Don&#39;t have an account?"},"desc":"Replace with `&#39;`."},{"messageId":"replaceWithAlt","data":{"alt":"&rsquo;"},"fix":{"range":[5981,6017],"text":"\r\n            Don&rsquo;t have an account?"},"desc":"Replace with `&rsquo;`."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"'use client';\r\n\r\nimport { useState, Suspense } from 'react';\r\nimport { useForm } from 'react-hook-form';\r\nimport { zodResolver } from '@hookform/resolvers/zod';\r\nimport { z } from 'zod';\r\nimport { signIn } from 'next-auth/react';\r\nimport { useRouter, useSearchParams } from 'next/navigation';\r\nimport { Button } from \"@/components/ui/button\"\r\nimport {\r\n  Form,\r\n  FormControl,\r\n  FormField,\r\n  FormItem,\r\n  FormLabel,\r\n  FormMessage,\r\n} from \"@/components/ui/form\"\r\nimport { Input } from \"@/components/ui/input\"\r\nimport { Bot, ArrowRight, Loader2 } from \"lucide-react\";\r\nimport Link from 'next/link';\r\n\r\nconst formSchema = z.object({\r\n  email: z.string().email(\"Please enter a valid email address\"),\r\n  password: z.string().min(1, \"Password is required\"),\r\n});\r\n\r\nfunction LoginForm() {\r\n  const router = useRouter();\r\n  const searchParams = useSearchParams();\r\n  const callbackUrl = searchParams.get('callbackUrl') || '/dashboard';\r\n  const [error, setError] = useState<string | null>(null);\r\n  const [loading, setLoading] = useState(false);\r\n  const [registrationEnabled, setRegistrationEnabled] = useState<boolean | null>(null);\r\n\r\n  import('react').then(({ useEffect }) => {\r\n    useEffect(() => {\r\n      fetch('/api/settings/system')\r\n        .then(res => res.json())\r\n        .then(data => {\r\n          setRegistrationEnabled(data?.enableRegistration !== false);\r\n        })\r\n        .catch(() => setRegistrationEnabled(true));\r\n    }, []);\r\n  });\r\n\r\n  const form = useForm<z.infer<typeof formSchema>>({\r\n    resolver: zodResolver(formSchema),\r\n    defaultValues: {\r\n      email: \"\",\r\n      password: \"\",\r\n    },\r\n  });\r\n\r\n  async function onSubmit(values: z.infer<typeof formSchema>) {\r\n    setLoading(true);\r\n    setError(null);\r\n    try {\r\n      const result = await signIn('credentials', {\r\n        redirect: false,\r\n        email: values.email,\r\n        password: values.password,\r\n      });\r\n\r\n      if (result?.error) {\r\n        setError(\"Invalid email or password\");\r\n      } else {\r\n        window.location.href = callbackUrl;\r\n        router.refresh();\r\n      }\r\n    } catch (err) {\r\n      setError(\"An unexpected error occurred\");\r\n    } finally {\r\n      setLoading(false);\r\n    }\r\n  }\r\n\r\n  return (\r\n    <div className=\"flex items-center justify-center min-h-screen relative overflow-hidden bg-background\">\r\n      {/* Background Orbs */}\r\n      <div className=\"absolute top-0 left-0 -translate-x-1/2 -translate-y-1/2 w-[40rem] h-[40rem] bg-primary/20 rounded-full blur-[120px] pointer-events-none\" />\r\n      <div className=\"absolute bottom-0 right-0 translate-x-1/3 translate-y-1/3 w-[30rem] h-[30rem] bg-blue-500/20 rounded-full blur-[100px] pointer-events-none\" />\r\n\r\n      <div className=\"relative z-10 w-full max-w-md p-4 animate-in fade-in zoom-in-95 duration-500\">\r\n        <div className=\"flex flex-col items-center mb-8\">\r\n          <div className=\"relative flex h-16 w-16 mb-4 items-center justify-center rounded-2xl bg-gradient-to-br from-emerald-400 to-primary text-white shadow-lg shadow-primary/30\">\r\n            <Bot className=\"h-8 w-8\" />\r\n          </div>\r\n          <h1 className=\"text-3xl font-bold tracking-tight text-foreground\">Welcome Back</h1>\r\n          <p className=\"text-muted-foreground mt-2\">Sign in to your WA-AKG account</p>\r\n        </div>\r\n\r\n        <div className=\"glass-panel rounded-3xl p-8 shadow-2xl shadow-black/5 dark:shadow-black/40\">\r\n          {error && (\r\n            <div className=\"mb-6 p-4 rounded-xl bg-destructive/10 border border-destructive/20 text-destructive text-sm text-center font-medium animate-in shake duration-300\">\r\n              {error}\r\n            </div>\r\n          )}\r\n\r\n          <Form {...form}>\r\n            <form onSubmit={form.handleSubmit(onSubmit)} className=\"space-y-5\">\r\n              <FormField\r\n                control={form.control}\r\n                name=\"email\"\r\n                render={({ field }) => (\r\n                  <FormItem>\r\n                    <FormLabel className=\"text-foreground/80\">Email</FormLabel>\r\n                    <FormControl>\r\n                      <Input\r\n                        placeholder=\"name@example.com\"\r\n                        className=\"h-12 px-4 rounded-xl bg-background/50 border-white/20 dark:border-white/10 focus-visible:ring-primary/50 transition-all font-medium\"\r\n                        {...field}\r\n                      />\r\n                    </FormControl>\r\n                    <FormMessage />\r\n                  </FormItem>\r\n                )}\r\n              />\r\n              <FormField\r\n                control={form.control}\r\n                name=\"password\"\r\n                render={({ field }) => (\r\n                  <FormItem>\r\n                    <FormLabel className=\"text-foreground/80\">Password</FormLabel>\r\n                    <FormControl>\r\n                      <Input\r\n                        type=\"password\"\r\n                        placeholder=\"ΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇó\"\r\n                        className=\"h-12 px-4 rounded-xl bg-background/50 border-white/20 dark:border-white/10 focus-visible:ring-primary/50 transition-all font-medium\"\r\n                        {...field}\r\n                      />\r\n                    </FormControl>\r\n                    <FormMessage />\r\n                  </FormItem>\r\n                )}\r\n              />\r\n\r\n              <Button\r\n                type=\"submit\"\r\n                size=\"lg\"\r\n                className=\"w-full h-12 rounded-xl text-base shadow-lg shadow-primary/20 hover:shadow-primary/30 mt-2\"\r\n                disabled={loading}\r\n              >\r\n                {loading ? (\r\n                  <><Loader2 className=\"mr-2 h-5 w-5 animate-spin\" /> Authenticating...</>\r\n                ) : (\r\n                  <>Sign In <ArrowRight className=\"ml-2 h-5 w-5\" /></>\r\n                )}\r\n              </Button>\r\n            </form>\r\n          </Form>\r\n        </div>\r\n\r\n        {registrationEnabled !== false && (\r\n          <div className=\"mt-8 text-center text-sm text-muted-foreground\">\r\n            Don't have an account?{\" \"}\r\n            <Link href=\"/auth/register\" className=\"font-semibold text-primary hover:text-primary/80 transition-colors\">\r\n              Create an account\r\n            </Link>\r\n          </div>\r\n        )}\r\n      </div>\r\n    </div>\r\n  );\r\n}\r\n\r\nexport default function LoginPage() {\r\n  return (\r\n    <Suspense fallback={\r\n      <div className=\"flex items-center justify-center min-h-screen bg-background\">\r\n        <Loader2 className=\"h-8 w-8 animate-spin text-primary\" />\r\n      </div>\r\n    }>\r\n      <LoginForm />\r\n    </Suspense>\r\n  );\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\auth\\register\\page.tsx","messages":[{"ruleId":"react-hooks/rules-of-hooks","severity":2,"message":"React Hook \"useEffect\" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function.","line":40,"column":9,"nodeType":"Identifier","endLine":40,"endColumn":18},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":90,"column":23,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":90,"endColumn":26,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3058,3061],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3058,3061],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"'use client';\r\n\r\nimport { useState, Suspense } from 'react';\r\nimport { useForm } from 'react-hook-form';\r\nimport { zodResolver } from '@hookform/resolvers/zod';\r\nimport { z } from 'zod';\r\nimport { useRouter } from 'next/navigation';\r\nimport { Button } from \"@/components/ui/button\"\r\nimport {\r\n    Form,\r\n    FormControl,\r\n    FormField,\r\n    FormItem,\r\n    FormLabel,\r\n    FormMessage,\r\n} from \"@/components/ui/form\"\r\nimport { Input } from \"@/components/ui/input\"\r\nimport { Bot, ArrowRight, Loader2 } from \"lucide-react\";\r\nimport Link from 'next/link';\r\n\r\nconst formSchema = z.object({\r\n    name: z.string().min(2, \"Name must be at least 2 characters\"),\r\n    email: z.string().email(\"Please enter a valid email address\"),\r\n    password: z.string().min(6, \"Password must be at least 6 characters\"),\r\n    confirmPassword: z.string()\r\n}).refine((data) => data.password === data.confirmPassword, {\r\n    message: \"Passwords do not match\",\r\n    path: [\"confirmPassword\"],\r\n});\r\n\r\nfunction RegisterForm() {\r\n    const router = useRouter();\r\n    const [error, setError] = useState<string | null>(null);\r\n    const [success, setSuccess] = useState(false);\r\n    const [loading, setLoading] = useState(false);\r\n    const [registrationEnabled, setRegistrationEnabled] = useState<boolean | null>(null);\r\n\r\n    // Fetch system settings to check if registration is enabled\r\n    import('react').then(({ useEffect }) => {\r\n        useEffect(() => {\r\n            fetch('/api/settings/system')\r\n                .then(res => res.json())\r\n                .then(data => {\r\n                    if (data && data.enableRegistration !== undefined) {\r\n                        setRegistrationEnabled(data.enableRegistration);\r\n                    } else {\r\n                        setRegistrationEnabled(true);\r\n                    }\r\n                })\r\n                .catch(() => setRegistrationEnabled(true));\r\n        }, []);\r\n    });\r\n\r\n    const form = useForm<z.infer<typeof formSchema>>({\r\n        resolver: zodResolver(formSchema),\r\n        defaultValues: {\r\n            name: \"\",\r\n            email: \"\",\r\n            password: \"\",\r\n            confirmPassword: \"\"\r\n        },\r\n    });\r\n\r\n    async function onSubmit(values: z.infer<typeof formSchema>) {\r\n        setLoading(true);\r\n        setError(null);\r\n        try {\r\n            const response = await fetch('/api/auth/register', {\r\n                method: 'POST',\r\n                headers: {\r\n                    'Content-Type': 'application/json',\r\n                },\r\n                body: JSON.stringify({\r\n                    name: values.name,\r\n                    email: values.email,\r\n                    password: values.password,\r\n                }),\r\n            });\r\n\r\n            if (!response.ok) {\r\n                const errorData = await response.json();\r\n                throw new Error(errorData.error || \"Failed to register\");\r\n            }\r\n\r\n            setSuccess(true);\r\n            setTimeout(() => {\r\n                router.push('/auth/login');\r\n            }, 2000);\r\n\r\n        } catch (err: any) {\r\n            setError(err.message || \"An unexpected error occurred\");\r\n        } finally {\r\n            setLoading(false);\r\n        }\r\n    }\r\n\r\n    if (success) {\r\n        return (\r\n            <div className=\"flex flex-col items-center justify-center min-h-screen bg-background relative overflow-hidden\">\r\n                <div className=\"absolute top-0 left-0 -translate-x-1/2 -translate-y-1/2 w-[40rem] h-[40rem] bg-primary/20 rounded-full blur-[120px] pointer-events-none\" />\r\n                <div className=\"glass-panel p-10 rounded-3xl flex flex-col items-center text-center max-w-sm animate-in zoom-in duration-500\">\r\n                    <div className=\"h-16 w-16 bg-emerald-500 rounded-full flex items-center justify-center mb-6 shadow-lg shadow-emerald-500/30\">\r\n                        <Bot className=\"h-8 w-8 text-white\" />\r\n                    </div>\r\n                    <h2 className=\"text-2xl font-bold text-foreground mb-2\">Registration Successful!</h2>\r\n                    <p className=\"text-muted-foreground\">Redirecting you to the login page...</p>\r\n                </div>\r\n            </div>\r\n        );\r\n    }\r\n\r\n    if (registrationEnabled === false) {\r\n        return (\r\n            <div className=\"flex flex-col items-center justify-center min-h-screen bg-background relative overflow-hidden\">\r\n                <div className=\"absolute top-0 left-0 -translate-x-1/2 -translate-y-1/2 w-[40rem] h-[40rem] bg-amber-500/20 rounded-full blur-[120px] pointer-events-none\" />\r\n                <div className=\"glass-panel p-10 rounded-3xl flex flex-col items-center text-center max-w-sm animate-in zoom-in duration-500\">\r\n                    <div className=\"h-16 w-16 bg-amber-500/20 rounded-2xl flex items-center justify-center mb-6 shadow-lg shadow-amber-500/30 border border-amber-500/50\">\r\n                        <Bot className=\"h-8 w-8 text-amber-500\" />\r\n                    </div>\r\n                    <h2 className=\"text-2xl font-bold text-foreground mb-2\">Registration Disabled</h2>\r\n                    <p className=\"text-muted-foreground mb-6\">The administrator has currently disabled new account registrations.</p>\r\n                    <Link href=\"/auth/login\">\r\n                        <Button variant=\"outline\" className=\"w-full\">Return to Login</Button>\r\n                    </Link>\r\n                </div>\r\n            </div>\r\n        );\r\n    }\r\n\r\n    if (registrationEnabled === null) {\r\n        return (\r\n            <div className=\"flex items-center justify-center min-h-screen bg-background\">\r\n                <Loader2 className=\"h-8 w-8 animate-spin text-primary\" />\r\n            </div>\r\n        );\r\n    }\r\n\r\n    return (\r\n        <div className=\"flex items-center justify-center min-h-screen relative overflow-hidden bg-background py-12\">\r\n            {/* Background Orbs */}\r\n            <div className=\"absolute top-0 left-0 w-full h-full overflow-hidden -z-10 pointer-events-none\">\r\n                <div className=\"absolute top-0 right-0 translate-x-1/3 -translate-y-1/4 w-[40rem] h-[40rem] bg-emerald-500/10 rounded-full blur-[120px]\" />\r\n                <div className=\"absolute bottom-0 left-0 -translate-x-1/4 translate-y-1/4 w-[30rem] h-[30rem] bg-primary/20 rounded-full blur-[100px]\" />\r\n            </div>\r\n\r\n            <div className=\"relative z-10 w-full max-w-md p-4 animate-in fade-in zoom-in-95 duration-500\">\r\n                <div className=\"flex flex-col items-center mb-8\">\r\n                    <div className=\"relative flex h-16 w-16 mb-4 items-center justify-center rounded-2xl bg-gradient-to-br from-emerald-400 to-primary text-white shadow-lg shadow-primary/30\">\r\n                        <Bot className=\"h-8 w-8\" />\r\n                    </div>\r\n                    <h1 className=\"text-3xl font-bold tracking-tight text-foreground\">Create Account</h1>\r\n                    <p className=\"text-muted-foreground mt-2\">Join WA-AKG today</p>\r\n                </div>\r\n\r\n                <div className=\"glass-panel rounded-3xl p-8 shadow-2xl shadow-black/5 dark:shadow-black/40\">\r\n                    {error && (\r\n                        <div className=\"mb-6 p-4 rounded-xl bg-destructive/10 border border-destructive/20 text-destructive text-sm text-center font-medium animate-in shake duration-300\">\r\n                            {error}\r\n                        </div>\r\n                    )}\r\n\r\n                    <Form {...form}>\r\n                        <form onSubmit={form.handleSubmit(onSubmit)} className=\"space-y-4\">\r\n                            <FormField\r\n                                control={form.control}\r\n                                name=\"name\"\r\n                                render={({ field }) => (\r\n                                    <FormItem>\r\n                                        <FormLabel className=\"text-foreground/80\">Full Name</FormLabel>\r\n                                        <FormControl>\r\n                                            <Input\r\n                                                placeholder=\"John Doe\"\r\n                                                className=\"h-12 px-4 rounded-xl bg-background/50 border-white/20 dark:border-white/10 focus-visible:ring-primary/50 transition-all font-medium\"\r\n                                                {...field}\r\n                                            />\r\n                                        </FormControl>\r\n                                        <FormMessage />\r\n                                    </FormItem>\r\n                                )}\r\n                            />\r\n                            <FormField\r\n                                control={form.control}\r\n                                name=\"email\"\r\n                                render={({ field }) => (\r\n                                    <FormItem>\r\n                                        <FormLabel className=\"text-foreground/80\">Email</FormLabel>\r\n                                        <FormControl>\r\n                                            <Input\r\n                                                placeholder=\"name@example.com\"\r\n                                                className=\"h-12 px-4 rounded-xl bg-background/50 border-white/20 dark:border-white/10 focus-visible:ring-primary/50 transition-all font-medium\"\r\n                                                {...field}\r\n                                            />\r\n                                        </FormControl>\r\n                                        <FormMessage />\r\n                                    </FormItem>\r\n                                )}\r\n                            />\r\n                            <FormField\r\n                                control={form.control}\r\n                                name=\"password\"\r\n                                render={({ field }) => (\r\n                                    <FormItem>\r\n                                        <FormLabel className=\"text-foreground/80\">Password</FormLabel>\r\n                                        <FormControl>\r\n                                            <Input\r\n                                                type=\"password\"\r\n                                                placeholder=\"ΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇó\"\r\n                                                className=\"h-12 px-4 rounded-xl bg-background/50 border-white/20 dark:border-white/10 focus-visible:ring-primary/50 transition-all font-medium\"\r\n                                                {...field}\r\n                                            />\r\n                                        </FormControl>\r\n                                        <FormMessage />\r\n                                    </FormItem>\r\n                                )}\r\n                            />\r\n                            <FormField\r\n                                control={form.control}\r\n                                name=\"confirmPassword\"\r\n                                render={({ field }) => (\r\n                                    <FormItem>\r\n                                        <FormLabel className=\"text-foreground/80\">Confirm Password</FormLabel>\r\n                                        <FormControl>\r\n                                            <Input\r\n                                                type=\"password\"\r\n                                                placeholder=\"ΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇó\"\r\n                                                className=\"h-12 px-4 rounded-xl bg-background/50 border-white/20 dark:border-white/10 focus-visible:ring-primary/50 transition-all font-medium\"\r\n                                                {...field}\r\n                                            />\r\n                                        </FormControl>\r\n                                        <FormMessage />\r\n                                    </FormItem>\r\n                                )}\r\n                            />\r\n\r\n                            <Button\r\n                                type=\"submit\"\r\n                                size=\"lg\"\r\n                                className=\"w-full h-12 rounded-xl text-base shadow-lg shadow-primary/20 hover:shadow-primary/30 mt-4\"\r\n                                disabled={loading}\r\n                            >\r\n                                {loading ? (\r\n                                    <><Loader2 className=\"mr-2 h-5 w-5 animate-spin\" /> Creating Account...</>\r\n                                ) : (\r\n                                    <>Register <ArrowRight className=\"ml-2 h-5 w-5\" /></>\r\n                                )}\r\n                            </Button>\r\n                        </form>\r\n                    </Form>\r\n\r\n                    <div className=\"mt-6 text-xs text-center text-muted-foreground leading-relaxed\">\r\n                        By registering, you agree to our <Link href=\"/terms\" className=\"underline hover:text-foreground\">Terms of Service</Link> and <Link href=\"/privacy\" className=\"underline hover:text-foreground\">Privacy Policy</Link>.\r\n                    </div>\r\n                </div>\r\n\r\n                <div className=\"mt-8 text-center text-sm text-muted-foreground\">\r\n                    Already have an account?{\" \"}\r\n                    <Link href=\"/auth/login\" className=\"font-semibold text-primary hover:text-primary/80 transition-colors\">\r\n                        Sign in\r\n                    </Link>\r\n                </div>\r\n            </div>\r\n        </div>\r\n    );\r\n}\r\n\r\nexport default function RegisterPage() {\r\n    return (\r\n        <Suspense fallback={\r\n            <div className=\"flex items-center justify-center min-h-screen bg-background\">\r\n                <Loader2 className=\"h-8 w-8 animate-spin text-primary\" />\r\n            </div>\r\n        }>\r\n            <RegisterForm />\r\n        </Suspense>\r\n    );\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\dashboard\\api-docs\\page.tsx","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'session' is assigned a value but never used.","line":9,"column":19,"nodeType":"Identifier","messageId":"unusedVar","endLine":9,"endColumn":26}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\"use client\";\r\n\r\nimport { useEffect, useState } from \"react\";\r\nimport { useSession } from \"next-auth/react\";\r\nimport { useRouter } from \"next/navigation\";\r\nimport { FileText, Code, ExternalLink } from \"lucide-react\";\r\n\r\nexport default function ApiDocsPage() {\r\n    const { data: session, status } = useSession();\r\n    const router = useRouter();\r\n    const [filter, setFilter] = useState(\"\");\r\n    const [selectedCategory, setSelectedCategory] = useState(\"All\");\r\n\r\n    useEffect(() => {\r\n        if (status === \"unauthenticated\") {\r\n            router.push(\"/auth/login\");\r\n        }\r\n    }, [status, router]);\r\n\r\n    const apiEndpoints = [\r\n        // Sessions\r\n        { category: \"Sessions\", method: \"GET\", path: \"/api/sessions\", description: \"List all sessions\", params: \"-\" },\r\n        { category: \"Sessions\", method: \"POST\", path: \"/api/sessions\", description: \"Create new session\", params: \"Body: { name, sessionId }\" },\r\n        { category: \"Sessions\", method: \"GET\", path: \"/api/sessions/[id]\", description: \"Get session details\", params: \"Path: id\" },\r\n        { category: \"Sessions\", method: \"GET\", path: \"/api/sessions/[id]/qr\", description: \"Get QR code\", params: \"Path: id\" },\r\n        { category: \"Sessions\", method: \"GET\", path: \"/api/sessions/[id]/bot-config\", description: \"Get bot config\", params: \"Path: id\" },\r\n        { category: \"Sessions\", method: \"POST\", path: \"/api/sessions/[id]/bot-config\", description: \"Update bot config\", params: \"Path: id, Body: { enabled, botMode, ... }\" },\r\n        { category: \"Sessions\", method: \"PATCH\", path: \"/api/sessions/[id]/settings\", description: \"Update settings\", params: \"Path: id, Body: { config }\" },\r\n        { category: \"Sessions\", method: \"DELETE\", path: \"/api/sessions/[id]/settings\", description: \"Delete session\", params: \"Path: id\" },\r\n        { category: \"Sessions\", method: \"POST\", path: \"/api/sessions/[id]/[action]\", description: \"Control session\", params: \"Path: id, action (start|stop|restart|logout)\" },\r\n\r\n        // Groups\r\n        { category: \"Groups\", method: \"GET\", path: \"/api/groups/[sessionId]\", description: \"List groups\", params: \"Path: sessionId\" },\r\n        { category: \"Groups\", method: \"POST\", path: \"/api/groups/[sessionId]/create\", description: \"Create group\", params: \"Path: sessionId, Body: { subject, participants }\" },\r\n        { category: \"Groups\", method: \"POST\", path: \"/api/groups/[sessionId]/invite/accept\", description: \"Accept invite\", params: \"Path: sessionId, Body: { code }\" },\r\n        { category: \"Groups\", method: \"PUT\", path: \"/api/groups/[sessionId]/[jid]/picture\", description: \"Update group picture\", params: \"Path: sessionId, jid, Body: { file } (multipart/form-data)\" },\r\n        { category: \"Groups\", method: \"DELETE\", path: \"/api/groups/[sessionId]/[jid]/picture\", description: \"Remove group picture\", params: \"Path: sessionId, jid\" },\r\n        { category: \"Groups\", method: \"PUT\", path: \"/api/groups/[sessionId]/[jid]/subject\", description: \"Update group name\", params: \"Path: sessionId, jid, Body: { subject }\" },\r\n        { category: \"Groups\", method: \"PUT\", path: \"/api/groups/[sessionId]/[jid]/description\", description: \"Update description\", params: \"Path: sessionId, jid, Body: { description }\" },\r\n        { category: \"Groups\", method: \"GET\", path: \"/api/groups/[sessionId]/[jid]/invite\", description: \"Get invite code\", params: \"Path: sessionId, jid\" },\r\n        { category: \"Groups\", method: \"PUT\", path: \"/api/groups/[sessionId]/[jid]/invite/revoke\", description: \"Revoke invite\", params: \"Path: sessionId, jid\" },\r\n        { category: \"Groups\", method: \"PUT\", path: \"/api/groups/[sessionId]/[jid]/members\", description: \"Manage members\", params: \"Path: sessionId, jid, Body: { action, participants }\" },\r\n        { category: \"Groups\", method: \"PUT\", path: \"/api/groups/[sessionId]/[jid]/settings\", description: \"Update settings\", params: \"Path: sessionId, jid, Body: { settings }\" },\r\n        { category: \"Groups\", method: \"PUT\", path: \"/api/groups/[sessionId]/[jid]/ephemeral\", description: \"Toggle disappearing\", params: \"Path: sessionId, jid, Body: { ephemeral }\" },\r\n        { category: \"Groups\", method: \"POST\", path: \"/api/groups/[sessionId]/[jid]/leave\", description: \"Leave group\", params: \"Path: sessionId, jid\" },\r\n\r\n        // Groups (Legacy)\r\n        { category: \"Groups\", method: \"GET\", path: \"/api/groups\", description: \"List groups [DEPRECATED]\", params: \"Query: sessionId\" },\r\n        { category: \"Groups\", method: \"POST\", path: \"/api/groups/create\", description: \"Create group [DEPRECATED]\", params: \"Body: { sessionId, subject, participants }\" },\r\n        { category: \"Groups\", method: \"POST\", path: \"/api/groups/invite/accept\", description: \"Accept invite [DEPRECATED]\", params: \"Body: { sessionId, code }\" },\r\n\r\n        // Profile\r\n        { category: \"Profile\", method: \"GET\", path: \"/api/profile/[sessionId]\", description: \"Get own profile\", params: \"Path: sessionId\" },\r\n        { category: \"Profile\", method: \"PUT\", path: \"/api/profile/[sessionId]/name\", description: \"Update name\", params: \"Path: sessionId, Body: { name }\" },\r\n        { category: \"Profile\", method: \"PUT\", path: \"/api/profile/[sessionId]/status\", description: \"Update status\", params: \"Path: sessionId, Body: { status }\" },\r\n        { category: \"Profile\", method: \"PUT\", path: \"/api/profile/[sessionId]/picture\", description: \"Update picture\", params: \"Path: sessionId, Body: { image } (multipart/form-data)\" },\r\n        { category: \"Profile\", method: \"DELETE\", path: \"/api/profile/[sessionId]/picture\", description: \"Remove picture\", params: \"Path: sessionId\" },\r\n\r\n        // Profile (Legacy)\r\n        { category: \"Profile\", method: \"GET\", path: \"/api/profile\", description: \"Get profile [DEPRECATED]\", params: \"Query: sessionId\" },\r\n        { category: \"Profile\", method: \"PUT\", path: \"/api/profile/name\", description: \"Update name [DEPRECATED]\", params: \"Body: { sessionId, name }\" },\r\n        { category: \"Profile\", method: \"PUT\", path: \"/api/profile/picture\", description: \"Update picture [DEPRECATED]\", params: \"Body: { sessionId, image }\" },\r\n        { category: \"Profile\", method: \"DELETE\", path: \"/api/profile/picture\", description: \"Remove picture [DEPRECATED]\", params: \"Body: { sessionId }\" },\r\n        { category: \"Profile\", method: \"PUT\", path: \"/api/profile/status\", description: \"Update status [DEPRECATED]\", params: \"Body: { sessionId, status }\" },\r\n\r\n        // Messaging\r\n        { category: \"Messaging\", method: \"POST\", path: \"/api/messages/[sessionId]/[jid]/send\", description: \"Send message\", params: \"Path: sessionId, jid, Body: { message }\" },\r\n        { category: \"Messaging\", method: \"POST\", path: \"/api/messages/[sessionId]/[jid]/list\", description: \"Send list message\", params: \"Path: sessionId, jid, Body: { ... }\" },\r\n        { category: \"Messaging\", method: \"POST\", path: \"/api/messages/[sessionId]/[jid]/location\", description: \"Send location\", params: \"Path: sessionId, jid, Body: { location }\" },\r\n        { category: \"Messaging\", method: \"POST\", path: \"/api/messages/[sessionId]/[jid]/poll\", description: \"Send poll\", params: \"Path: sessionId, jid, Body: { poll }\" },\r\n        { category: \"Messaging\", method: \"POST\", path: \"/api/messages/[sessionId]/[jid]/spam\", description: \"Report spam\", params: \"Path: sessionId, jid\" },\r\n        { category: \"Messaging\", method: \"POST\", path: \"/api/messages/[sessionId]/[jid]/sticker\", description: \"Send sticker\", params: \"Path: sessionId, jid, Body: { file, pack, author, type, quality } (multipart/form-data)\" },\r\n        { category: \"Messaging\", method: \"POST\", path: \"/api/messages/[sessionId]/[jid]/[messageId]/react\", description: \"Send reaction\", params: \"Path: sessionId, jid, messageId\" },\r\n        { category: \"Messaging\", method: \"POST\", path: \"/api/messages/[sessionId]/[jid]/contact\", description: \"Send contact\", params: \"Path: sessionId, jid, Body: { vcard }\" },\r\n        { category: \"Messaging\", method: \"POST\", path: \"/api/messages/[sessionId]/[jid]/forward\", description: \"Forward message\", params: \"Path: sessionId, jid, Body: { messageId }\" },\r\n        { category: \"Messaging\", method: \"POST\", path: \"/api/messages/[sessionId]/broadcast\", description: \"Broadcast message\", params: \"Path: sessionId, Body: { jids[], message }\" },\r\n        { category: \"Messaging\", method: \"DELETE\", path: \"/api/messages/[sessionId]/[jid]/[messageId]\", description: \"Delete message\", params: \"Path: sessionId, jid, messageId\" },\r\n\r\n        { category: \"Messaging\", method: \"GET\", path: \"/api/messages/[sessionId]/download/[messageId]/media\", description: \"Download media\", params: \"Path: sessionId, messageId\" },\r\n        { category: \"Messaging\", method: \"GET\", path: \"/api/media/[filename]\", description: \"Serve media file\", params: \"Path: filename\" },\r\n\r\n        // Messaging (Legacy)\r\n        { category: \"Messaging\", method: \"POST\", path: \"/api/messages/broadcast\", description: \"Broadcast message [DEPRECATED]\", params: \"Body: { sessionId, jids[], message }\" },\r\n        { category: \"Messaging\", method: \"POST\", path: \"/api/messages/contact\", description: \"Send contact [DEPRECATED]\", params: \"Body: { sessionId, jid, vcard }\" },\r\n        { category: \"Messaging\", method: \"DELETE\", path: \"/api/messages/delete\", description: \"Delete message [DEPRECATED]\", params: \"Body: { sessionId, jid, messageId }\" },\r\n        { category: \"Messaging\", method: \"POST\", path: \"/api/messages/forward\", description: \"Forward message [DEPRECATED]\", params: \"Body: { sessionId, jid, messageId }\" },\r\n        { category: \"Messaging\", method: \"POST\", path: \"/api/messages/list\", description: \"Send list message [DEPRECATED]\", params: \"Body: { sessionId, jid, ... }\" },\r\n        { category: \"Messaging\", method: \"POST\", path: \"/api/messages/location\", description: \"Send location [DEPRECATED]\", params: \"Body: { sessionId, jid, location }\" },\r\n        { category: \"Messaging\", method: \"POST\", path: \"/api/messages/poll\", description: \"Send poll [DEPRECATED]\", params: \"Body: { sessionId, jid, poll }\" },\r\n        { category: \"Messaging\", method: \"POST\", path: \"/api/messages/react\", description: \"Send reaction [DEPRECATED]\", params: \"Body: { sessionId, jid, reaction }\" },\r\n        { category: \"Messaging\", method: \"POST\", path: \"/api/messages/spam\", description: \"Report spam [DEPRECATED]\", params: \"Body: { sessionId, jid }\" },\r\n        { category: \"Messaging\", method: \"POST\", path: \"/api/messages/sticker\", description: \"Send sticker [DEPRECATED]\", params: \"Body: { sessionId, jid, sticker }\" },\r\n\r\n        // Chat\r\n        { category: \"Chat\", method: \"GET\", path: \"/api/chat/[sessionId]\", description: \"Get chats\", params: \"Path: sessionId, Query: page, limit\" },\r\n        { category: \"Chat\", method: \"GET\", path: \"/api/chat/[sessionId]/[jid]\", description: \"Get specific chat\", params: \"Path: sessionId, jid, Query: limit\" },\r\n        { category: \"Chat\", method: \"POST\", path: \"/api/chat/[sessionId]/check\", description: \"Check WhatsApp numbers\", params: \"Path: sessionId, Body: { phones[] }\" },\r\n        { category: \"Chat\", method: \"PUT\", path: \"/api/chat/[sessionId]/[jid]/read\", description: \"Mark as read\", params: \"Path: sessionId, jid\" },\r\n        { category: \"Chat\", method: \"POST\", path: \"/api/chat/[sessionId]/[jid]/archive\", description: \"Archive chat\", params: \"Path: sessionId, jid, Body: { archive }\" },\r\n        { category: \"Chat\", method: \"POST\", path: \"/api/chat/[sessionId]/[jid]/presence\", description: \"Send presence\", params: \"Path: sessionId, jid, Body: { presence }\" },\r\n        { category: \"Chat\", method: \"POST\", path: \"/api/chat/[sessionId]/[jid]/profile-picture\", description: \"Get profile picture\", params: \"Path: sessionId, jid\" },\r\n        { category: \"Chat\", method: \"PUT\", path: \"/api/chat/[sessionId]/[jid]/mute\", description: \"Mute chat\", params: \"Path: sessionId, jid, Body: { mute }\" },\r\n        { category: \"Chat\", method: \"PUT\", path: \"/api/chat/[sessionId]/[jid]/pin\", description: \"Pin chat\", params: \"Path: sessionId, jid, Body: { pin }\" },\r\n        { category: \"Chat\", method: \"GET\", path: \"/api/chats/[sessionId]/by-label/[labelId]\", description: \"Filter by label\", params: \"Path: sessionId, labelId\" },\r\n\r\n        // Chat (Legacy)\r\n        { category: \"Chat\", method: \"POST\", path: \"/api/chat/[sessionId]/send\", description: \"Send message [DEPRECATED]\", params: \"Path: sessionId, Body: { jid, message }\" },\r\n        { category: \"Chat\", method: \"PUT\", path: \"/api/chat/archive\", description: \"Archive chat [DEPRECATED]\", params: \"Body: { sessionId, jid, archive }\" },\r\n        { category: \"Chat\", method: \"POST\", path: \"/api/chat/check\", description: \"Check WhatsApp numbers [DEPRECATED]\", params: \"Body: { sessionId, phones[] }\" },\r\n        { category: \"Chat\", method: \"PUT\", path: \"/api/chat/mute\", description: \"Mute chat [DEPRECATED]\", params: \"Body: { sessionId, jid, mute }\" },\r\n        { category: \"Chat\", method: \"PUT\", path: \"/api/chat/pin\", description: \"Pin chat [DEPRECATED]\", params: \"Body: { sessionId, jid, pin }\" },\r\n        { category: \"Chat\", method: \"POST\", path: \"/api/chat/presence\", description: \"Send presence [DEPRECATED]\", params: \"Body: { sessionId, jid, presence }\" },\r\n        { category: \"Chat\", method: \"POST\", path: \"/api/chat/profile-picture\", description: \"Get profile picture [DEPRECATED]\", params: \"Body: { sessionId, jid }\" },\r\n        { category: \"Chat\", method: \"PUT\", path: \"/api/chat/read\", description: \"Mark as read [DEPRECATED]\", params: \"Body: { sessionId, jid }\" },\r\n        { category: \"Chat\", method: \"POST\", path: \"/api/chat/send\", description: \"Send message [DEPRECATED]\", params: \"Body: { sessionId, jid, message }\" },\r\n        { category: \"Chat\", method: \"GET\", path: \"/api/chats/by-label/[labelId]\", description: \"Filter by label [DEPRECATED]\", params: \"Path: labelId, Query: sessionId\" },\r\n\r\n        // Contacts\r\n        { category: \"Contacts\", method: \"GET\", path: \"/api/contacts/[sessionId]\", description: \"List contacts\", params: \"Path: sessionId, Query: search\" },\r\n        { category: \"Contacts\", method: \"POST\", path: \"/api/contacts/[sessionId]/[jid]/block\", description: \"Block contact\", params: \"Path: sessionId, jid\" },\r\n        { category: \"Contacts\", method: \"POST\", path: \"/api/contacts/[sessionId]/[jid]/unblock\", description: \"Unblock contact\", params: \"Path: sessionId, jid\" },\r\n\r\n        // Contacts (Legacy)\r\n        { category: \"Contacts\", method: \"GET\", path: \"/api/contacts\", description: \"List contacts [DEPRECATED]\", params: \"Query: search\" },\r\n        { category: \"Contacts\", method: \"POST\", path: \"/api/contacts/block\", description: \"Block contact [DEPRECATED]\", params: \"Body: { sessionId, jid }\" },\r\n        { category: \"Contacts\", method: \"POST\", path: \"/api/contacts/unblock\", description: \"Unblock contact [DEPRECATED]\", params: \"Body: { sessionId, jid }\" },\r\n\r\n        // Labels\r\n        { category: \"Labels\", method: \"GET\", path: \"/api/labels/[sessionId]\", description: \"List labels\", params: \"Path: sessionId\" },\r\n        { category: \"Labels\", method: \"POST\", path: \"/api/labels/[sessionId]\", description: \"Create label\", params: \"Path: sessionId, Body: { name, color }\" },\r\n        { category: \"Labels\", method: \"PUT\", path: \"/api/labels/[sessionId]/[id]\", description: \"Update label\", params: \"Path: sessionId, id, Body: { name, color }\" },\r\n        { category: \"Labels\", method: \"DELETE\", path: \"/api/labels/[sessionId]/[id]\", description: \"Delete label\", params: \"Path: sessionId, id\" },\r\n        { category: \"Labels\", method: \"GET\", path: \"/api/labels/[sessionId]/chat-labels/[jid]\", description: \"Get chat labels\", params: \"Path: sessionId, jid\" },\r\n        { category: \"Labels\", method: \"PUT\", path: \"/api/labels/[sessionId]/chat-labels/[jid]\", description: \"Add/remove labels\", params: \"Path: sessionId, jid, Body: { labelIds[], action }\" },\r\n\r\n        // Labels (Legacy)\r\n        { category: \"Labels\", method: \"GET\", path: \"/api/labels\", description: \"List labels [DEPRECATED]\", params: \"Query: sessionId\" },\r\n        { category: \"Labels\", method: \"POST\", path: \"/api/labels\", description: \"Create label [DEPRECATED]\", params: \"Body: { sessionId, name, color }\" },\r\n        { category: \"Labels\", method: \"GET\", path: \"/api/labels/chat-labels\", description: \"Get chat labels [DEPRECATED]\", params: \"Query: sessionId, jid\" },\r\n        { category: \"Labels\", method: \"PUT\", path: \"/api/labels/chat-labels\", description: \"Update chat labels [DEPRECATED]\", params: \"Body: { sessionId, jid, labelIds[], action }\" },\r\n\r\n        // Auto Reply\r\n        { category: \"Auto Reply\", method: \"GET\", path: \"/api/autoreplies/[sessionId]\", description: \"List auto replies\", params: \"Path: sessionId\" },\r\n        { category: \"Auto Reply\", method: \"POST\", path: \"/api/autoreplies/[sessionId]\", description: \"Create auto reply\", params: \"Path: sessionId, Body: { keyword, response, matchType }\" },\r\n        { category: \"Auto Reply\", method: \"GET\", path: \"/api/autoreplies/[sessionId]/[id]\", description: \"Get auto reply\", params: \"Path: sessionId, id\" },\r\n        { category: \"Auto Reply\", method: \"PUT\", path: \"/api/autoreplies/[sessionId]/[id]\", description: \"Update auto reply\", params: \"Path: sessionId, id, Body: { ... }\" },\r\n        { category: \"Auto Reply\", method: \"DELETE\", path: \"/api/autoreplies/[sessionId]/[id]\", description: \"Delete auto reply\", params: \"Path: sessionId, id\" },\r\n\r\n        // Auto Reply (Legacy)\r\n        { category: \"Auto Reply\", method: \"GET\", path: \"/api/autoreplies\", description: \"List auto replies [DEPRECATED]\", params: \"Query: sessionId\" },\r\n        { category: \"Auto Reply\", method: \"POST\", path: \"/api/autoreplies\", description: \"Create auto reply [DEPRECATED]\", params: \"Body: { sessionId, keyword, ... }\" },\r\n\r\n        // Scheduler\r\n        { category: \"Scheduler\", method: \"GET\", path: \"/api/scheduler/[sessionId]\", description: \"List scheduled\", params: \"Path: sessionId\" },\r\n        { category: \"Scheduler\", method: \"POST\", path: \"/api/scheduler/[sessionId]\", description: \"Create scheduled\", params: \"Path: sessionId, Body: { jid, content, sendAt }\" },\r\n        { category: \"Scheduler\", method: \"GET\", path: \"/api/scheduler/[sessionId]/[id]\", description: \"Get scheduled\", params: \"Path: sessionId, id\" },\r\n        { category: \"Scheduler\", method: \"PUT\", path: \"/api/scheduler/[sessionId]/[id]\", description: \"Update scheduled\", params: \"Path: sessionId, id, Body: { ... }\" },\r\n        { category: \"Scheduler\", method: \"DELETE\", path: \"/api/scheduler/[sessionId]/[id]\", description: \"Delete scheduled\", params: \"Path: sessionId, id\" },\r\n\r\n        // Scheduler (Legacy)\r\n        { category: \"Scheduler\", method: \"GET\", path: \"/api/scheduler\", description: \"List scheduled [DEPRECATED]\", params: \"Query: sessionId\" },\r\n        { category: \"Scheduler\", method: \"POST\", path: \"/api/scheduler\", description: \"Create scheduled [DEPRECATED]\", params: \"Body: { sessionId, content, ... }\" },\r\n\r\n        // Webhooks\r\n        { category: \"Webhooks\", method: \"GET\", path: \"/api/webhooks/[sessionId]\", description: \"List webhooks\", params: \"Path: sessionId\" },\r\n        { category: \"Webhooks\", method: \"POST\", path: \"/api/webhooks/[sessionId]\", description: \"Create webhook\", params: \"Path: sessionId, Body: { name, url, events[] }\" },\r\n        { category: \"Webhooks\", method: \"PUT\", path: \"/api/webhooks/[sessionId]/[id]\", description: \"Update webhook\", params: \"Path: sessionId, id, Body: { ... }\" },\r\n        { category: \"Webhooks\", method: \"DELETE\", path: \"/api/webhooks/[sessionId]/[id]\", description: \"Delete webhook\", params: \"Path: sessionId, id\" },\r\n\r\n        // Webhooks (Legacy)\r\n        { category: \"Webhooks\", method: \"GET\", path: \"/api/webhooks\", description: \"List webhooks [DEPRECATED]\", params: \"Query: sessionId\" },\r\n        { category: \"Webhooks\", method: \"POST\", path: \"/api/webhooks\", description: \"Create webhook [DEPRECATED]\", params: \"Body: { sessionId, url, ... }\" },\r\n\r\n        // Notifications\r\n        { category: \"Notifications\", method: \"GET\", path: \"/api/notifications\", description: \"List notifications\", params: \"-\" },\r\n        { category: \"Notifications\", method: \"POST\", path: \"/api/notifications\", description: \"Create notification\", params: \"Body: { title, message, ... }\" },\r\n        { category: \"Notifications\", method: \"PATCH\", path: \"/api/notifications/read\", description: \"Mark as read\", params: \"Body: { ids[] }\" },\r\n        { category: \"Notifications\", method: \"DELETE\", path: \"/api/notifications/delete\", description: \"Delete notifications\", params: \"Query: id\" },\r\n\r\n        // Users\r\n        { category: \"Users\", method: \"GET\", path: \"/api/users\", description: \"List users\", params: \"-\" },\r\n        { category: \"Users\", method: \"POST\", path: \"/api/users\", description: \"Create user\", params: \"Body: { name, email, password }\" },\r\n        { category: \"Users\", method: \"GET\", path: \"/api/users/[id]\", description: \"Get user\", params: \"Path: id\" },\r\n        { category: \"Users\", method: \"PATCH\", path: \"/api/users/[id]\", description: \"Update user\", params: \"Path: id, Body: { ... }\" },\r\n        { category: \"Users\", method: \"DELETE\", path: \"/api/users/[id]\", description: \"Delete user\", params: \"Path: id\" },\r\n        { category: \"Users\", method: \"GET\", path: \"/api/user/api-key\", description: \"Get API key\", params: \"-\" },\r\n        { category: \"Users\", method: \"POST\", path: \"/api/user/api-key\", description: \"Generate API key\", params: \"-\" },\r\n        { category: \"Users\", method: \"DELETE\", path: \"/api/user/api-key\", description: \"Revoke API key\", params: \"-\" },\r\n\r\n        // System\r\n        { category: \"System\", method: \"GET\", path: \"/api/settings/system\", description: \"Get system settings\", params: \"-\" },\r\n        { category: \"System\", method: \"POST\", path: \"/api/settings/system\", description: \"Update system settings\", params: \"Body: { appName, logoUrl, timezone }\" },\r\n        { category: \"System\", method: \"POST\", path: \"/api/status/[sessionId]/update\", description: \"Update status\", params: \"Path: sessionId, Body: { status }\" },\r\n        { category: \"System\", method: \"GET\", path: \"/api/system/check-updates\", description: \"Check updates\", params: \"-\" },\r\n    ];\r\n\r\n\r\n    const categories = [\"All\", ...Array.from(new Set(apiEndpoints.map(e => e.category)))];\r\n\r\n    const filteredEndpoints = apiEndpoints.filter(endpoint => {\r\n        const matchesFilter = endpoint.path.toLowerCase().includes(filter.toLowerCase()) ||\r\n            endpoint.description.toLowerCase().includes(filter.toLowerCase());\r\n        const matchesCategory = selectedCategory === \"All\" || endpoint.category === selectedCategory;\r\n        return matchesFilter && matchesCategory;\r\n    });\r\n\r\n    const getMethodColor = (method: string) => {\r\n        switch (method) {\r\n            case \"GET\": return \"bg-green-100 text-green-800 border-green-300\";\r\n            case \"POST\": return \"bg-blue-100 text-blue-800 border-blue-300\";\r\n            case \"PUT\": return \"bg-yellow-100 text-yellow-800 border-yellow-300\";\r\n            case \"PATCH\": return \"bg-orange-100 text-orange-800 border-orange-300\";\r\n            case \"DELETE\": return \"bg-red-100 text-red-800 border-red-300\";\r\n            default: return \"bg-gray-100 text-gray-800 border-gray-300\";\r\n        }\r\n    };\r\n\r\n    if (status === \"loading\") {\r\n        return (\r\n            <div className=\"flex items-center justify-center min-h-screen\">\r\n                <div className=\"text-gray-600\">Loading...</div>\r\n            </div>\r\n        );\r\n    }\r\n\r\n    return (\r\n        <div className=\"min-h-screen bg-gray-50 p-6\">\r\n            <div className=\"max-w-7xl mx-auto\">\r\n                {/* Header */}\r\n                <div className=\"flex flex-col md:flex-row justify-between items-start md:items-center gap-4 mb-8\">\r\n                    <div>\r\n                        <h1 className=\"text-3xl font-bold text-gray-900 tracking-tight flex items-center gap-2\">\r\n                            <FileText className=\"w-8 h-8 text-blue-600\" />\r\n                            API Documentation\r\n                        </h1>\r\n                        <p className=\"text-gray-500 mt-2\">\r\n                            Complete reference for all {apiEndpoints.length} API endpoints.\r\n                        </p>\r\n                    </div>\r\n                    <a\r\n                        href=\"/docs\"\r\n                        target=\"_blank\"\r\n                        className=\"flex items-center gap-2 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition\"\r\n                    >\r\n                        <Code className=\"w-4 h-4\" />\r\n                        Open Swagger UI\r\n                        <ExternalLink className=\"w-4 h-4\" />\r\n                    </a>\r\n                </div>\r\n\r\n                {/* Master Documentation Alert */}\r\n                <div className=\"bg-blue-50 border-l-4 border-blue-500 p-4 rounded-r shadow-sm mb-6\">\r\n                    <div className=\"flex items-start\">\r\n                        <div className=\"flex-shrink-0\">\r\n                            <FileText className=\"h-5 w-5 text-blue-600\" />\r\n                        </div>\r\n                        <div className=\"ml-3\">\r\n                            <h3 className=\"text-sm font-medium text-blue-800\">≡ƒôÿ Project Documentation Available</h3>\r\n                            <div className=\"mt-2 text-sm text-blue-700\">\r\n                                <p>\r\n                                    For a deep dive into the <strong>Project Architecture</strong>, <strong>Database Schema</strong>, and <strong>Frontend Routing</strong>,\r\n                                    please refer to the <a href=\"/docs/PROJECT_DOCUMENTATION.md\" className=\"font-bold underline hover:text-blue-900\">Master Project Documentation</a> file in your codebase.\r\n                                </p>\r\n                            </div>\r\n                        </div>\r\n                    </div>\r\n                </div>\r\n\r\n                {/* Quick Links */}\r\n                <div className=\"bg-white rounded-lg shadow p-6 mb-6\">\r\n                    <h2 className=\"text-lg font-semibold mb-4\">Quick Links</h2>\r\n                    <div className=\"grid grid-cols-1 md:grid-cols-3 gap-4\">\r\n                        <a\r\n                            href=\"/docs\"\r\n                            target=\"_blank\"\r\n                            className=\"flex items-center p-4 border rounded-lg hover:bg-gray-50 transition-colors group\"\r\n                        >\r\n                            <Code className=\"w-10 h-10 text-blue-600 mr-4\" />\r\n                            <div className=\"flex-1\">\r\n                                <h3 className=\"font-medium text-gray-800 group-hover:text-blue-600\">Swagger UI</h3>\r\n                                <p className=\"text-sm text-gray-600\">Interactive API testing</p>\r\n                            </div>\r\n                            <ExternalLink className=\"w-5 h-5 text-gray-400\" />\r\n                        </a>\r\n                        <a\r\n                            href=\"/api/docs\"\r\n                            target=\"_blank\"\r\n                            className=\"flex items-center p-4 border rounded-lg hover:bg-gray-50 transition-colors group\"\r\n                        >\r\n                            <FileText className=\"w-10 h-10 text-green-600 mr-4\" />\r\n                            <div className=\"flex-1\">\r\n                                <h3 className=\"font-medium text-gray-800 group-hover:text-green-600\">OpenAPI Spec</h3>\r\n                                <p className=\"text-sm text-gray-600\">JSON specification</p>\r\n                            </div>\r\n                            <ExternalLink className=\"w-5 h-5 text-gray-400\" />\r\n                        </a>\r\n                        <div className=\"flex items-center p-4 border rounded-lg bg-gray-50\">\r\n                            <div className=\"flex-1\">\r\n                                <h3 className=\"font-medium text-gray-800\">Base URL</h3>\r\n                                <p className=\"text-sm text-gray-600 font-mono break-all\">{process.env.NEXT_PUBLIC_API_URL || '/api'}</p>\r\n                            </div>\r\n                        </div>\r\n                    </div>\r\n                </div>\r\n\r\n                {/* Filters */}\r\n                <div className=\"bg-white rounded-lg shadow p-6 mb-6\">\r\n                    <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\r\n                        <div>\r\n                            <label className=\"block text-sm font-medium text-gray-700 mb-2\">Search</label>\r\n                            <input\r\n                                type=\"text\"\r\n                                value={filter}\r\n                                onChange={(e) => setFilter(e.target.value)}\r\n                                placeholder=\"Search endpoints...\"\r\n                                className=\"w-full px-4 py-2 border rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent\"\r\n                            />\r\n                        </div>\r\n                        <div>\r\n                            <label className=\"block text-sm font-medium text-gray-700 mb-2\">Category</label>\r\n                            <select\r\n                                value={selectedCategory}\r\n                                onChange={(e) => setSelectedCategory(e.target.value)}\r\n                                className=\"w-full px-4 py-2 border rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent\"\r\n                            >\r\n                                {categories.map(cat => (\r\n                                    <option key={cat} value={cat}>{cat}</option>\r\n                                ))}\r\n                            </select>\r\n                        </div>\r\n                    </div>\r\n                </div>\r\n\r\n                {/* Endpoints List */}\r\n                <div className=\"bg-white rounded-lg shadow overflow-hidden\">\r\n                    <div className=\"overflow-x-auto\">\r\n                        <table className=\"min-w-full divide-y divide-gray-200\">\r\n                            <thead className=\"bg-gray-50\">\r\n                                <tr>\r\n                                    <th className=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\">Method</th>\r\n                                    <th className=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\">Endpoint</th>\r\n                                    <th className=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\">Params</th>\r\n                                    <th className=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\">Description</th>\r\n                                    <th className=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\">Category</th>\r\n                                </tr>\r\n                            </thead>\r\n                            <tbody className=\"bg-white divide-y divide-gray-200\">\r\n                                {filteredEndpoints.map((endpoint, index) => (\r\n                                    <tr key={index} className=\"hover:bg-gray-50\">\r\n                                        <td className=\"px-6 py-4 whitespace-nowrap\">\r\n                                            <span className={`px-3 py-1 text-xs font-semibold rounded-full border ${getMethodColor(endpoint.method)}`}>\r\n                                                {endpoint.method}\r\n                                            </span>\r\n                                        </td>\r\n                                        <td className=\"px-6 py-4 whitespace-nowrap\">\r\n                                            <code className=\"text-sm text-gray-900 font-mono\">{endpoint.path}</code>\r\n                                        </td>\r\n                                        <td className=\"px-6 py-4 text-xs font-mono text-gray-600 max-w-xs break-words\">\r\n                                            {endpoint.params || \"-\"}\r\n                                        </td>\r\n                                        <td className=\"px-6 py-4 text-sm text-gray-600\">{endpoint.description}</td>\r\n                                        <td className=\"px-6 py-4 whitespace-nowrap\">\r\n                                            <span className=\"px-2 py-1 text-xs bg-gray-100 text-gray-700 rounded\">\r\n                                                {endpoint.category}\r\n                                            </span>\r\n                                        </td>\r\n                                    </tr>\r\n                                ))}\r\n                            </tbody>\r\n                        </table>\r\n                    </div>\r\n\r\n                    {filteredEndpoints.length === 0 && (\r\n                        <div className=\"text-center py-12 text-gray-500\">\r\n                            No endpoints found matching your criteria\r\n                        </div>\r\n                    )}\r\n                </div>\r\n\r\n                {/* Stats */}\r\n                <div className=\"mt-6 grid grid-cols-2 md:grid-cols-4 gap-4\">\r\n                    <div className=\"bg-white rounded-lg shadow p-4\">\r\n                        <div className=\"text-2xl font-bold text-blue-600\">{apiEndpoints.length}</div>\r\n                        <div className=\"text-sm text-gray-600\">Total Endpoints</div>\r\n                    </div>\r\n                    <div className=\"bg-white rounded-lg shadow p-4\">\r\n                        <div className=\"text-2xl font-bold text-green-600\">{categories.length - 1}</div>\r\n                        <div className=\"text-sm text-gray-600\">Categories</div>\r\n                    </div>\r\n                    <div className=\"bg-white rounded-lg shadow p-4\">\r\n                        <div className=\"text-2xl font-bold text-yellow-600\">{apiEndpoints.filter(e => e.method === \"POST\").length}</div>\r\n                        <div className=\"text-sm text-gray-600\">POST Endpoints</div>\r\n                    </div>\r\n                    <div className=\"bg-white rounded-lg shadow p-4\">\r\n                        <div className=\"text-2xl font-bold text-purple-600\">{apiEndpoints.filter(e => e.method === \"GET\").length}</div>\r\n                        <div className=\"text-sm text-gray-600\">GET Endpoints</div>\r\n                    </div>\r\n                </div>\r\n            </div>\r\n        </div>\r\n    );\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\dashboard\\autoreply\\page.tsx","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'CardDescription' is defined but never used.","line":4,"column":52,"nodeType":"Identifier","messageId":"unusedVar","endLine":4,"endColumn":67,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"CardDescription"},"fix":{"range":[112,129],"text":""},"desc":"Remove unused variable \"CardDescription\"."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":92,"column":36,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":92,"endColumn":39,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3181,3184],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3181,3184],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'error' is defined but never used.","line":133,"column":18,"nodeType":"Identifier","messageId":"unusedVar","endLine":133,"endColumn":23},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'error' is defined but never used.","line":148,"column":18,"nodeType":"Identifier","messageId":"unusedVar","endLine":148,"endColumn":23}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\"use client\";\r\n\r\nimport { useState, useEffect } from \"react\";\r\nimport { Card, CardContent, CardHeader, CardTitle, CardDescription } from \"@/components/ui/card\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { Input } from \"@/components/ui/input\";\r\nimport { Textarea } from \"@/components/ui/textarea\";\r\nimport { Label } from \"@/components/ui/label\";\r\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"@/components/ui/select\";\r\nimport { Trash2, Plus, MessageSquare, RefreshCw } from \"lucide-react\";\r\nimport { toast } from \"sonner\";\r\nimport {\r\n    AlertDialog,\r\n    AlertDialogAction,\r\n    AlertDialogCancel,\r\n    AlertDialogContent,\r\n    AlertDialogDescription,\r\n    AlertDialogFooter,\r\n    AlertDialogHeader,\r\n    AlertDialogTitle,\r\n} from \"@/components/ui/alert-dialog\";\r\nimport { SearchFilter } from \"@/components/dashboard/search-filter\";\r\nimport { useSession } from \"@/components/dashboard/session-provider\";\r\nimport { SessionGuard } from \"@/components/dashboard/session-guard\";\r\n\r\ninterface AutoReply {\r\n    id: string;\r\n    keyword: string;\r\n    response: string;\r\n    matchType: string;\r\n    isMedia: boolean;\r\n    mediaUrl: string | null;\r\n}\r\n\r\nexport default function AutoReplyPage() {\r\n    const { sessionId: selectedSessionId } = useSession();\r\n\r\n    const [rules, setRules] = useState<AutoReply[]>([]);\r\n    const [loading, setLoading] = useState(false);\r\n    const [searchTerm, setSearchTerm] = useState(\"\");\r\n\r\n    // Form state ...\r\n    const [showForm, setShowForm] = useState(false);\r\n    const [newKeyword, setNewKeyword] = useState(\"\");\r\n    const [newResponse, setNewResponse] = useState(\"\");\r\n    const [newMatchType, setNewMatchType] = useState(\"EXACT\");\r\n    const [newIsMedia, setNewIsMedia] = useState(false);\r\n    const [newMediaUrl, setNewMediaUrl] = useState(\"\");\r\n    const [newTriggerType, setNewTriggerType] = useState(\"ALL\");\r\n\r\n    // Delete state\r\n    const [deleteId, setDeleteId] = useState<string | null>(null);\r\n\r\n    // Remove local listener\r\n\r\n    // Edit state\r\n    const [editingId, setEditingId] = useState<string | null>(null);\r\n\r\n    useEffect(() => {\r\n        if (selectedSessionId) {\r\n            fetchRules(selectedSessionId);\r\n        } else {\r\n            setRules([]);\r\n        }\r\n    }, [selectedSessionId]);\r\n\r\n    const fetchRules = async (sessionId: string) => {\r\n        setLoading(true);\r\n        try {\r\n            const res = await fetch(`/api/autoreplies/${sessionId}`);\r\n            if (res.ok) {\r\n                const data = await res.json();\r\n                setRules(data);\r\n            } else {\r\n                setRules([]); // or error\r\n            }\r\n        } catch (error) {\r\n            console.error(error);\r\n            toast.error(\"Failed to fetch auto replies\");\r\n        } finally {\r\n            setLoading(false);\r\n        }\r\n    };\r\n\r\n    const handleEdit = (rule: AutoReply) => {\r\n        setEditingId(rule.id);\r\n        setNewKeyword(rule.keyword);\r\n        setNewResponse(rule.response);\r\n        setNewMatchType(rule.matchType);\r\n        setNewIsMedia(rule.isMedia || false);\r\n        setNewMediaUrl(rule.mediaUrl || \"\");\r\n        setNewTriggerType((rule as any).triggerType || \"ALL\");\r\n        setShowForm(true);\r\n    };\r\n\r\n    const handleSaveRule = async () => {\r\n        if (!selectedSessionId || !newKeyword || !newResponse) return;\r\n\r\n        try {\r\n            const url = editingId\r\n                ? `/api/autoreplies/${selectedSessionId}/${editingId}`\r\n                : `/api/autoreplies/${selectedSessionId}`;\r\n\r\n            const method = editingId ? \"PUT\" : \"POST\";\r\n\r\n            const res = await fetch(url, {\r\n                method,\r\n                headers: { \"Content-Type\": \"application/json\" },\r\n                body: JSON.stringify({\r\n                    keyword: newKeyword,\r\n                    response: newResponse,\r\n                    matchType: newMatchType,\r\n                    isMedia: newIsMedia,\r\n                    mediaUrl: newMediaUrl,\r\n                    triggerType: newTriggerType // Added triggerType\r\n                })\r\n            });\r\n\r\n            if (res.ok) {\r\n                toast.success(editingId ? \"Rule updated\" : \"Rule created\");\r\n                setShowForm(false);\r\n                setNewKeyword(\"\");\r\n                setNewResponse(\"\");\r\n                setNewMatchType(\"EXACT\");\r\n                setNewIsMedia(false);\r\n                setNewMediaUrl(\"\");\r\n                setNewTriggerType(\"ALL\"); // Reset newTriggerType\r\n                setEditingId(null);\r\n                fetchRules(selectedSessionId);\r\n            } else {\r\n                toast.error(editingId ? \"Failed to update rule\" : \"Failed to create rule\");\r\n            }\r\n        } catch (error) {\r\n            toast.error(\"An error occurred\");\r\n        }\r\n    };\r\n\r\n    const confirmDelete = async () => {\r\n        if (!deleteId) return;\r\n        try {\r\n            const res = await fetch(`/api/autoreplies/${selectedSessionId}/${deleteId}`, { method: \"DELETE\" });\r\n            if (res.ok) {\r\n                toast.success(\"Rule deleted\");\r\n                setRules(rules.filter(r => r.id !== deleteId));\r\n            } else {\r\n                toast.error(\"Failed to delete rule\");\r\n            }\r\n        } catch (error) {\r\n            toast.error(\"Failed to delete rule\");\r\n        } finally {\r\n            setDeleteId(null);\r\n        }\r\n    };\r\n\r\n    const filteredRules = rules.filter(r =>\r\n        r.keyword.toLowerCase().includes(searchTerm.toLowerCase()) ||\r\n        r.response.toLowerCase().includes(searchTerm.toLowerCase())\r\n    );\r\n\r\n    return (\r\n        <SessionGuard>\r\n            <div className=\"space-y-6\">\r\n                <div className=\"flex justify-between items-center\">\r\n                    <div>\r\n                        <h1 className=\"text-2xl font-bold flex items-center gap-2\">\r\n                            <MessageSquare className=\"h-6 w-6\" /> Auto Reply\r\n                        </h1>\r\n                        <p className=\"text-muted-foreground\">Automatically reply to incoming messages based on keywords.</p>\r\n                    </div>\r\n\r\n                    <div className=\"flex items-center gap-2\">\r\n                        <Button variant=\"outline\" onClick={() => selectedSessionId && fetchRules(selectedSessionId)} disabled={loading || !selectedSessionId}>\r\n                            <RefreshCw className={`h-4 w-4 mr-2 ${loading ? 'animate-spin' : ''}`} />\r\n                            Refresh\r\n                        </Button>\r\n                        <Button onClick={() => {\r\n                            setEditingId(null);\r\n                            setNewKeyword(\"\");\r\n                            setNewResponse(\"\");\r\n                            setNewMatchType(\"EXACT\");\r\n                            setNewIsMedia(false);\r\n                            setNewMediaUrl(\"\");\r\n                            setNewTriggerType(\"ALL\"); // Reset newTriggerType\r\n                            setShowForm(!showForm);\r\n                        }} disabled={!selectedSessionId}>\r\n                            <Plus className=\"h-4 w-4 mr-2\" /> Add Rule\r\n                        </Button>\r\n                    </div>\r\n                </div>\r\n\r\n                <SearchFilter\r\n                    placeholder=\"Search rules...\"\r\n                    onSearch={setSearchTerm}\r\n                />\r\n\r\n                {/* New/Edit Rule Form */}\r\n                {showForm && (\r\n                    <Card className=\"border-2 border-primary/20\">\r\n                        <CardHeader>\r\n                            <CardTitle>{editingId ? \"Edit Auto Reply Rule\" : \"New Auto Reply Rule\"}</CardTitle>\r\n                        </CardHeader>\r\n                        <CardContent className=\"space-y-4\">\r\n                            <div className=\"space-y-2\">\r\n                                <Label>Keyword</Label>\r\n                                <Input\r\n                                    value={newKeyword}\r\n                                    onChange={e => setNewKeyword(e.target.value)}\r\n                                    placeholder=\"e.g. !hello\"\r\n                                />\r\n                            </div>\r\n                            <div className=\"grid grid-cols-2 gap-4\">\r\n                                <div className=\"space-y-2\">\r\n                                    <Label>Match Type</Label>\r\n                                    <Select value={newMatchType} onValueChange={setNewMatchType}>\r\n                                        <SelectTrigger>\r\n                                            <SelectValue />\r\n                                        </SelectTrigger>\r\n                                        <SelectContent>\r\n                                            <SelectItem value=\"EXACT\">Exact Match</SelectItem>\r\n                                            <SelectItem value=\"CONTAINS\">Contains</SelectItem>\r\n                                            <SelectItem value=\"STARTS_WITH\">Starts With</SelectItem>\r\n                                            <SelectItem value=\"REGEX\">Regex</SelectItem>\r\n                                        </SelectContent>\r\n                                    </Select>\r\n                                </div>\r\n                                <div className=\"space-y-2\">\r\n                                    <Label>Respond IN</Label>\r\n                                    <Select value={newTriggerType} onValueChange={setNewTriggerType}>\r\n                                        <SelectTrigger>\r\n                                            <SelectValue />\r\n                                        </SelectTrigger>\r\n                                        <SelectContent>\r\n                                            <SelectItem value=\"ALL\">All Chats</SelectItem>\r\n                                            <SelectItem value=\"PRIVATE\">Private Only</SelectItem>\r\n                                            <SelectItem value=\"GROUP\">Group Only</SelectItem>\r\n                                        </SelectContent>\r\n                                    </Select>\r\n                                </div>\r\n                            </div>\r\n\r\n                            <div className=\"space-y-4 border p-3 rounded-md\">\r\n                                <div className=\"flex items-center gap-2\">\r\n                                    <input\r\n                                        type=\"checkbox\"\r\n                                        id=\"isMedia\"\r\n                                        className=\"h-4 w-4 rounded border-gray-300\"\r\n                                        checked={newIsMedia}\r\n                                        onChange={(e) => setNewIsMedia(e.target.checked)}\r\n                                    />\r\n                                    <Label htmlFor=\"isMedia\">Send Media</Label>\r\n                                </div>\r\n\r\n                                {newIsMedia && (\r\n                                    <div className=\"space-y-2\">\r\n                                        <Label>Media URL</Label>\r\n                                        <Input\r\n                                            placeholder=\"https://example.com/image.jpg\"\r\n                                            value={newMediaUrl}\r\n                                            onChange={(e) => setNewMediaUrl(e.target.value)}\r\n                                        />\r\n                                        <p className=\"text-xs text-muted-foreground\">Direct link to image, video, or document.</p>\r\n                                    </div>\r\n                                )}\r\n                            </div>\r\n                            <div className=\"space-y-2\">\r\n                                <Label>Response Message</Label>\r\n                                <Textarea\r\n                                    value={newResponse}\r\n                                    onChange={e => setNewResponse(e.target.value)}\r\n                                    placeholder=\"Hello! How can I help you?\"\r\n                                    rows={4}\r\n                                />\r\n                            </div>\r\n                            <div className=\"flex justify-end gap-2\">\r\n                                <Button variant=\"ghost\" onClick={() => {\r\n                                    setShowForm(false);\r\n                                    setEditingId(null);\r\n                                    setNewKeyword(\"\");\r\n                                    setNewResponse(\"\");\r\n                                    setNewIsMedia(false);\r\n                                    setNewMediaUrl(\"\");\r\n                                }}>Cancel</Button>\r\n                                <Button onClick={handleSaveRule}>{editingId ? \"Update\" : \"Save\"}</Button>\r\n                            </div>\r\n                        </CardContent>\r\n                    </Card>\r\n                )}\r\n\r\n                {/* Rules List */}\r\n                {loading ? (\r\n                    <div className=\"text-center p-8\">Loading rules...</div>\r\n                ) : filteredRules.length === 0 ? (\r\n                    <div className=\"text-center p-8 text-muted-foreground border rounded-lg bg-slate-50\">\r\n                        {selectedSessionId ? \"No auto reply rules found matching criteria.\" : \"No session selected.\"}\r\n                    </div>\r\n                ) : (\r\n                    <div className=\"grid gap-4\">\r\n                        {filteredRules.map(rule => (\r\n                            <Card key={rule.id}>\r\n                                <CardContent className=\"flex justify-between items-center p-4\">\r\n                                    <div>\r\n                                        <div className=\"font-bold flex items-center gap-2\">\r\n                                            {rule.keyword}\r\n                                            <span className=\"text-xs bg-slate-100 px-2 py-0.5 rounded text-slate-500 font-normal\">{rule.matchType}</span>\r\n                                        </div>\r\n                                        <div className=\"text-sm text-muted-foreground mt-1\">{rule.response}</div>\r\n                                    </div>\r\n                                    <div className=\"flex gap-2\">\r\n                                        <Button variant=\"ghost\" size=\"sm\" onClick={() => handleEdit(rule)}>\r\n                                            Edit\r\n                                        </Button>\r\n                                        <Button variant=\"ghost\" size=\"icon\" onClick={() => setDeleteId(rule.id)} className=\"text-destructive hover:text-destructive hover:bg-red-50\">\r\n                                            <Trash2 className=\"h-4 w-4\" />\r\n                                        </Button>\r\n                                    </div>\r\n                                </CardContent>\r\n                            </Card>\r\n                        ))}\r\n                    </div>\r\n                )}\r\n\r\n                <AlertDialog open={!!deleteId} onOpenChange={(open) => !open && setDeleteId(null)}>\r\n                    <AlertDialogContent>\r\n                        <AlertDialogHeader>\r\n                            <AlertDialogTitle>Delete Rule?</AlertDialogTitle>\r\n                            <AlertDialogDescription>\r\n                                This will verify delete this auto reply rule.\r\n                            </AlertDialogDescription>\r\n                        </AlertDialogHeader>\r\n                        <AlertDialogFooter>\r\n                            <AlertDialogCancel>Cancel</AlertDialogCancel>\r\n                            <AlertDialogAction onClick={confirmDelete} className=\"bg-red-600 hover:bg-red-700\">Delete</AlertDialogAction>\r\n                        </AlertDialogFooter>\r\n                    </AlertDialogContent>\r\n                </AlertDialog>\r\n            </div>\r\n        </SessionGuard>\r\n    );\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\dashboard\\bot-settings\\page.tsx","messages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'fetchConfig'. Either include it or remove the dependency array.","line":65,"column":8,"nodeType":"ArrayExpression","endLine":65,"endColumn":26,"suggestions":[{"desc":"Update the dependencies array to be: [currentSessionId, fetchConfig]","fix":{"range":[2462,2480],"text":"[currentSessionId, fetchConfig]"}}]},{"ruleId":"react/no-unescaped-entities","severity":2,"message":"`\"` can be escaped with `&quot;`, `&ldquo;`, `&#34;`, `&rdquo;`.","line":150,"column":74,"nodeType":"JSXText","messageId":"unescapedEntityAlts","suggestions":[{"messageId":"replaceWithAlt","data":{"alt":"&quot;"},"fix":{"range":[6539,6661],"text":"\r\n                                Configure your WhatsApp Bot features and &quot;Magic Commands\".\r\n                            "},"desc":"Replace with `&quot;`."},{"messageId":"replaceWithAlt","data":{"alt":"&ldquo;"},"fix":{"range":[6539,6661],"text":"\r\n                                Configure your WhatsApp Bot features and &ldquo;Magic Commands\".\r\n                            "},"desc":"Replace with `&ldquo;`."},{"messageId":"replaceWithAlt","data":{"alt":"&#34;"},"fix":{"range":[6539,6661],"text":"\r\n                                Configure your WhatsApp Bot features and &#34;Magic Commands\".\r\n                            "},"desc":"Replace with `&#34;`."},{"messageId":"replaceWithAlt","data":{"alt":"&rdquo;"},"fix":{"range":[6539,6661],"text":"\r\n                                Configure your WhatsApp Bot features and &rdquo;Magic Commands\".\r\n                            "},"desc":"Replace with `&rdquo;`."}]},{"ruleId":"react/no-unescaped-entities","severity":2,"message":"`\"` can be escaped with `&quot;`, `&ldquo;`, `&#34;`, `&rdquo;`.","line":150,"column":89,"nodeType":"JSXText","messageId":"unescapedEntityAlts","suggestions":[{"messageId":"replaceWithAlt","data":{"alt":"&quot;"},"fix":{"range":[6539,6661],"text":"\r\n                                Configure your WhatsApp Bot features and \"Magic Commands&quot;.\r\n                            "},"desc":"Replace with `&quot;`."},{"messageId":"replaceWithAlt","data":{"alt":"&ldquo;"},"fix":{"range":[6539,6661],"text":"\r\n                                Configure your WhatsApp Bot features and \"Magic Commands&ldquo;.\r\n                            "},"desc":"Replace with `&ldquo;`."},{"messageId":"replaceWithAlt","data":{"alt":"&#34;"},"fix":{"range":[6539,6661],"text":"\r\n                                Configure your WhatsApp Bot features and \"Magic Commands&#34;.\r\n                            "},"desc":"Replace with `&#34;`."},{"messageId":"replaceWithAlt","data":{"alt":"&rdquo;"},"fix":{"range":[6539,6661],"text":"\r\n                                Configure your WhatsApp Bot features and \"Magic Commands&rdquo;.\r\n                            "},"desc":"Replace with `&rdquo;`."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":220,"column":66,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":220,"endColumn":69,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[10751,10754],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[10751,10754],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":274,"column":66,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":274,"endColumn":69,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[14724,14727],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[14724,14727],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":4,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\"use client\";\r\n\r\nimport { useEffect, useState } from \"react\";\r\nimport { useSession } from \"@/components/dashboard/session-provider\";\r\nimport { SessionGuard } from \"@/components/dashboard/session-guard\";\r\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from \"@/components/ui/card\";\r\nimport { Switch } from \"@/components/ui/switch\";\r\nimport { Label } from \"@/components/ui/label\";\r\nimport { Input } from \"@/components/ui/input\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"@/components/ui/select\";\r\nimport { Textarea } from \"@/components/ui/textarea\";\r\nimport { toast } from \"sonner\";\r\nimport { Loader2, Bot, Wand2, Shield, Activity, Image as ImageIcon, MessageSquare } from \"lucide-react\";\r\n\r\ninterface BotConfig {\r\n    id?: string;\r\n    enabled: boolean;\r\n    botName: string;\r\n    botMode: 'ALL' | 'OWNER' | 'SPECIFIC' | 'BLACKLIST';\r\n    botAllowedJids: string[];\r\n    botBlockedJids: string[];\r\n    autoReplyMode: 'ALL' | 'OWNER' | 'SPECIFIC' | 'BLACKLIST';\r\n    autoReplyAllowedJids: string[];\r\n    autoReplyBlockedJids: string[];\r\n    enableSticker: boolean;\r\n    enableVideoSticker: boolean;\r\n    maxStickerDuration: number;\r\n    enablePing: boolean;\r\n    enableUptime: boolean;\r\n    removeBgApiKey: string | null;\r\n}\r\n\r\nexport default function BotSettingsPage() {\r\n    const { sessionId: currentSessionId } = useSession();\r\n    const [config, setConfig] = useState<BotConfig>({\r\n        enabled: true,\r\n        botName: \"WA-AKG Bot\",\r\n        botMode: 'OWNER',\r\n        botAllowedJids: [],\r\n        botBlockedJids: [],\r\n        autoReplyMode: 'ALL',\r\n        autoReplyAllowedJids: [],\r\n        autoReplyBlockedJids: [],\r\n        enableSticker: true,\r\n        enableVideoSticker: true,\r\n        maxStickerDuration: 10,\r\n        enablePing: true,\r\n        enableUptime: true,\r\n        removeBgApiKey: \"\"\r\n    });\r\n    const [isLoading, setIsLoading] = useState(false);\r\n    const [isSaving, setIsSaving] = useState(false);\r\n\r\n    // Helpers to manage JID text area\r\n    const [botJidsText, setBotJidsText] = useState(\"\");\r\n    const [botBlockedJidsText, setBotBlockedJidsText] = useState(\"\");\r\n    const [autoReplyJidsText, setAutoReplyJidsText] = useState(\"\");\r\n    const [autoReplyBlockedJidsText, setAutoReplyBlockedJidsText] = useState(\"\");\r\n\r\n    useEffect(() => {\r\n        if (currentSessionId) {\r\n            fetchConfig();\r\n        }\r\n    }, [currentSessionId]);\r\n\r\n    const fetchConfig = async () => {\r\n        if (!currentSessionId) return;\r\n        setIsLoading(true);\r\n        try {\r\n            const res = await fetch(`/api/sessions/${currentSessionId}/bot-config`);\r\n            if (res.ok) {\r\n                const data = await res.json();\r\n                setConfig({\r\n                    ...data,\r\n                    botName: data.botName || \"WA-AKG Bot\",\r\n                    botMode: data.botMode || 'OWNER',\r\n                    autoReplyMode: data.autoReplyMode || 'ALL',\r\n                    botAllowedJids: Array.isArray(data.botAllowedJids) ? data.botAllowedJids : [],\r\n                    botBlockedJids: Array.isArray(data.botBlockedJids) ? data.botBlockedJids : [],\r\n                    autoReplyAllowedJids: Array.isArray(data.autoReplyAllowedJids) ? data.autoReplyAllowedJids : [],\r\n                    autoReplyBlockedJids: Array.isArray(data.autoReplyBlockedJids) ? data.autoReplyBlockedJids : [],\r\n                    enableVideoSticker: data.enableVideoSticker !== undefined ? data.enableVideoSticker : true,\r\n                    maxStickerDuration: data.maxStickerDuration || 10,\r\n                    removeBgApiKey: data.removeBgApiKey || \"\"\r\n                });\r\n                // Init text areas\r\n                setBotJidsText((data.botAllowedJids || []).join('\\n'));\r\n                setBotBlockedJidsText((data.botBlockedJids || []).join('\\n'));\r\n                setAutoReplyJidsText((data.autoReplyAllowedJids || []).join('\\n'));\r\n                setAutoReplyBlockedJidsText((data.autoReplyBlockedJids || []).join('\\n'));\r\n            }\r\n        } catch (error) {\r\n            console.error(\"Failed to fetch config\", error);\r\n            toast.error(\"Failed to load bot settings\");\r\n        } finally {\r\n            setIsLoading(false);\r\n        }\r\n    };\r\n\r\n    const handleSave = async () => {\r\n        if (!currentSessionId) return;\r\n        setIsSaving(true);\r\n\r\n        // Parse JIDs\r\n        const botJids = botJidsText.split('\\n').map(s => s.trim()).filter(Boolean);\r\n        const botBlockedJids = botBlockedJidsText.split('\\n').map(s => s.trim()).filter(Boolean);\r\n        const autoReplyJids = autoReplyJidsText.split('\\n').map(s => s.trim()).filter(Boolean);\r\n        const autoReplyBlockedJids = autoReplyBlockedJidsText.split('\\n').map(s => s.trim()).filter(Boolean);\r\n\r\n        const payload = {\r\n            ...config,\r\n            botAllowedJids: botJids,\r\n            botBlockedJids: botBlockedJids,\r\n            autoReplyAllowedJids: autoReplyJids,\r\n            autoReplyBlockedJids: autoReplyBlockedJids\r\n        };\r\n\r\n        try {\r\n            const res = await fetch(`/api/sessions/${currentSessionId}/bot-config`, {\r\n                method: \"POST\",\r\n                headers: { \"Content-Type\": \"application/json\" },\r\n                body: JSON.stringify(payload)\r\n            });\r\n\r\n            if (!res.ok) throw new Error(\"Failed to save\");\r\n\r\n            toast.success(\"Bot settings saved successfully\");\r\n        } catch (error) {\r\n            console.error(error);\r\n            toast.error(\"Failed to save settings\");\r\n        } finally {\r\n            setIsSaving(false);\r\n        }\r\n    };\r\n\r\n    return (\r\n        <SessionGuard>\r\n            {/* Note: SessionGuard handles the no session state, so we can assume currentSessionId exists in logic, but TS might complain so we keep safe checks if needed or rely on guard blocking it */}\r\n            {isLoading ? (\r\n                <div className=\"flex items-center justify-center min-h-[60vh]\">\r\n                    <Loader2 className=\"h-8 w-8 animate-spin text-primary\" />\r\n                </div>\r\n            ) : (\r\n                <div className=\"container max-w-4xl py-6 space-y-8\">\r\n                    <div className=\"flex flex-col md:flex-row justify-between items-start md:items-center gap-4\">\r\n                        <div>\r\n                            <h1 className=\"text-3xl font-bold tracking-tight\">Bot Magic Settings ≡ƒ¬ä</h1>\r\n                            <p className=\"text-muted-foreground\">\r\n                                Configure your WhatsApp Bot features and \"Magic Commands\".\r\n                            </p>\r\n                        </div>\r\n                        <Button onClick={handleSave} disabled={isSaving}>\r\n                            {isSaving && <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" />}\r\n                            Save Changes\r\n                        </Button>\r\n                    </div>\r\n\r\n                    <div className=\"grid gap-6\">\r\n                        {/* Main Switch */}\r\n                        <Card className={config.enabled ? \"border-primary/50 bg-primary/5\" : \"\"}>\r\n                            <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\r\n                                <div className=\"space-y-1\">\r\n                                    <CardTitle className=\"text-xl\">Enable Bot Features</CardTitle>\r\n                                    <CardDescription>\r\n                                        Turn on/off all magic commands for this session.\r\n                                    </CardDescription>\r\n                                </div>\r\n                                <Switch\r\n                                    checked={config.enabled}\r\n                                    onCheckedChange={(checked) => setConfig(prev => ({ ...prev, enabled: checked }))}\r\n                                />\r\n                            </CardHeader>\r\n                        </Card>\r\n\r\n                        {/* Bot Identity */}\r\n                        <Card>\r\n                            <CardHeader>\r\n                                <CardTitle className=\"text-lg flex items-center gap-2\">\r\n                                    <Bot className=\"h-5 w-5\" /> Bot Identity\r\n                                </CardTitle>\r\n                                <CardDescription>\r\n                                    Customize how your bot identifies itself.\r\n                                </CardDescription>\r\n                            </CardHeader>\r\n                            <CardContent className=\"space-y-4\">\r\n                                <div className=\"space-y-2\">\r\n                                    <Label>Bot Name</Label>\r\n                                    <Input\r\n                                        placeholder=\"e.g. WA-AKG Bot\"\r\n                                        value={config.botName || \"\"}\r\n                                        onChange={(e) => setConfig(prev => ({ ...prev, botName: e.target.value }))}\r\n                                    />\r\n                                    <p className=\"text-xs text-muted-foreground\">\r\n                                        Displayed in stickermaker watermarks and help menus.\r\n                                    </p>\r\n                                </div>\r\n                            </CardContent>\r\n                        </Card>\r\n\r\n                        {/* Access Control */}\r\n                        <Card>\r\n                            <CardHeader>\r\n                                <CardTitle className=\"text-lg flex items-center gap-2\">\r\n                                    <Shield className=\"h-5 w-5\" /> Access Control\r\n                                </CardTitle>\r\n                                <CardDescription>\r\n                                    Who can use the bot and trigger auto-replies?\r\n                                </CardDescription>\r\n                            </CardHeader>\r\n                            <CardContent className=\"space-y-8\">\r\n                                {/* Bot Commands */}\r\n                                <div className=\"space-y-4\">\r\n                                    <div className=\"flex flex-col space-y-2 md:flex-row md:space-y-0 md:items-center md:justify-between\">\r\n                                        <Label className=\"text-base flex items-center gap-2\">\r\n                                            <Bot className=\"h-4 w-4\" /> Bot Commands Access\r\n                                        </Label>\r\n                                        <Select\r\n                                            value={config.botMode}\r\n                                            onValueChange={(val: any) => setConfig(prev => ({ ...prev, botMode: val }))}\r\n                                        >\r\n                                            <SelectTrigger className=\"w-full md:w-[200px]\">\r\n                                                <SelectValue placeholder=\"Select Mode\" />\r\n                                            </SelectTrigger>\r\n                                            <SelectContent>\r\n                                                <SelectItem value=\"OWNER\">Owner Only (Me)</SelectItem>\r\n                                                <SelectItem value=\"ALL\">Public (Everyone)</SelectItem>\r\n                                                <SelectItem value=\"SPECIFIC\">Specific Contacts</SelectItem>\r\n                                                <SelectItem value=\"BLACKLIST\">Block Specific Contacts</SelectItem>\r\n                                            </SelectContent>\r\n                                        </Select>\r\n                                    </div>\r\n                                    <p className=\"text-sm text-muted-foreground\">\r\n                                        Controls who can use commands like <code>#sticker</code>, <code>#ping</code>.\r\n                                    </p>\r\n\r\n                                    {config.botMode === 'SPECIFIC' && (\r\n                                        <div className=\"ml-1 pl-4 border-l-2 border-slate-200 space-y-2\">\r\n                                            <Label>Allowed JIDs (one per line)</Label>\r\n                                            <Textarea\r\n                                                placeholder=\"628123456789@s.whatsapp.net\"\r\n                                                value={botJidsText}\r\n                                                onChange={(e) => setBotJidsText(e.target.value)}\r\n                                                className=\"font-mono text-sm max-h-[150px]\"\r\n                                            />\r\n                                            <p className=\"text-xs text-muted-foreground\">Enter specific WhatsApp IDs (JIDs) allowed to use the bot.</p>\r\n                                        </div>\r\n                                    )}\r\n\r\n                                    {config.botMode === 'BLACKLIST' && (\r\n                                        <div className=\"ml-1 pl-4 border-l-2 border-slate-200 space-y-2\">\r\n                                            <Label>Blocked JIDs (one per line)</Label>\r\n                                            <Textarea\r\n                                                placeholder=\"628123456789@s.whatsapp.net\"\r\n                                                value={botBlockedJidsText}\r\n                                                onChange={(e) => setBotBlockedJidsText(e.target.value)}\r\n                                                className=\"font-mono text-sm max-h-[150px]\"\r\n                                            />\r\n                                            <p className=\"text-xs text-muted-foreground\">Enter WhatsApp IDs (JIDs) blocked from using the bot.</p>\r\n                                        </div>\r\n                                    )}\r\n                                </div>\r\n\r\n                                <div className=\"border-t\" />\r\n\r\n                                {/* Auto Reply */}\r\n                                <div className=\"space-y-4\">\r\n                                    <div className=\"flex flex-col space-y-2 md:flex-row md:space-y-0 md:items-center md:justify-between\">\r\n                                        <Label className=\"text-base flex items-center gap-2\">\r\n                                            <MessageSquare className=\"h-4 w-4\" /> Auto Reply Access\r\n                                        </Label>\r\n                                        <Select\r\n                                            value={config.autoReplyMode}\r\n                                            onValueChange={(val: any) => setConfig(prev => ({ ...prev, autoReplyMode: val }))}\r\n                                        >\r\n                                            <SelectTrigger className=\"w-full md:w-[200px]\">\r\n                                                <SelectValue placeholder=\"Select Mode\" />\r\n                                            </SelectTrigger>\r\n                                            <SelectContent>\r\n                                                <SelectItem value=\"ALL\">Everyone (Public)</SelectItem>\r\n                                                <SelectItem value=\"OWNER\">Owner Only (Me)</SelectItem>\r\n                                                <SelectItem value=\"SPECIFIC\">Specific Contacts</SelectItem>\r\n                                                <SelectItem value=\"BLACKLIST\">Block Specific Contacts</SelectItem>\r\n                                            </SelectContent>\r\n                                        </Select>\r\n                                    </div>\r\n                                    <p className=\"text-sm text-muted-foreground\">\r\n                                        Controls whose messages trigger Auto Replies.\r\n                                    </p>\r\n\r\n                                    {config.autoReplyMode === 'SPECIFIC' && (\r\n                                        <div className=\"ml-1 pl-4 border-l-2 border-slate-200 space-y-2\">\r\n                                            <Label>Allowed JIDs (one per line)</Label>\r\n                                            <Textarea\r\n                                                placeholder=\"628123456789@s.whatsapp.net\"\r\n                                                value={autoReplyJidsText}\r\n                                                onChange={(e) => setAutoReplyJidsText(e.target.value)}\r\n                                                className=\"font-mono text-sm max-h-[150px]\"\r\n                                            />\r\n                                        </div>\r\n                                    )}\r\n\r\n                                    {config.autoReplyMode === 'BLACKLIST' && (\r\n                                        <div className=\"ml-1 pl-4 border-l-2 border-slate-200 space-y-2\">\r\n                                            <Label>Blocked JIDs (one per line)</Label>\r\n                                            <Textarea\r\n                                                placeholder=\"628123456789@s.whatsapp.net\"\r\n                                                value={autoReplyBlockedJidsText}\r\n                                                onChange={(e) => setAutoReplyBlockedJidsText(e.target.value)}\r\n                                                className=\"font-mono text-sm max-h-[150px]\"\r\n                                            />\r\n                                        </div>\r\n                                    )}\r\n                                </div>\r\n                            </CardContent>\r\n                        </Card>\r\n\r\n                        {/* Features */}\r\n                        <Card>\r\n                            <CardHeader>\r\n                                <CardTitle className=\"text-lg flex items-center gap-2\">\r\n                                    <Wand2 className=\"h-5 w-5\" /> Enabled Features\r\n                                </CardTitle>\r\n                            </CardHeader>\r\n                            <CardContent className=\"grid md:grid-cols-3 gap-6\">\r\n                                <div className=\"flex items-center justify-between md:block md:space-y-2\">\r\n                                    <Label className=\"flex items-center gap-2\">\r\n                                        <ImageIcon className=\"h-4 w-4\" /> Sticker (#sticker)\r\n                                    </Label>\r\n                                    <Switch\r\n                                        checked={config.enableSticker}\r\n                                        onCheckedChange={(checked) => setConfig(prev => ({ ...prev, enableSticker: checked }))}\r\n                                    />\r\n                                </div>\r\n\r\n                                <div className=\"space-y-3 p-3 border rounded-lg\">\r\n                                    <div className=\"flex items-center justify-between\">\r\n                                        <Label className=\"flex items-center gap-2 font-medium\">\r\n                                            <ImageIcon className=\"h-4 w-4\" /> Enable Video/GIF\r\n                                        </Label>\r\n                                        <Switch\r\n                                            checked={config.enableSticker && config.enableVideoSticker}\r\n                                            onCheckedChange={(checked) => setConfig(prev => ({ ...prev, enableVideoSticker: checked }))}\r\n                                            disabled={!config.enableSticker}\r\n                                        />\r\n                                    </div>\r\n                                    <div className=\"flex items-center justify-between gap-4\">\r\n                                        <Label className=\"text-xs text-muted-foreground whitespace-nowrap\">\r\n                                            Max Duration\r\n                                        </Label>\r\n                                        <div className=\"flex items-center gap-2\">\r\n                                            <Input\r\n                                                type=\"number\"\r\n                                                min={1}\r\n                                                max={60}\r\n                                                className=\"h-8 w-20 text-right\"\r\n                                                value={config.maxStickerDuration || \"\"}\r\n                                                onChange={(e) => {\r\n                                                    const val = e.target.value;\r\n                                                    setConfig(prev => ({\r\n                                                        ...prev,\r\n                                                        maxStickerDuration: val === \"\" ? 0 : parseInt(val)\r\n                                                    }));\r\n                                                }}\r\n                                                disabled={!config.enableVideoSticker}\r\n                                            />\r\n                                            <span className=\"text-xs text-muted-foreground\">sec</span>\r\n                                        </div>\r\n                                    </div>\r\n                                </div>\r\n\r\n                                <div className=\"flex items-center justify-between md:block md:space-y-2\">\r\n                                    <Label className=\"flex items-center gap-2\">\r\n                                        <Activity className=\"h-4 w-4\" /> Ping (#ping)\r\n                                    </Label>\r\n                                    <Switch\r\n                                        checked={config.enablePing}\r\n                                        onCheckedChange={(checked) => setConfig(prev => ({ ...prev, enablePing: checked }))}\r\n                                    />\r\n                                </div>\r\n\r\n                                <div className=\"flex items-center justify-between md:block md:space-y-2\">\r\n                                    <Label className=\"flex items-center gap-2\">\r\n                                        <Loader2 className=\"h-4 w-4\" /> Uptime (#uptime)\r\n                                    </Label>\r\n                                    <Switch\r\n                                        checked={config.enableUptime}\r\n                                        onCheckedChange={(checked) => setConfig(prev => ({ ...prev, enableUptime: checked }))}\r\n                                    />\r\n                                </div>\r\n                            </CardContent>\r\n                        </Card>\r\n\r\n                        {/* Integrations (RemoveBG) */}\r\n                        <Card>\r\n                            <CardHeader>\r\n                                <CardTitle className=\"text-lg flex items-center gap-2\">\r\n                                    <Shield className=\"h-5 w-5\" /> Integrations\r\n                                </CardTitle>\r\n                                <CardDescription>\r\n                                    Configure external keys for enhanced features.\r\n                                </CardDescription>\r\n                            </CardHeader>\r\n                            <CardContent className=\"space-y-4\">\r\n                                <div className=\"space-y-2\">\r\n                                    <Label>Remove.bg API Key</Label>\r\n                                    <div className=\"flex gap-2\">\r\n                                        <Input\r\n                                            type=\"password\"\r\n                                            placeholder=\"rb_xxxxxxxxxxxxxxxx\"\r\n                                            value={config.removeBgApiKey || \"\"}\r\n                                            onChange={(e) => setConfig(prev => ({ ...prev, removeBgApiKey: e.target.value }))}\r\n                                        />\r\n                                    </div>\r\n                                    <p className=\"text-xs text-muted-foreground\">\r\n                                        Required for background removal features. Get one at <a href=\"https://www.remove.bg/api\" target=\"_blank\" rel=\"noopener noreferrer\" className=\"underline hover:text-primary\">remove.bg</a>.\r\n                                        <br />Command: <code>#sticker nobg</code>\r\n                                    </p>\r\n                                </div>\r\n                            </CardContent>\r\n                        </Card>\r\n                    </div>\r\n                </div>\r\n            )}\r\n        </SessionGuard>\r\n    );\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\dashboard\\broadcast\\page.tsx","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'useEffect' is defined but never used.","line":3,"column":20,"nodeType":"Identifier","messageId":"unusedVar","endLine":3,"endColumn":29,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"useEffect"},"fix":{"range":[34,45],"text":""},"desc":"Remove unused variable \"useEffect\"."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'Input' is defined but never used.","line":7,"column":10,"nodeType":"Identifier","messageId":"unusedVar","endLine":7,"endColumn":15,"suggestions":[{"messageId":"removeUnusedImportDeclaration","data":{"varName":"Input"},"fix":{"range":[215,261],"text":""},"desc":"Remove unused import declaration."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'Users' is defined but never used.","line":10,"column":27,"nodeType":"Identifier","messageId":"unusedVar","endLine":10,"endColumn":32,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"Users"},"fix":{"range":[436,443],"text":""},"desc":"Remove unused variable \"Users\"."}]}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\"use client\";\r\n\r\nimport { useState, useEffect } from \"react\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { Textarea } from \"@/components/ui/textarea\";\r\nimport { Label } from \"@/components/ui/label\";\r\nimport { Input } from \"@/components/ui/input\";\r\nimport { Card, CardContent, CardHeader, CardTitle, CardDescription } from \"@/components/ui/card\";\r\nimport { Slider } from \"@/components/ui/slider\";\r\nimport { RefreshCw, Send, Users } from \"lucide-react\";\r\nimport { toast } from \"sonner\";\r\n\r\nimport { useSession } from \"@/components/dashboard/session-provider\";\r\nimport { SessionGuard } from \"@/components/dashboard/session-guard\";\r\n\r\nexport default function BroadcastPage() {\r\n    const { sessionId } = useSession();\r\n    const [contacts, setContacts] = useState(\"\"); // Raw text input\r\n    const [message, setMessage] = useState(\"\");\r\n    const [delay, setDelay] = useState([2000]);\r\n    const [loading, setLoading] = useState(false);\r\n\r\n    const handleSend = async () => {\r\n        if (!sessionId) return alert(\"No active session found\");\r\n        setLoading(true);\r\n\r\n        try {\r\n            // Parse contacts\r\n            const recipients = contacts.split(/[\\n,]+/).map(s => s.trim()).filter(Boolean).map(s => {\r\n                // Formatting helper: ensure ends with @s.whatsapp.net if just number\r\n                if (!s.includes('@')) return `${s}@s.whatsapp.net`;\r\n                return s;\r\n            });\r\n\r\n            const res = await fetch(\"/api/messages/broadcast\", {\r\n                method: \"POST\",\r\n                body: JSON.stringify({\r\n                    sessionId,\r\n                    recipients,\r\n                    message: message, // Send as string, API handles conversion\r\n                    delay: delay[0]\r\n                })\r\n            });\r\n\r\n            if (res.ok) {\r\n                toast.success(\"Broadcast started!\");\r\n                setContacts(\"\");\r\n                setMessage(\"\");\r\n            } else {\r\n                toast.error(\"Failed to start broadcast\");\r\n            }\r\n\r\n        } catch (e) {\r\n            console.error(e);\r\n            toast.error(\"Error sending broadcast\");\r\n        } finally {\r\n            setLoading(false);\r\n        }\r\n    };\r\n\r\n    return (\r\n        <SessionGuard>\r\n            <div className=\"space-y-6\">\r\n                <div className=\"flex justify-between items-center\">\r\n                    <h2 className=\"text-3xl font-bold tracking-tight\">Broadcast / Blast</h2>\r\n                </div>\r\n\r\n                <div className=\"grid gap-6 md:grid-cols-2\">\r\n                    <Card>\r\n                        <CardHeader>\r\n                            <CardTitle>Recipients</CardTitle>\r\n                            <CardDescription>Enter phone numbers separated by comma or new line.</CardDescription>\r\n                        </CardHeader>\r\n                        <CardContent className=\"space-y-4\">\r\n                            <div className=\"space-y-2\">\r\n                                <Label>Target Numbers (e.g., 628123456789)</Label>\r\n                                <Textarea\r\n                                    placeholder=\"628123456789&#10;628987654321\"\r\n                                    className=\"min-h-[200px]\"\r\n                                    value={contacts}\r\n                                    onChange={e => setContacts(e.target.value)}\r\n                                />\r\n                                <p className=\"text-xs text-muted-foreground\">{contacts.split(/[\\n,]+/).filter(Boolean).length} numbers identified</p>\r\n                            </div>\r\n                        </CardContent>\r\n                    </Card>\r\n\r\n                    <Card>\r\n                        <CardHeader>\r\n                            <CardTitle>Message Content</CardTitle>\r\n                        </CardHeader>\r\n                        <CardContent className=\"space-y-4\">\r\n                            <div className=\"space-y-2\">\r\n                                <Label>Message</Label>\r\n                                <Textarea\r\n                                    placeholder=\"Type your message here...\"\r\n                                    className=\"min-h-[150px]\"\r\n                                    value={message}\r\n                                    onChange={e => setMessage(e.target.value)}\r\n                                />\r\n                            </div>\r\n\r\n                            <div className=\"space-y-4 pt-4\">\r\n                                <div className=\"space-y-2\">\r\n                                    <Label>Delay (ms): {delay[0]}</Label>\r\n                                    <Slider\r\n                                        defaultValue={[2000]}\r\n                                        max={10000}\r\n                                        step={100}\r\n                                        value={delay}\r\n                                        onValueChange={setDelay}\r\n                                    />\r\n                                    <p className=\"text-xs text-muted-foreground\">Randomized delay to prevent ban.</p>\r\n                                </div>\r\n\r\n                                <Button className=\"w-full\" onClick={handleSend} disabled={loading || !sessionId}>\r\n                                    {loading ? <RefreshCw className=\"mr-2 h-4 w-4 animate-spin\" /> : <Send className=\"mr-2 h-4 w-4\" />}\r\n                                    Start Broadcast\r\n                                </Button>\r\n                            </div>\r\n                        </CardContent>\r\n                    </Card>\r\n                </div>\r\n            </div>\r\n        </SessionGuard>\r\n    );\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\dashboard\\chat\\page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\dashboard\\contacts\\page.tsx","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'PaginationLink' is defined but never used.","line":21,"column":5,"nodeType":"Identifier","messageId":"unusedVar","endLine":21,"endColumn":19,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"PaginationLink"},"fix":{"range":[537,558],"text":""},"desc":"Remove unused variable \"PaginationLink\"."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'PaginationNext' is defined but never used.","line":22,"column":5,"nodeType":"Identifier","messageId":"unusedVar","endLine":22,"endColumn":19,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"PaginationNext"},"fix":{"range":[558,579],"text":""},"desc":"Remove unused variable \"PaginationNext\"."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'PaginationPrevious' is defined but never used.","line":23,"column":5,"nodeType":"Identifier","messageId":"unusedVar","endLine":23,"endColumn":23,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"PaginationPrevious"},"fix":{"range":[579,604],"text":""},"desc":"Remove unused variable \"PaginationPrevious\"."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'ChevronDown' is defined but never used.","line":26,"column":33,"nodeType":"Identifier","messageId":"unusedVar","endLine":26,"endColumn":44,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"ChevronDown"},"fix":{"range":[676,689],"text":""},"desc":"Remove unused variable \"ChevronDown\"."}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'fetchContacts'. Either include it or remove the dependency array.","line":64,"column":8,"nodeType":"ArrayExpression","endLine":64,"endColumn":16,"suggestions":[{"desc":"Update the dependencies array to be: [fetchContacts, search]","fix":{"range":[1777,1785],"text":"[fetchContacts, search]"}}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'fetchContacts'. Either include it or remove the dependency array.","line":69,"column":8,"nodeType":"ArrayExpression","endLine":69,"endColumn":32,"suggestions":[{"desc":"Update the dependencies array to be: [page, sessionId, limit, fetchContacts]","fix":{"range":[1890,1914],"text":"[page, sessionId, limit, fetchContacts]"}}]}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":6,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\r\n\"use client\";\r\n\r\nimport { useState, useEffect } from \"react\";\r\nimport { useSession } from \"@/components/dashboard/session-provider\";\r\nimport { Card, CardContent, CardHeader, CardTitle, CardDescription } from \"@/components/ui/card\";\r\nimport { Input } from \"@/components/ui/input\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport {\r\n    Table,\r\n    TableBody,\r\n    TableCell,\r\n    TableHead,\r\n    TableHeader,\r\n    TableRow\r\n} from \"@/components/ui/table\";\r\nimport {\r\n    Pagination,\r\n    PaginationContent,\r\n    PaginationItem,\r\n    PaginationLink,\r\n    PaginationNext,\r\n    PaginationPrevious\r\n} from \"@/components/ui/pagination\";\r\n\r\nimport { Search, Loader2, User, ChevronDown } from \"lucide-react\";\r\nimport { Avatar, AvatarFallback, AvatarImage } from \"@/components/ui/avatar\";\r\nimport {\r\n    Select,\r\n    SelectContent,\r\n    SelectItem,\r\n    SelectTrigger,\r\n    SelectValue,\r\n} from \"@/components/ui/select\";\r\n\r\ninterface Contact {\r\n    id: string;\r\n    jid: string;\r\n    name?: string;\r\n    notify?: string;\r\n    verifiedName?: string;\r\n    profilePic?: string;\r\n    remoteJidAlt?: string;\r\n}\r\n\r\nexport default function ContactListPage() {\r\n    const { sessionId } = useSession();\r\n    const [contacts, setContacts] = useState<Contact[]>([]);\r\n    const [loading, setLoading] = useState(false);\r\n\r\n    // Filters\r\n    const [search, setSearch] = useState(\"\");\r\n    const [page, setPage] = useState(1);\r\n    const [limit, setLimit] = useState(\"10\");\r\n    const [meta, setMeta] = useState({ total: 0, totalPages: 1 });\r\n\r\n    // Debounce Search\r\n    useEffect(() => {\r\n        const timer = setTimeout(() => {\r\n            setPage(1); // Reset to page 1 on search\r\n            fetchContacts();\r\n        }, 500);\r\n        return () => clearTimeout(timer);\r\n    }, [search]);\r\n\r\n    // Fetch on page/session/limit change\r\n    useEffect(() => {\r\n        fetchContacts();\r\n    }, [page, sessionId, limit]);\r\n\r\n    const fetchContacts = async () => {\r\n        if (!sessionId) return;\r\n        setLoading(true);\r\n        try {\r\n            const params = new URLSearchParams({\r\n                page: page.toString(),\r\n                limit: limit,\r\n                search: search\r\n            });\r\n\r\n            const res = await fetch(`/api/contacts/${sessionId}?${params}`);\r\n            const data = await res.json();\r\n\r\n            if (res.ok) {\r\n                setContacts(data.data);\r\n                setMeta(data.meta);\r\n            } else {\r\n                setContacts([]);\r\n            }\r\n        } catch (error) {\r\n            console.error(error);\r\n        } finally {\r\n            setLoading(false);\r\n        }\r\n    };\r\n\r\n    return (\r\n        <div className=\"space-y-6\">\r\n            <div className=\"flex flex-col md:flex-row justify-between items-start md:items-center gap-4\">\r\n                <div>\r\n                    <h2 className=\"text-3xl font-bold tracking-tight\">Contacts</h2>\r\n                    <p className=\"text-muted-foreground\">\r\n                        Manage and view your saved contacts.\r\n                    </p>\r\n                </div>\r\n            </div>\r\n\r\n            <Card>\r\n                <CardHeader>\r\n                    <div className=\"flex flex-col md:flex-row justify-between items-center gap-4\">\r\n                        <div className=\"space-y-1\">\r\n                            <CardTitle>Contact List</CardTitle>\r\n                            <CardDescription>\r\n                                Total: {meta.total} contacts found\r\n                            </CardDescription>\r\n                        </div>\r\n                        <div className=\"flex items-center gap-2 w-full md:w-auto\">\r\n                            <Select value={limit} onValueChange={(val) => { setLimit(val); setPage(1); }}>\r\n                                <SelectTrigger className=\"w-[100px]\">\r\n                                    <SelectValue placeholder=\"Limit\" />\r\n                                </SelectTrigger>\r\n                                <SelectContent>\r\n                                    {[5, 10, 25, 50, 100, 200, 250, 500, 1000, 2000, 3000].map((l) => (\r\n                                        <SelectItem key={l} value={l.toString()}>\r\n                                            {l}\r\n                                        </SelectItem>\r\n                                    ))}\r\n                                </SelectContent>\r\n                            </Select>\r\n                            <div className=\"relative w-full md:w-64\">\r\n                                <Search className=\"absolute left-2 top-2.5 h-4 w-4 text-muted-foreground\" />\r\n                                <Input\r\n                                    placeholder=\"Search contacts...\"\r\n                                    className=\"pl-8\"\r\n                                    value={search}\r\n                                    onChange={(e) => setSearch(e.target.value)}\r\n                                />\r\n                            </div>\r\n                        </div>\r\n                    </div>\r\n                </CardHeader>\r\n                <CardContent>\r\n                    <div className=\"rounded-md border\">\r\n                        <Table>\r\n                            <TableHeader>\r\n                                <TableRow>\r\n                                    <TableHead className=\"w-[80px]\">Image</TableHead>\r\n                                    <TableHead>Name / Pushname</TableHead>\r\n                                    <TableHead className=\"hidden md:table-cell\">JID (ID)</TableHead>\r\n                                    <TableHead className=\"hidden md:table-cell\">Phone / Alt</TableHead>\r\n                                </TableRow>\r\n                            </TableHeader>\r\n                            <TableBody>\r\n                                {loading ? (\r\n                                    <TableRow>\r\n                                        <TableCell colSpan={4} className=\"h-24 text-center\">\r\n                                            <div className=\"flex justify-center items-center gap-2\">\r\n                                                <Loader2 className=\"h-4 w-4 animate-spin\" />\r\n                                                Loading...\r\n                                            </div>\r\n                                        </TableCell>\r\n                                    </TableRow>\r\n                                ) : contacts.length === 0 ? (\r\n                                    <TableRow>\r\n                                        <TableCell colSpan={4} className=\"h-24 text-center\">\r\n                                            No contacts found.\r\n                                        </TableCell>\r\n                                    </TableRow>\r\n                                ) : (\r\n                                    contacts.map((contact) => (\r\n                                        <TableRow key={contact.id}>\r\n                                            <TableCell>\r\n                                                <Avatar>\r\n                                                    <AvatarImage src={contact.profilePic || \"\"} />\r\n                                                    <AvatarFallback><User className=\"h-4 w-4\" /></AvatarFallback>\r\n                                                </Avatar>\r\n                                            </TableCell>\r\n                                            <TableCell>\r\n                                                <div className=\"flex flex-col\">\r\n                                                    <span className=\"font-medium\">{contact.name || contact.notify || \"Unknown\"}</span>\r\n                                                    {contact.verifiedName && (\r\n                                                        <span className=\"text-xs text-green-600 flex items-center gap-1\">\r\n                                                            Γ£ô {contact.verifiedName}\r\n                                                        </span>\r\n                                                    )}\r\n                                                </div>\r\n                                            </TableCell>\r\n                                            <TableCell className=\"hidden md:table-cell font-mono text-sm text-muted-foreground\">\r\n                                                {contact.jid}\r\n                                            </TableCell>\r\n                                            <TableCell className=\"hidden md:table-cell text-sm\">\r\n                                                {contact.remoteJidAlt || \"-\"}\r\n                                            </TableCell>\r\n                                        </TableRow>\r\n                                    ))\r\n                                )}\r\n                            </TableBody>\r\n                        </Table>\r\n                    </div>\r\n\r\n                    {/* Pagination */}\r\n                    {meta.totalPages > 1 && (\r\n                        <div className=\"mt-4\">\r\n                            <Pagination>\r\n                                <PaginationContent>\r\n                                    <PaginationItem>\r\n                                        <Button\r\n                                            variant=\"ghost\"\r\n                                            disabled={page <= 1}\r\n                                            onClick={() => setPage(p => Math.max(1, p - 1))}\r\n                                        >\r\n                                            Previous\r\n                                        </Button>\r\n                                    </PaginationItem>\r\n\r\n                                    <PaginationItem>\r\n                                        <span className=\"text-sm text-muted-foreground mx-4\">\r\n                                            Page {page} of {meta.totalPages}\r\n                                        </span>\r\n                                    </PaginationItem>\r\n\r\n                                    <PaginationItem>\r\n                                        <Button\r\n                                            variant=\"ghost\"\r\n                                            disabled={page >= meta.totalPages}\r\n                                            onClick={() => setPage(p => Math.min(meta.totalPages, p + 1))}\r\n                                        >\r\n                                            Next\r\n                                        </Button>\r\n                                    </PaginationItem>\r\n                                </PaginationContent>\r\n                            </Pagination>\r\n                        </div>\r\n                    )}\r\n                </CardContent>\r\n            </Card>\r\n        </div>\r\n    );\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\dashboard\\groups\\page.tsx","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'Card' is defined but never used.","line":5,"column":10,"nodeType":"Identifier","messageId":"unusedVar","endLine":5,"endColumn":14,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"Card"},"fix":{"range":[122,127],"text":""},"desc":"Remove unused variable \"Card\"."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'CardContent' is defined but never used.","line":5,"column":16,"nodeType":"Identifier","messageId":"unusedVar","endLine":5,"endColumn":27,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"CardContent"},"fix":{"range":[126,139],"text":""},"desc":"Remove unused variable \"CardContent\"."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'CardHeader' is defined but never used.","line":5,"column":29,"nodeType":"Identifier","messageId":"unusedVar","endLine":5,"endColumn":39,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"CardHeader"},"fix":{"range":[139,151],"text":""},"desc":"Remove unused variable \"CardHeader\"."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'CardTitle' is defined but never used.","line":5,"column":41,"nodeType":"Identifier","messageId":"unusedVar","endLine":5,"endColumn":50,"suggestions":[{"messageId":"removeUnusedImportDeclaration","data":{"varName":"CardTitle"},"fix":{"range":[113,193],"text":""},"desc":"Remove unused import declaration."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'Dialog' is defined but never used.","line":6,"column":10,"nodeType":"Identifier","messageId":"unusedVar","endLine":6,"endColumn":16,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"Dialog"},"fix":{"range":[204,211],"text":""},"desc":"Remove unused variable \"Dialog\"."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'DialogContent' is defined but never used.","line":6,"column":18,"nodeType":"Identifier","messageId":"unusedVar","endLine":6,"endColumn":31,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"DialogContent"},"fix":{"range":[210,225],"text":""},"desc":"Remove unused variable \"DialogContent\"."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'DialogHeader' is defined but never used.","line":6,"column":33,"nodeType":"Identifier","messageId":"unusedVar","endLine":6,"endColumn":45,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"DialogHeader"},"fix":{"range":[225,239],"text":""},"desc":"Remove unused variable \"DialogHeader\"."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'DialogTitle' is defined but never used.","line":6,"column":47,"nodeType":"Identifier","messageId":"unusedVar","endLine":6,"endColumn":58,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"DialogTitle"},"fix":{"range":[239,252],"text":""},"desc":"Remove unused variable \"DialogTitle\"."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'DialogTrigger' is defined but never used.","line":6,"column":60,"nodeType":"Identifier","messageId":"unusedVar","endLine":6,"endColumn":73,"suggestions":[{"messageId":"removeUnusedImportDeclaration","data":{"varName":"DialogTrigger"},"fix":{"range":[195,300],"text":""},"desc":"Remove unused import declaration."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":20,"column":20,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":20,"endColumn":23,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[872,875],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[872,875],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'error' is defined but never used.","line":42,"column":18,"nodeType":"Identifier","messageId":"unusedVar","endLine":42,"endColumn":23},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'error' is defined but never used.","line":73,"column":18,"nodeType":"Identifier","messageId":"unusedVar","endLine":73,"endColumn":23}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":11,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\"use client\";\r\n\r\nimport { useEffect, useState } from \"react\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { Card, CardContent, CardHeader, CardTitle } from \"@/components/ui/card\";\r\nimport { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from \"@/components/ui/dialog\";\r\nimport { Input } from \"@/components/ui/input\";\r\nimport { Label } from \"@/components/ui/label\";\r\nimport { Users, Plus, RefreshCw } from \"lucide-react\";\r\nimport { SearchFilter } from \"@/components/dashboard/search-filter\";\r\nimport { useSession } from \"@/components/dashboard/session-provider\";\r\nimport { SessionGuard } from \"@/components/dashboard/session-guard\";\r\nimport { toast } from \"sonner\"; // Added import\r\n\r\n// Define a type for Group if not already defined elsewhere\r\ninterface Group {\r\n    id: string;\r\n    subject: string;\r\n    jid: string;\r\n    participants?: any[];\r\n}\r\n\r\nexport default function GroupsPage() {\r\n    const { sessionId } = useSession();\r\n\r\n    const [groups, setGroups] = useState<Group[]>([]);\r\n    const [loading, setLoading] = useState(false);\r\n    const [isCreateOpen, setIsCreateOpen] = useState(false);\r\n    const [newGroupName, setNewGroupName] = useState(\"\");\r\n    const [searchTerm, setSearchTerm] = useState(\"\");\r\n\r\n    const fetchGroups = async (sessId: string) => {\r\n        setLoading(true);\r\n        try {\r\n            const res = await fetch(`/api/groups/${sessId}`);\r\n            if (res.ok) {\r\n                const data = await res.json();\r\n                setGroups(data);\r\n            } else {\r\n                setGroups([]);\r\n            }\r\n        } catch (error) {\r\n            toast.error(\"Failed to fetch groups\");\r\n        } finally {\r\n            setLoading(false);\r\n        }\r\n    };\r\n\r\n    useEffect(() => {\r\n        if (sessionId) {\r\n            fetchGroups(sessionId);\r\n        } else {\r\n            setGroups([]);\r\n        }\r\n    }, [sessionId]);\r\n\r\n    const handleCreateGroup = async () => {\r\n        if (!sessionId || !newGroupName) return;\r\n        try {\r\n            const res = await fetch(`/api/groups/${sessionId}/create`, {\r\n                method: \"POST\",\r\n                headers: { \"Content-Type\": \"application/json\" },\r\n                body: JSON.stringify({ sessionId, subject: newGroupName })\r\n            });\r\n            if (res.ok) {\r\n                toast.success(\"Group created\");\r\n                setIsCreateOpen(false);\r\n                setNewGroupName(\"\");\r\n                fetchGroups(sessionId);\r\n            } else {\r\n                toast.error(\"Failed to create group\");\r\n            }\r\n        } catch (error) {\r\n            toast.error(\"Failed to create group\");\r\n        }\r\n    };\r\n\r\n    const filteredGroups = groups.filter(g =>\r\n        g.subject.toLowerCase().includes(searchTerm.toLowerCase()) ||\r\n        g.jid.includes(searchTerm)\r\n    );\r\n\r\n    return (\r\n        <SessionGuard>\r\n            <div className=\"space-y-6\">\r\n                <div className=\"flex justify-between items-center\">\r\n                    <div>\r\n                        <h1 className=\"text-2xl font-bold flex items-center gap-2\">\r\n                            <Users className=\"h-6 w-6\" /> Groups\r\n                        </h1>\r\n                        <p className=\"text-muted-foreground\">\r\n                            {sessionId ? \"Manage groups for active session.\" : \"Select a session from the top bar.\"}\r\n                        </p>\r\n                    </div>\r\n                    <div className=\"flex items-center gap-2\">\r\n                        <Button variant=\"outline\" onClick={() => sessionId && fetchGroups(sessionId)} disabled={loading || !sessionId}>\r\n                            <RefreshCw className={`h-4 w-4 mr-2 ${loading ? 'animate-spin' : ''}`} />\r\n                            Refresh\r\n                        </Button>\r\n                        <Button onClick={() => setIsCreateOpen(true)} disabled={!sessionId}>\r\n                            <Plus className=\"h-4 w-4 mr-2\" /> Create Group\r\n                        </Button>\r\n                    </div>\r\n                </div>\r\n\r\n                <SearchFilter\r\n                    placeholder=\"Search groups...\"\r\n                    onSearch={setSearchTerm}\r\n                />\r\n\r\n                {/* Create Dialog */}\r\n                {isCreateOpen && (\r\n                    <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50\">\r\n                        <div className=\"bg-white p-6 rounded-lg shadow-lg w-96\">\r\n                            <h2 className=\"text-xl font-bold mb-4\">Create New Group</h2>\r\n                            <div className=\"space-y-4\">\r\n                                <div>\r\n                                    <Label>Group Subject</Label>\r\n                                    <Input value={newGroupName} onChange={e => setNewGroupName(e.target.value)} placeholder=\"My New Group\" />\r\n                                </div>\r\n                                <div className=\"flex justify-end gap-2\">\r\n                                    <Button variant=\"ghost\" onClick={() => setIsCreateOpen(false)}>Cancel</Button>\r\n                                    <Button onClick={handleCreateGroup}>Create</Button>\r\n                                </div>\r\n                            </div>\r\n                        </div>\r\n                    </div>\r\n                )}\r\n\r\n                {/* Groups List */}\r\n                {loading ? (\r\n                    <div className=\"text-center p-8\">Loading groups...</div>\r\n                ) : filteredGroups.length === 0 ? (\r\n                    <div className=\"text-center p-8 text-muted-foreground border rounded-lg bg-slate-50\">\r\n                        {sessionId ? \"No groups found matching criteria.\" : \"No session selected.\"}\r\n                    </div>\r\n                ) : (\r\n                    <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-3\">\r\n                        {filteredGroups.map(group => (\r\n                            <div key={group.id} className=\"bg-white p-4 rounded-lg shadow border flex justify-between items-start\">\r\n                                <div>\r\n                                    <h3 className=\"font-bold text-lg\">{group.subject}</h3>\r\n                                    <div className=\"text-xs text-muted-foreground mt-1\">{group.jid}</div>\r\n                                    <div className=\"text-xs text-slate-500 mt-1\">Participants: {group.participants?.length || 0}</div>\r\n                                </div>\r\n                            </div>\r\n                        ))}\r\n                    </div>\r\n                )}\r\n            </div>\r\n        </SessionGuard>\r\n    );\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\dashboard\\layout.tsx","messages":[{"ruleId":"@typescript-eslint/ban-ts-comment","severity":2,"message":"Use \"@ts-expect-error\" instead of \"@ts-ignore\", as \"@ts-ignore\" will do nothing if the following line is error-free.","line":19,"column":5,"nodeType":"Line","messageId":"tsIgnoreInsteadOfExpectError","endLine":19,"endColumn":18,"suggestions":[{"messageId":"replaceTsIgnoreWithTsExpectError","fix":{"range":[674,687],"text":"// @ts-expect-error"},"desc":"Replace \"@ts-ignore\" with \"@ts-expect-error\"."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Button } from \"@/components/ui/button\";\r\nimport { auth, signOut } from \"@/lib/auth\";\r\nimport { Navbar } from \"@/components/dashboard/navbar\";\r\nimport { SessionProvider } from \"@/components/dashboard/session-provider\";\r\nimport { SidebarNav } from \"@/components/dashboard/sidebar-nav\";\r\nimport { LogOut } from \"lucide-react\";\r\nimport { UpdateChecker } from \"@/components/dashboard/update-checker\";\r\nimport { prisma } from \"@/lib/prisma\";\r\nimport { Toaster } from \"sonner\";\r\nimport pkg from \"../../../package.json\";\r\n\r\n\r\nexport default async function DashboardLayout({\r\n    children,\r\n}: {\r\n    children: React.ReactNode;\r\n}) {\r\n    const session = await auth();\r\n    // @ts-ignore\r\n    const systemConfig = await prisma.systemConfig.findUnique({ where: { id: \"default\" } });\r\n    const appName = systemConfig?.appName || \"WA-AKG\";\r\n\r\n    return (\r\n        <SessionProvider>\r\n            <UpdateChecker />\r\n            <div className=\"flex h-screen bg-background relative overflow-hidden\">\r\n                {/* Ambient Dashboard Background */}\r\n                <div className=\"absolute top-0 left-0 w-full h-full overflow-hidden pointer-events-none z-0\">\r\n                    <div className=\"absolute top-[-10%] left-[-10%] w-[40rem] h-[40rem] bg-emerald-500/5 dark:bg-emerald-500/10 rounded-full blur-[120px]\" />\r\n                    <div className=\"absolute bottom-[-10%] right-[-10%] w-[30rem] h-[30rem] bg-blue-500/5 dark:bg-blue-500/10 rounded-full blur-[100px]\" />\r\n                </div>\r\n\r\n                {/* Sidebar */}\r\n                <aside className=\"w-[280px] bg-background/60 backdrop-blur-xl border-r border-border/50 hidden md:flex flex-col h-full sticky left-0 top-0 z-20 shadow-[4px_0_24px_-12px_rgba(0,0,0,0.1)]\">\r\n                    {/* Logo / Brand */}\r\n                    <div className=\"px-6 py-6 border-b border-border/50\">\r\n                        <h1 className=\"text-2xl font-bold tracking-tight text-transparent bg-clip-text bg-gradient-to-r from-primary to-blue-500\">{appName}</h1>\r\n                        <p className=\"text-xs text-muted-foreground mt-1 font-medium\">WhatsApp Gateway</p>\r\n                    </div>\r\n\r\n                    {/* Navigation */}\r\n                    <SidebarNav />\r\n\r\n                    {/* User Footer */}\r\n                    <div className=\"p-5 border-t border-border/50 bg-background/40\">\r\n                        <div className=\"flex items-center gap-3 mb-4\">\r\n                            <div className=\"h-9 w-9 rounded-xl bg-gradient-to-br from-primary/20 to-blue-500/20 flex items-center justify-center text-sm font-bold text-primary border border-primary/20 shadow-inner\">\r\n                                {session?.user?.name?.charAt(0)?.toUpperCase() || \"U\"}\r\n                            </div>\r\n                            <div className=\"flex-1 min-w-0\">\r\n                                <p className=\"text-sm font-semibold text-foreground truncate\">{session?.user?.name || \"User\"}</p>\r\n                                <p className=\"text-xs text-muted-foreground truncate\">{session?.user?.email}</p>\r\n                            </div>\r\n                        </div>\r\n                        <form action={async () => {\r\n                            'use server';\r\n                            await signOut();\r\n                        }}>\r\n                            <Button variant=\"outline\" size=\"sm\" className=\"w-full flex items-center justify-center gap-2 text-xs h-9 rounded-xl border-border/50 hover:bg-destructive/10 hover:text-destructive hover:border-destructive/30 transition-colors\">\r\n                                <LogOut size={14} /> Sign Out\r\n                            </Button>\r\n                        </form>\r\n                        <p className=\"text-[10px] text-muted-foreground/60 text-center mt-3 font-mono\">v{pkg.version}</p>\r\n                    </div>\r\n                </aside>\r\n\r\n                {/* Main Content */}\r\n                <div className=\"flex-1 flex flex-col overflow-hidden min-w-0 relative z-10\">\r\n                    <Navbar appName={appName} />\r\n                    <main className=\"flex-1 overflow-auto p-4 sm:p-6 lg:p-8 styled-scrollbar\">\r\n                        {children}\r\n                    </main>\r\n                </div>\r\n                <Toaster />\r\n            </div>\r\n        </SessionProvider>\r\n    );\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\dashboard\\loading.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\dashboard\\notifications\\page.tsx","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'useSession' is defined but never used.","line":14,"column":10,"nodeType":"Identifier","messageId":"unusedVar","endLine":14,"endColumn":20,"suggestions":[{"messageId":"removeUnusedImportDeclaration","data":{"varName":"useSession"},"fix":{"range":[599,644],"text":""},"desc":"Remove unused import declaration."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'e' is defined but never used.","line":57,"column":18,"nodeType":"Identifier","messageId":"unusedVar","endLine":57,"endColumn":19}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\r\n\"use client\";\r\n\r\nimport { useState } from \"react\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { Input } from \"@/components/ui/input\";\r\nimport { Textarea } from \"@/components/ui/textarea\";\r\nimport { Label } from \"@/components/ui/label\";\r\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"@/components/ui/select\";\r\nimport { Card, CardContent, CardHeader, CardTitle, CardDescription } from \"@/components/ui/card\";\r\nimport { Switch } from \"@/components/ui/switch\";\r\nimport { Bell, Send, CheckCircle2 } from \"lucide-react\";\r\nimport { toast } from \"sonner\";\r\nimport { useSession } from \"next-auth/react\"; // Use client session for Role check UI-side\r\n\r\nexport default function NotificationAdminPage() {\r\n    // Note: Server-side protection is also needed.\r\n    // For now assuming Layout or Middleware handles role check, or API sends 403.\r\n\r\n    const [title, setTitle] = useState(\"\");\r\n    const [message, setMessage] = useState(\"\");\r\n    const [type, setType] = useState(\"INFO\");\r\n    const [broadcast, setBroadcast] = useState(true);\r\n    const [targetUserId, setTargetUserId] = useState(\"\");\r\n    const [href, setHref] = useState(\"\");\r\n    const [loading, setLoading] = useState(false);\r\n\r\n    const handleSend = async () => {\r\n        if (!title || !message) return toast.error(\"Title and Message are required\");\r\n        if (!broadcast && !targetUserId) return toast.error(\"Target User ID is required for non-broadcast\");\r\n\r\n        setLoading(true);\r\n        try {\r\n            const res = await fetch(\"/api/notifications\", {\r\n                method: \"POST\",\r\n                headers: { \"Content-Type\": \"application/json\" },\r\n                body: JSON.stringify({\r\n                    title,\r\n                    message,\r\n                    type,\r\n                    broadcast,\r\n                    targetUserId: broadcast ? undefined : targetUserId,\r\n                    href\r\n                })\r\n            });\r\n\r\n            if (res.ok) {\r\n                const data = await res.json();\r\n                toast.success(`Notification sent successfully! (Count: ${data.count || 1})`);\r\n                // Reset form\r\n                setTitle(\"\");\r\n                setMessage(\"\");\r\n                setHref(\"\");\r\n            } else {\r\n                toast.error(\"Failed to send notification\");\r\n            }\r\n        } catch (e) {\r\n            toast.error(\"Error sending notification\");\r\n        } finally {\r\n            setLoading(false);\r\n        }\r\n    };\r\n\r\n    return (\r\n        <div className=\"space-y-6\">\r\n            <div className=\"flex justify-between items-center\">\r\n                <h1 className=\"text-3xl font-bold flex items-center gap-2\">\r\n                    <Bell className=\"h-8 w-8\" /> Notification Manager\r\n                </h1>\r\n            </div>\r\n\r\n            <div className=\"grid gap-6 md:grid-cols-2\">\r\n                <Card>\r\n                    <CardHeader>\r\n                        <CardTitle>Compose Notification</CardTitle>\r\n                        <CardDescription>Send alerts to users or system-wide broadcasts.</CardDescription>\r\n                    </CardHeader>\r\n                    <CardContent className=\"space-y-4\">\r\n                        <div className=\"space-y-2\">\r\n                            <Label>Title</Label>\r\n                            <Input value={title} onChange={e => setTitle(e.target.value)} placeholder=\"e.g. System Maintenance\" />\r\n                        </div>\r\n\r\n                        <div className=\"space-y-2\">\r\n                            <Label>Message</Label>\r\n                            <Textarea value={message} onChange={e => setMessage(e.target.value)} placeholder=\"Detailed message...\" />\r\n                        </div>\r\n\r\n                        <div className=\"grid grid-cols-2 gap-4\">\r\n                            <div className=\"space-y-2\">\r\n                                <Label>Type</Label>\r\n                                <Select value={type} onValueChange={setType}>\r\n                                    <SelectTrigger>\r\n                                        <SelectValue />\r\n                                    </SelectTrigger>\r\n                                    <SelectContent>\r\n                                        <SelectItem value=\"INFO\">Info</SelectItem>\r\n                                        <SelectItem value=\"WARNING\">Warning</SelectItem>\r\n                                        <SelectItem value=\"SUCCESS\">Success</SelectItem>\r\n                                        <SelectItem value=\"SYSTEM\">System</SelectItem>\r\n                                    </SelectContent>\r\n                                </Select>\r\n                            </div>\r\n\r\n                            <div className=\"space-y-2\">\r\n                                <Label>Action Link (Optional)</Label>\r\n                                <Input value={href} onChange={e => setHref(e.target.value)} placeholder=\"/dashboard/settings\" />\r\n                            </div>\r\n                        </div>\r\n\r\n                        <div className=\"flex items-center space-x-2 py-2\">\r\n                            <Switch id=\"broadcast\" checked={broadcast} onCheckedChange={setBroadcast} />\r\n                            <Label htmlFor=\"broadcast\">Broadcast to ALL Users</Label>\r\n                        </div>\r\n\r\n                        {!broadcast && (\r\n                            <div className=\"space-y-2 animate-in fade-in slide-in-from-top-2\">\r\n                                <Label>Target User ID</Label>\r\n                                <Input value={targetUserId} onChange={e => setTargetUserId(e.target.value)} placeholder=\"User ID (cuid)\" />\r\n                            </div>\r\n                        )}\r\n\r\n                        <div className=\"pt-4\">\r\n                            <Button className=\"w-full\" onClick={handleSend} disabled={loading}>\r\n                                {loading ? <CheckCircle2 className=\"mr-2 h-4 w-4 animate-spin\" /> : <Send className=\"mr-2 h-4 w-4\" />}\r\n                                Send Notification\r\n                            </Button>\r\n                        </div>\r\n                    </CardContent>\r\n                </Card>\r\n\r\n                <div className=\"space-y-6\">\r\n                    <Card className=\"bg-slate-50 border-dashed\">\r\n                        <CardHeader>\r\n                            <CardTitle className=\"text-base text-muted-foreground\">Preview</CardTitle>\r\n                        </CardHeader>\r\n                        <CardContent>\r\n                            <div className=\"bg-white p-4 rounded-lg shadow-sm border flex gap-3 items-start\">\r\n                                <div className={`p-2 rounded-full ${type === 'WARNING' ? 'bg-yellow-100 text-yellow-600' : type === 'SUCCESS' ? 'bg-green-100 text-green-600' : 'bg-blue-100 text-blue-600'}`}>\r\n                                    <Bell className=\"h-5 w-5\" />\r\n                                </div>\r\n                                <div>\r\n                                    <h4 className=\"font-semibold text-sm\">{title || \"Notification Title\"}</h4>\r\n                                    <p className=\"text-xs text-muted-foreground mt-1\">{message || \"Notification message content will appear here.\"}</p>\r\n                                    <p className=\"text-[10px] text-slate-400 mt-2\">Just now</p>\r\n                                </div>\r\n                            </div>\r\n                        </CardContent>\r\n                    </Card>\r\n                </div>\r\n            </div>\r\n        </div>\r\n    );\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\dashboard\\page.tsx","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'CardHeader' is defined but never used.","line":2,"column":16,"nodeType":"Identifier","messageId":"unusedVar","endLine":2,"endColumn":26,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"CardHeader"},"fix":{"range":[53,65],"text":""},"desc":"Remove unused variable \"CardHeader\"."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'CardTitle' is defined but never used.","line":2,"column":28,"nodeType":"Identifier","messageId":"unusedVar","endLine":2,"endColumn":37,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"CardTitle"},"fix":{"range":[65,76],"text":""},"desc":"Remove unused variable \"CardTitle\"."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'CardDescription' is defined but never used.","line":2,"column":52,"nodeType":"Identifier","messageId":"unusedVar","endLine":2,"endColumn":67,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"CardDescription"},"fix":{"range":[89,106],"text":""},"desc":"Remove unused variable \"CardDescription\"."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'Settings' is defined but never used.","line":12,"column":5,"nodeType":"Identifier","messageId":"unusedVar","endLine":12,"endColumn":13,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"Settings"},"fix":{"range":[304,319],"text":""},"desc":"Remove unused variable \"Settings\"."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'Activity' is defined but never used.","line":15,"column":5,"nodeType":"Identifier","messageId":"unusedVar","endLine":15,"endColumn":13,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"Activity"},"fix":{"range":[349,364],"text":""},"desc":"Remove unused variable \"Activity\"."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'otherSessions' is assigned a value but never used.","line":36,"column":11,"nodeType":"Identifier","messageId":"unusedVar","endLine":36,"endColumn":24}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":6,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { prisma } from \"@/lib/prisma\";\r\nimport { Card, CardHeader, CardTitle, CardContent, CardDescription } from \"@/components/ui/card\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport Link from \"next/link\";\r\nimport {\r\n    Plus,\r\n    Wifi,\r\n    WifiOff,\r\n    MessageSquare,\r\n    Bot,\r\n    Send,\r\n    Settings,\r\n    QrCode,\r\n    ArrowRight,\r\n    Activity,\r\n    Zap,\r\n} from \"lucide-react\";\r\n\r\nimport { auth } from \"@/lib/auth\";\r\nimport { getAccessibleSessions } from \"@/lib/api-auth\";\r\nimport { redirect } from \"next/navigation\";\r\n\r\nexport const dynamic = 'force-dynamic';\r\n\r\nexport default async function DashboardPage() {\r\n    const session = await auth();\r\n    if (!session?.user) {\r\n        redirect(\"/login\");\r\n    }\r\n\r\n    const sessions = await getAccessibleSessions(session.user.id!, session.user.role || \"OWNER\");\r\n\r\n    const totalSessions = sessions.length;\r\n    const connectedSessions = sessions.filter(s => s.status === 'CONNECTED').length;\r\n    const disconnectedSessions = sessions.filter(s => s.status === 'DISCONNECTED' || s.status === 'CLOSE').length;\r\n    const otherSessions = totalSessions - connectedSessions - disconnectedSessions;\r\n\r\n    // Fetch auto-reply count for accessible sessions\r\n    let autoReplyCount = 0;\r\n    try {\r\n        const sessionIds = sessions.map(s => s.sessionId);\r\n        if (sessionIds.length > 0) {\r\n            autoReplyCount = await prisma.autoReply.count({\r\n                where: { sessionId: { in: sessionIds } }\r\n            });\r\n        }\r\n    } catch {\r\n        // If auto-reply table doesn't exist yet, just show 0\r\n    }\r\n\r\n    const stats = [\r\n        {\r\n            title: \"Total Sessions\",\r\n            value: totalSessions,\r\n            icon: QrCode,\r\n            description: \"Registered sessions\",\r\n            color: \"text-blue-600\",\r\n            bg: \"bg-blue-50\",\r\n        },\r\n        {\r\n            title: \"Connected\",\r\n            value: connectedSessions,\r\n            icon: Wifi,\r\n            description: \"Online & ready\",\r\n            color: \"text-emerald-600\",\r\n            bg: \"bg-emerald-50\",\r\n        },\r\n        {\r\n            title: \"Disconnected\",\r\n            value: disconnectedSessions,\r\n            icon: WifiOff,\r\n            description: \"Needs reconnection\",\r\n            color: \"text-red-500\",\r\n            bg: \"bg-red-50\",\r\n        },\r\n        {\r\n            title: \"Auto-Reply Rules\",\r\n            value: autoReplyCount,\r\n            icon: Zap,\r\n            description: \"Active automations\",\r\n            color: \"text-amber-600\",\r\n            bg: \"bg-amber-50\",\r\n        },\r\n    ];\r\n\r\n    const quickActions = [\r\n        { href: \"/dashboard/sessions\", label: \"New Session\", icon: Plus, description: \"Connect a new device\" },\r\n        { href: \"/dashboard/chat\", label: \"Send Message\", icon: Send, description: \"Open chat interface\" },\r\n        { href: \"/dashboard/bot-settings\", label: \"Bot Settings\", icon: Bot, description: \"Configure chatbot\" },\r\n        { href: \"/dashboard/autoreply\", label: \"Auto Reply\", icon: MessageSquare, description: \"Manage keywords\" },\r\n    ];\r\n\r\n    return (\r\n        <div className=\"space-y-8\">\r\n            {/* Header */}\r\n            <div className=\"flex flex-col sm:flex-row sm:justify-between sm:items-center gap-4\">\r\n                <div>\r\n                    <h2 className=\"text-2xl sm:text-3xl font-bold tracking-tight text-slate-900\">Dashboard</h2>\r\n                    <p className=\"text-sm text-slate-500 mt-1\">Overview of your WhatsApp gateway</p>\r\n                </div>\r\n                <Link href=\"/dashboard/sessions\">\r\n                    <Button size=\"sm\" className=\"gap-2\">\r\n                        <Plus className=\"h-4 w-4\" /> Add Session\r\n                    </Button>\r\n                </Link>\r\n            </div>\r\n\r\n            {/* Stats Grid */}\r\n            <div className=\"grid grid-cols-2 lg:grid-cols-4 gap-4\">\r\n                {stats.map((stat) => {\r\n                    const Icon = stat.icon;\r\n                    return (\r\n                        <Card key={stat.title} className=\"glass-panel border-border/50 shadow-sm hover:shadow-md hover:shadow-primary/5 transition-all duration-300\">\r\n                            <CardContent className=\"p-4 sm:p-5\">\r\n                                <div className=\"flex items-start justify-between\">\r\n                                    <div className=\"space-y-1\">\r\n                                        <p className=\"text-xs font-bold text-muted-foreground uppercase tracking-widest\">{stat.title}</p>\r\n                                        <p className=\"text-2xl sm:text-3xl font-extrabold text-foreground\">{stat.value}</p>\r\n                                        <p className=\"text-xs text-muted-foreground/70\">{stat.description}</p>\r\n                                    </div>\r\n                                    <div className={`${stat.bg} p-2.5 rounded-xl border object-contain border-white/20 dark:border-white/10 shadow-sm`}>\r\n                                        <Icon className={`h-5 w-5 ${stat.color}`} />\r\n                                    </div>\r\n                                </div>\r\n                            </CardContent>\r\n                        </Card>\r\n                    );\r\n                })}\r\n            </div>\r\n\r\n            {/* Quick Actions */}\r\n            <div>\r\n                <h3 className=\"text-sm font-semibold text-slate-500 uppercase tracking-wide mb-3\">Quick Actions</h3>\r\n                <div className=\"grid grid-cols-2 lg:grid-cols-4 gap-3\">\r\n                    {quickActions.map((action) => {\r\n                        const Icon = action.icon;\r\n                        return (\r\n                            <Link key={action.href} href={action.href}>\r\n                                <Card className=\"glass-panel border-border/50 shadow-sm hover:shadow-md hover:shadow-primary/10 hover:-translate-y-0.5 transition-all duration-300 group cursor-pointer h-full\">\r\n                                    <CardContent className=\"p-4 flex items-center gap-3\">\r\n                                        <div className=\"bg-muted/50 p-2.5 rounded-xl group-hover:bg-primary transition-colors border border-border/50 shadow-sm\">\r\n                                            <Icon className=\"h-5 w-5 text-muted-foreground group-hover:text-primary-foreground transition-colors\" />\r\n                                        </div>\r\n                                        <div className=\"min-w-0\">\r\n                                            <p className=\"text-sm font-semibold text-foreground truncate\">{action.label}</p>\r\n                                            <p className=\"text-xs text-muted-foreground/80 truncate\">{action.description}</p>\r\n                                        </div>\r\n                                    </CardContent>\r\n                                </Card>\r\n                            </Link>\r\n                        );\r\n                    })}\r\n                </div>\r\n            </div>\r\n\r\n            {/* Sessions List */}\r\n            <div>\r\n                <div className=\"flex items-center justify-between mb-3\">\r\n                    <h3 className=\"text-sm font-bold text-muted-foreground uppercase tracking-widest\">Sessions</h3>\r\n                    <Link href=\"/dashboard/sessions\" className=\"text-xs text-primary hover:text-primary/80 font-medium flex items-center gap-1 transition-colors\">\r\n                        View all <ArrowRight size={14} />\r\n                    </Link>\r\n                </div>\r\n\r\n                {sessions.length === 0 ? (\r\n                    <Card className=\"border-dashed border-2 border-slate-200 shadow-none\">\r\n                        <CardContent className=\"py-12 text-center\">\r\n                            <div className=\"bg-slate-100 h-12 w-12 rounded-full flex items-center justify-center mx-auto mb-3\">\r\n                                <QrCode className=\"h-6 w-6 text-slate-400\" />\r\n                            </div>\r\n                            <p className=\"text-sm font-medium text-slate-600 mb-1\">No sessions yet</p>\r\n                            <p className=\"text-xs text-slate-400 mb-4\">Connect your first WhatsApp device to get started</p>\r\n                            <Link href=\"/dashboard/sessions\">\r\n                                <Button size=\"sm\" variant=\"outline\" className=\"gap-2\">\r\n                                    <Plus className=\"h-4 w-4\" /> Create Session\r\n                                </Button>\r\n                            </Link>\r\n                        </CardContent>\r\n                    </Card>\r\n                ) : (\r\n                    <div className=\"grid gap-3 sm:grid-cols-2 lg:grid-cols-3\">\r\n                        {sessions.map(s => {\r\n                            const isConnected = s.status === 'CONNECTED';\r\n                            const isDisconnected = s.status === 'DISCONNECTED' || s.status === 'CLOSE';\r\n\r\n                            return (\r\n                                <Link key={s.id} href={`/dashboard/sessions/${s.id}`}>\r\n                                    <Card className=\"glass-panel border-border/50 shadow-sm hover:shadow-md hover:shadow-primary/5 hover:-translate-y-0.5 transition-all duration-300 cursor-pointer h-full\">\r\n                                        <CardContent className=\"p-4\">\r\n                                            <div className=\"flex items-start justify-between mb-2\">\r\n                                                <div className=\"min-w-0 flex-1\">\r\n                                                    <p className=\"text-sm font-bold text-foreground truncate\">{s.name}</p>\r\n                                                    <p className=\"text-xs text-muted-foreground font-mono truncate mt-1\">{s.sessionId}</p>\r\n                                                </div>\r\n                                                <div className={`flex items-center gap-1.5 text-xs font-medium px-2 py-1 rounded-full flex-shrink-0\r\n                                                    ${isConnected ? 'bg-emerald-50 text-emerald-700' : isDisconnected ? 'bg-red-50 text-red-600' : 'bg-amber-50 text-amber-600'}\r\n                                                `}>\r\n                                                    <span className={`h-1.5 w-1.5 rounded-full ${isConnected ? 'bg-emerald-500' : isDisconnected ? 'bg-red-400' : 'bg-amber-400'}`} />\r\n                                                    {s.status}\r\n                                                </div>\r\n                                            </div>\r\n                                        </CardContent>\r\n                                    </Card>\r\n                                </Link>\r\n                            );\r\n                        })}\r\n                    </div>\r\n                )}\r\n            </div>\r\n        </div>\r\n    );\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\dashboard\\scheduler\\page.tsx","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'error' is defined but never used.","line":78,"column":18,"nodeType":"Identifier","messageId":"unusedVar","endLine":78,"endColumn":23},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'error' is defined but never used.","line":144,"column":18,"nodeType":"Identifier","messageId":"unusedVar","endLine":144,"endColumn":23},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'error' is defined but never used.","line":159,"column":18,"nodeType":"Identifier","messageId":"unusedVar","endLine":159,"endColumn":23}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\"use client\";\r\n\r\nimport { useState, useEffect } from \"react\";\r\nimport { Card, CardContent, CardHeader, CardTitle } from \"@/components/ui/card\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { Input } from \"@/components/ui/input\";\r\nimport { Textarea } from \"@/components/ui/textarea\";\r\nimport { Label } from \"@/components/ui/label\";\r\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"@/components/ui/select\";\r\nimport { Trash2, Plus, CalendarClock, RefreshCw } from \"lucide-react\";\r\nimport { toast } from \"sonner\";\r\nimport {\r\n    AlertDialog,\r\n    AlertDialogAction,\r\n    AlertDialogCancel,\r\n    AlertDialogContent,\r\n    AlertDialogDescription,\r\n    AlertDialogFooter,\r\n    AlertDialogHeader,\r\n    AlertDialogTitle,\r\n} from \"@/components/ui/alert-dialog\";\r\nimport { SearchFilter } from \"@/components/dashboard/search-filter\";\r\nimport { useSession } from \"@/components/dashboard/session-provider\";\r\nimport { SessionGuard } from \"@/components/dashboard/session-guard\";\r\n\r\ninterface ScheduledMessage {\r\n    id: string;\r\n    jid: string;\r\n    content: string;\r\n    sendAt: string;\r\n    status: string;\r\n    mediaUrl?: string;\r\n    mediaType?: string;\r\n}\r\n\r\nexport default function SchedulerPage() {\r\n    const { sessionId: selectedSessionId } = useSession();\r\n\r\n    // ... rest of state\r\n    const [messages, setMessages] = useState<ScheduledMessage[]>([]);\r\n    const [loading, setLoading] = useState(false);\r\n    const [searchTerm, setSearchTerm] = useState(\"\");\r\n\r\n    // Form state ...\r\n    const [showForm, setShowForm] = useState(false);\r\n    const [newJid, setNewJid] = useState(\"\");\r\n    const [newContent, setNewContent] = useState(\"\");\r\n    const [newSendAt, setNewSendAt] = useState(\"\");\r\n    const [newMediaUrl, setNewMediaUrl] = useState(\"\");\r\n    const [newMediaType, setNewMediaType] = useState(\"image\");\r\n\r\n    // Delete state\r\n    const [deleteId, setDeleteId] = useState<string | null>(null);\r\n\r\n    // Edit state\r\n    const [editingId, setEditingId] = useState<string | null>(null);\r\n\r\n    // Remove local updateSession logic as it is handled by provider\r\n\r\n    useEffect(() => {\r\n        if (selectedSessionId) {\r\n            fetchMessages(selectedSessionId);\r\n        } else {\r\n            setMessages([]);\r\n        }\r\n    }, [selectedSessionId]);\r\n\r\n    const fetchMessages = async (sessionId: string) => {\r\n        setLoading(true);\r\n        try {\r\n            const res = await fetch(`/api/scheduler/${sessionId}`);\r\n            if (res.ok) {\r\n                const data = await res.json();\r\n                setMessages(data);\r\n            } else {\r\n                setMessages([]);\r\n            }\r\n        } catch (error) {\r\n            toast.error(\"Failed to fetch scheduled messages\");\r\n        } finally {\r\n            setLoading(false);\r\n        }\r\n    };\r\n\r\n    const handleEdit = (msg: ScheduledMessage) => {\r\n        setEditingId(msg.id);\r\n        const jidUser = msg.jid.split('@')[0];\r\n        setNewJid(jidUser);\r\n        setNewContent(msg.content);\r\n        setNewMediaUrl(msg.mediaUrl || \"\");\r\n        setNewMediaType(msg.mediaType || \"image\");\r\n        // Format date for datetime-local input (YYYY-MM-DDTHH:mm)\r\n        const date = new Date(msg.sendAt);\r\n        // Adjust to local ISO string roughly or use library. \r\n        // Simple manual format to avoid timezone issues with toISOString() which is UTC.\r\n        // This is a basic implementation.\r\n        const localIso = new Date(date.getTime() - (date.getTimezoneOffset() * 60000)).toISOString().slice(0, 16);\r\n        setNewSendAt(localIso);\r\n\r\n        setShowForm(true);\r\n    };\r\n\r\n    const handleSaveSchedule = async () => {\r\n        if (!selectedSessionId || !newJid || !newContent || !newSendAt) return;\r\n\r\n        // Append domain if missing\r\n        let jid = newJid;\r\n        if (!jid.includes(\"@\")) {\r\n            jid = jid + \"@s.whatsapp.net\"; // Default to private chat\r\n        }\r\n\r\n        try {\r\n            const url = editingId\r\n                ? `/api/scheduler/${selectedSessionId}/${editingId}`\r\n                : `/api/scheduler/${selectedSessionId}`;\r\n\r\n            const method = editingId ? \"PUT\" : \"POST\";\r\n\r\n            const res = await fetch(url, {\r\n                method,\r\n                headers: { \"Content-Type\": \"application/json\" },\r\n                body: JSON.stringify({\r\n                    jid,\r\n                    content: newContent,\r\n                    sendAt: newSendAt,\r\n                    mediaUrl: newMediaUrl,\r\n                    mediaType: newMediaType\r\n                })\r\n            });\r\n\r\n            if (res.ok) {\r\n                toast.success(editingId ? \"Schedule updated\" : \"Message scheduled\");\r\n                setShowForm(false);\r\n                setNewJid(\"\");\r\n                setNewContent(\"\");\r\n                setNewSendAt(\"\");\r\n                setNewMediaUrl(\"\");\r\n                setNewMediaType(\"image\");\r\n                setEditingId(null);\r\n                fetchMessages(selectedSessionId);\r\n            } else {\r\n                toast.error(editingId ? \"Failed to update schedule\" : \"Failed to schedule message\");\r\n            }\r\n        } catch (error) {\r\n            toast.error(\"An error occurred\");\r\n        }\r\n    };\r\n\r\n    const confirmDelete = async () => {\r\n        if (!deleteId) return;\r\n        try {\r\n            const res = await fetch(`/api/scheduler/${selectedSessionId}/${deleteId}`, { method: \"DELETE\" });\r\n            if (res.ok) {\r\n                toast.success(\"Schedule cancelled\");\r\n                setMessages(messages.filter(m => m.id !== deleteId));\r\n            } else {\r\n                toast.error(\"Failed to cancel schedule\");\r\n            }\r\n        } catch (error) {\r\n            toast.error(\"Failed to cancel schedule\");\r\n        } finally {\r\n            setDeleteId(null);\r\n        }\r\n    };\r\n\r\n    const filteredMessages = messages.filter(m =>\r\n        m.content.toLowerCase().includes(searchTerm.toLowerCase()) ||\r\n        m.jid.includes(searchTerm)\r\n    );\r\n\r\n    return (\r\n        <SessionGuard>\r\n            <div className=\"space-y-6\">\r\n                <div className=\"flex justify-between items-center\">\r\n                    <div>\r\n                        <h1 className=\"text-2xl font-bold flex items-center gap-2\">\r\n                            <CalendarClock className=\"h-6 w-6\" /> Scheduler\r\n                        </h1>\r\n                        <p className=\"text-muted-foreground\">\r\n                            {selectedSessionId ? \"Schedule messages for active session.\" : \"Select a session from the top bar.\"}\r\n                        </p>\r\n                    </div>\r\n\r\n                    <div className=\"flex items-center gap-2\">\r\n                        <Button variant=\"outline\" onClick={() => selectedSessionId && fetchMessages(selectedSessionId)} disabled={loading || !selectedSessionId}>\r\n                            <RefreshCw className={`h-4 w-4 mr-2 ${loading ? 'animate-spin' : ''}`} />\r\n                            Refresh\r\n                        </Button>\r\n                        <Button onClick={() => {\r\n                            setEditingId(null);\r\n                            setNewJid(\"\");\r\n                            setNewContent(\"\");\r\n                            setNewSendAt(\"\");\r\n                            setNewMediaUrl(\"\");\r\n                            setNewMediaType(\"image\");\r\n                            setShowForm(!showForm);\r\n                        }} disabled={!selectedSessionId}>\r\n                            <Plus className=\"h-4 w-4 mr-2\" /> Schedule Message\r\n                        </Button>\r\n                    </div>\r\n                </div>\r\n\r\n                <SearchFilter\r\n                    placeholder=\"Search schedules...\"\r\n                    onSearch={setSearchTerm}\r\n                />\r\n\r\n                {/* New/Edit Schedule Form */}\r\n                {showForm && (\r\n                    <Card className=\"border-2 border-primary/20\">\r\n                        <CardHeader>\r\n                            <CardTitle>{editingId ? \"Edit Scheduled Message\" : \"Schedule New Message\"}</CardTitle>\r\n                        </CardHeader>\r\n                        <CardContent className=\"space-y-4\">\r\n                            <div className=\"grid grid-cols-2 gap-4\">\r\n                                <div className=\"space-y-2\">\r\n                                    <Label>Recipient JID</Label>\r\n                                    <div className=\"flex gap-2\">\r\n                                        <Select onValueChange={(val) => {\r\n                                            if (val === \"GROUP\" && !newJid.endsWith(\"@g.us\")) setNewJid(newJid + \"@g.us\");\r\n                                            if (val === \"PRIVATE\" && !newJid.endsWith(\"@s.whatsapp.net\")) setNewJid(newJid + \"@s.whatsapp.net\");\r\n                                            if (val === \"NEWSLETTER\" && !newJid.endsWith(\"@newsletter\")) setNewJid(newJid + \"@newsletter\");\r\n                                        }}>\r\n                                            <SelectTrigger className=\"w-[120px]\">\r\n                                                <SelectValue placeholder=\"Type\" />\r\n                                            </SelectTrigger>\r\n                                            <SelectContent>\r\n                                                <SelectItem value=\"PRIVATE\">Private</SelectItem>\r\n                                                <SelectItem value=\"GROUP\">Group</SelectItem>\r\n                                                <SelectItem value=\"NEWSLETTER\">Channel</SelectItem>\r\n                                            </SelectContent>\r\n                                        </Select>\r\n                                        <Input\r\n                                            value={newJid}\r\n                                            onChange={e => setNewJid(e.target.value)}\r\n                                            placeholder=\"e.g. 62812345678@s.whatsapp.net\"\r\n                                            className=\"flex-1\"\r\n                                        />\r\n                                    </div>\r\n                                    <p className=\"text-xs text-muted-foreground\">Select type to auto-append suffix, or type full JID.</p>\r\n                                </div>\r\n                                <div className=\"space-y-2\">\r\n                                    <Label>Send At</Label>\r\n                                    <Input\r\n                                        type=\"datetime-local\"\r\n                                        value={newSendAt}\r\n                                        onChange={e => setNewSendAt(e.target.value)}\r\n                                    />\r\n                                </div>\r\n                            </div>\r\n                            <div className=\"space-y-2\">\r\n                                <Label>Message</Label>\r\n                                <Textarea\r\n                                    value={newContent}\r\n                                    onChange={e => setNewContent(e.target.value)}\r\n                                    placeholder=\"Hello there!\"\r\n                                    rows={4}\r\n                                />\r\n                            </div>\r\n\r\n                            <div className=\"grid grid-cols-2 gap-4\">\r\n                                <div className=\"space-y-2\">\r\n                                    <Label>Media URL (Optional)</Label>\r\n                                    <Input\r\n                                        value={newMediaUrl}\r\n                                        onChange={e => setNewMediaUrl(e.target.value)}\r\n                                        placeholder=\"https://example.com/image.jpg\"\r\n                                    />\r\n                                </div>\r\n                                <div className=\"space-y-2\">\r\n                                    <Label>Media Type</Label>\r\n                                    <Select value={newMediaType} onValueChange={setNewMediaType}>\r\n                                        <SelectTrigger>\r\n                                            <SelectValue />\r\n                                        </SelectTrigger>\r\n                                        <SelectContent>\r\n                                            <SelectItem value=\"image\">Image</SelectItem>\r\n                                            <SelectItem value=\"video\">Video</SelectItem>\r\n                                            <SelectItem value=\"document\">Document</SelectItem>\r\n                                        </SelectContent>\r\n                                    </Select>\r\n                                </div>\r\n                            </div>\r\n                            <div className=\"flex justify-end gap-2\">\r\n                                <Button variant=\"ghost\" onClick={() => {\r\n                                    setShowForm(false);\r\n                                    setEditingId(null);\r\n                                    setNewJid(\"\");\r\n                                    setNewContent(\"\");\r\n                                    setNewSendAt(\"\");\r\n                                    setNewMediaUrl(\"\");\r\n                                    setNewMediaType(\"image\");\r\n                                }}>Cancel</Button>\r\n                                <Button onClick={handleSaveSchedule}>{editingId ? \"Update\" : \"Schedule\"}</Button>\r\n                            </div>\r\n                        </CardContent>\r\n                    </Card>\r\n                )}\r\n\r\n                {/* Messages List */}\r\n                {loading ? (\r\n                    <div className=\"text-center p-8\">Loading...</div>\r\n                ) : filteredMessages.length === 0 ? (\r\n                    <div className=\"text-center p-8 text-muted-foreground border rounded-lg bg-slate-50\">\r\n                        {selectedSessionId ? \"No scheduled messages found matching criteria.\" : \"No session selected.\"}\r\n                    </div>\r\n                ) : (\r\n                    <div className=\"grid gap-4\">\r\n                        {filteredMessages.map(msg => (\r\n                            <Card key={msg.id} className={msg.status === 'SENT' ? 'opacity-70' : ''}>\r\n                                <CardContent className=\"flex justify-between items-center p-4\">\r\n                                    <div>\r\n                                        <div className=\"font-bold flex items-center gap-2\">\r\n                                            {msg.jid.split('@')[0]}\r\n                                            <span className={`text-xs px-2 py-0.5 rounded font-normal ${msg.status === 'PENDING' ? 'bg-yellow-100 text-yellow-800' :\r\n                                                msg.status === 'SENT' ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'\r\n                                                }`}>\r\n                                                {msg.status}\r\n                                            </span>\r\n                                        </div>\r\n                                        <div className=\"text-sm font-medium mt-1\">{msg.content}</div>\r\n                                        <div className=\"text-xs text-muted-foreground mt-1\">\r\n                                            Scheduled for: {new Date(msg.sendAt).toLocaleString()}\r\n                                        </div>\r\n                                    </div>\r\n                                    <div className=\"flex gap-2\">\r\n                                        <Button variant=\"ghost\" size=\"sm\" onClick={() => handleEdit(msg)} disabled={msg.status !== 'PENDING'}>\r\n                                            Edit\r\n                                        </Button>\r\n                                        <Button variant=\"ghost\" size=\"icon\" onClick={() => setDeleteId(msg.id)} className=\"text-destructive hover:text-destructive hover:bg-red-50\">\r\n                                            <Trash2 className=\"h-4 w-4\" />\r\n                                        </Button>\r\n                                    </div>\r\n                                </CardContent>\r\n                            </Card>\r\n                        ))}\r\n                    </div>\r\n                )}\r\n\r\n                <AlertDialog open={!!deleteId} onOpenChange={(open) => !open && setDeleteId(null)}>\r\n                    <AlertDialogContent>\r\n                        <AlertDialogHeader>\r\n                            <AlertDialogTitle>Cancel Schedule?</AlertDialogTitle>\r\n                            <AlertDialogDescription>\r\n                                This will permanently delete this scheduled message.\r\n                            </AlertDialogDescription>\r\n                        </AlertDialogHeader>\r\n                        <AlertDialogFooter>\r\n                            <AlertDialogCancel>Close</AlertDialogCancel>\r\n                            <AlertDialogAction onClick={confirmDelete} className=\"bg-red-600 hover:bg-red-700\">Delete</AlertDialogAction>\r\n                        </AlertDialogFooter>\r\n                    </AlertDialogContent>\r\n                </AlertDialog>\r\n            </div>\r\n        </SessionGuard>\r\n    );\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\dashboard\\sessions\\[sessionId]\\page.tsx","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'CardFooter' is defined but never used.","line":6,"column":69,"nodeType":"Identifier","messageId":"unusedVar","endLine":6,"endColumn":79,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"CardFooter"},"fix":{"range":[236,248],"text":""},"desc":"Remove unused variable \"CardFooter\"."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'Power' is defined but never used.","line":8,"column":54,"nodeType":"Identifier","messageId":"unusedVar","endLine":8,"endColumn":59,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"Power"},"fix":{"range":[365,372],"text":""},"desc":"Remove unused variable \"Power\"."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'QrCode' is defined but never used.","line":8,"column":69,"nodeType":"Identifier","messageId":"unusedVar","endLine":8,"endColumn":75,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"QrCode"},"fix":{"range":[380,388],"text":""},"desc":"Remove unused variable \"QrCode\"."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'socket' is assigned a value but never used.","line":46,"column":12,"nodeType":"Identifier","messageId":"unusedVar","endLine":46,"endColumn":18},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'fetchSession'. Either include it or remove the dependency array.","line":107,"column":8,"nodeType":"ArrayExpression","endLine":107,"endColumn":19,"suggestions":[{"desc":"Update the dependencies array to be: [fetchSession, sessionId]","fix":{"range":[3421,3432],"text":"[fetchSession, sessionId]"}}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":127,"column":25,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":127,"endColumn":28,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[4100,4103],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[4100,4103],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'e' is defined but never used.","line":143,"column":18,"nodeType":"Identifier","messageId":"unusedVar","endLine":143,"endColumn":19}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":6,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\"use client\";\r\n\r\nimport { useEffect, useState } from \"react\";\r\nimport { useParams, useRouter } from \"next/navigation\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { Card, CardContent, CardHeader, CardTitle, CardDescription, CardFooter } from \"@/components/ui/card\";\r\nimport { toast } from \"sonner\";\r\nimport { ArrowLeft, Play, Square, RotateCcw, LogOut, Power, Trash2, QrCode } from \"lucide-react\";\r\nimport Link from \"next/link\";\r\nimport { io, Socket } from \"socket.io-client\";\r\nimport { QRCodeSVG } from \"qrcode.react\";\r\nimport {\r\n    AlertDialog,\r\n    AlertDialogAction,\r\n    AlertDialogCancel,\r\n    AlertDialogContent,\r\n    AlertDialogDescription,\r\n    AlertDialogFooter,\r\n    AlertDialogHeader,\r\n    AlertDialogTitle,\r\n    AlertDialogTrigger,\r\n} from \"@/components/ui/alert-dialog\";\r\n\r\ntype SessionDetail = {\r\n    id: string;\r\n    name: string;\r\n    sessionId: string;\r\n    status: string;\r\n    userId: string;\r\n    uptime: number; // in seconds\r\n    me?: {\r\n        id: string;\r\n        name: string;\r\n    };\r\n    hasInstance: boolean;\r\n};\r\n\r\nexport default function SessionDetailPage() {\r\n    const params = useParams();\r\n    const router = useRouter();\r\n    const sessionId = params.sessionId as string;\r\n\r\n    const [session, setSession] = useState<SessionDetail | null>(null);\r\n    const [loading, setLoading] = useState(true);\r\n    const [qrCode, setQrCode] = useState<string | null>(null);\r\n    const [socket, setSocket] = useState<Socket | null>(null);\r\n    const [uptime, setUptime] = useState(0);\r\n\r\n    const fetchSession = async () => {\r\n        try {\r\n            const res = await fetch(`/api/sessions/${sessionId}`);\r\n            if (!res.ok) {\r\n                if (res.status === 404) {\r\n                    toast.error(\"Session not found\");\r\n                    router.push(\"/dashboard/sessions\");\r\n                    return;\r\n                }\r\n                throw new Error(\"Failed to fetch\");\r\n            }\r\n            const data = await res.json();\r\n            setSession(data);\r\n            setQrCode(data.qr || null);\r\n            setUptime(data.uptime || 0);\r\n        } catch (error) {\r\n            console.error(error);\r\n            toast.error(\"Failed to load session details\");\r\n        } finally {\r\n            setLoading(false);\r\n        }\r\n    };\r\n\r\n    useEffect(() => {\r\n        fetchSession();\r\n\r\n        const socketInstance = io({\r\n            path: \"/api/socket/io\",\r\n            addTrailingSlash: false,\r\n        });\r\n\r\n        socketInstance.on(\"connect\", () => {\r\n            console.log(\"Connected to socket\");\r\n            socketInstance.emit(\"join-session\", sessionId);\r\n        });\r\n\r\n        socketInstance.on(\"connection.update\", (data: { status: string, qr: string }) => {\r\n            console.log(\"Socket update:\", data);\r\n            setSession(prev => prev ? { ...prev, status: data.status } : null);\r\n            setQrCode(data.qr || null);\r\n\r\n            // Re-fetch full details on major status change (like connection) to get 'me' info\r\n            if (data.status === 'CONNECTED') {\r\n                fetchSession();\r\n            }\r\n        });\r\n\r\n        setSocket(socketInstance);\r\n\r\n        // Uptime counter\r\n        const interval = setInterval(() => {\r\n            setUptime(prev => prev + 1);\r\n        }, 1000);\r\n\r\n        return () => {\r\n            socketInstance.disconnect();\r\n            clearInterval(interval);\r\n        };\r\n    }, [sessionId]);\r\n\r\n    const performAction = async (action: string) => {\r\n        const loadingToast = toast.loading(` performing ${action}...`);\r\n        try {\r\n            const res = await fetch(`/api/sessions/${sessionId}/${action}`, {\r\n                method: \"POST\"\r\n            });\r\n            const data = await res.json();\r\n\r\n            if (!res.ok) throw new Error(data.error || \"Action failed\");\r\n\r\n            toast.success(data.message || \"Success\");\r\n\r\n            // Refresh logic\r\n            if (action === 'logout') {\r\n                setQrCode(null); // Will likely wait for scan-qr event\r\n            }\r\n            fetchSession();\r\n\r\n        } catch (error: any) {\r\n            toast.error(error.message);\r\n        } finally {\r\n            toast.dismiss(loadingToast);\r\n        }\r\n    };\r\n\r\n    const deleteSession = async () => {\r\n        try {\r\n            const res = await fetch(`/api/sessions/${sessionId}/settings`, { method: 'DELETE' });\r\n            if (res.ok) {\r\n                toast.success(\"Session deleted\");\r\n                router.push(\"/dashboard/sessions\");\r\n            } else {\r\n                toast.error(\"Failed to delete\");\r\n            }\r\n        } catch (e) {\r\n            toast.error(\"Error deleting session\");\r\n        }\r\n    };\r\n\r\n    const formatUptime = (seconds: number) => {\r\n        if (!session?.status || session.status !== \"CONNECTED\") return \"Offline\";\r\n        const d = Math.floor(seconds / (3600 * 24));\r\n        const h = Math.floor((seconds % (3600 * 24)) / 3600);\r\n        const m = Math.floor((seconds % 3600) / 60);\r\n        const s = Math.floor(seconds % 60);\r\n        return `${d}d ${h}h ${m}m ${s}s`;\r\n    };\r\n\r\n    if (loading) return <div className=\"p-8\">Loading...</div>;\r\n    if (!session) return <div className=\"p-8\">Session not found</div>;\r\n\r\n    return (\r\n        <div className=\"max-w-4xl mx-auto space-y-6\">\r\n            <div className=\"flex items-center space-x-4 mb-6\">\r\n                <Button variant=\"ghost\" asChild>\r\n                    <Link href=\"/dashboard/sessions\">\r\n                        <ArrowLeft className=\"mr-2 h-4 w-4\" /> Back to Sessions\r\n                    </Link>\r\n                </Button>\r\n                <h1 className=\"text-2xl font-bold\">{session.name} <span className=\"text-gray-400 font-normal text-sm\">({session.sessionId})</span></h1>\r\n            </div>\r\n\r\n            <div className=\"grid grid-cols-1 md:grid-cols-3 gap-6\">\r\n                {/* Status Card */}\r\n                <Card className=\"md:col-span-2\">\r\n                    <CardHeader>\r\n                        <CardTitle className=\"flex items-center justify-between\">\r\n                            Session Status\r\n                            <div className={`px-3 py-1 rounded-full text-xs font-bold ${session.status === 'CONNECTED' ? 'bg-green-100 text-green-700' :\r\n                                session.status === 'STOPPED' ? 'bg-red-100 text-red-700' :\r\n                                    'bg-yellow-100 text-yellow-700'\r\n                                }`}>\r\n                                {session.status}\r\n                            </div>\r\n                        </CardTitle>\r\n                        <CardDescription>Real-time connection status and uptime.</CardDescription>\r\n                    </CardHeader>\r\n                    <CardContent className=\"space-y-4\">\r\n                        <div className=\"grid grid-cols-2 gap-4\">\r\n                            <div className=\"p-4 bg-gray-50 rounded-lg\">\r\n                                <span className=\"text-sm text-gray-500 block\">Uptime</span>\r\n                                <span className=\"text-xl font-mono font-medium\">{formatUptime(uptime)}</span>\r\n                            </div>\r\n                            <div className=\"p-4 bg-gray-50 rounded-lg\">\r\n                                <span className=\"text-sm text-gray-500 block\">Connected As</span>\r\n                                <span className=\"text-lg font-medium truncate\">{session.me?.name || session.me?.id || \"-\"}</span>\r\n                            </div>\r\n                        </div>\r\n\r\n                        {qrCode && (\r\n                            <div className=\"flex flex-col items-center justify-center p-6 border-2 border-dashed rounded-lg bg-white\">\r\n                                <QRCodeSVG value={qrCode} size={256} />\r\n                                <p className=\"mt-4 text-sm text-gray-500 animate-pulse\">Scan with WhatsApp to connect</p>\r\n                            </div>\r\n                        )}\r\n                    </CardContent>\r\n                </Card>\r\n\r\n                {/* Actions Panel */}\r\n                <Card>\r\n                    <CardHeader>\r\n                        <CardTitle>Controls</CardTitle>\r\n                        <CardDescription>Manage the active session.</CardDescription>\r\n                    </CardHeader>\r\n                    <CardContent className=\"space-y-3\">\r\n                        <Button\r\n                            variant=\"outline\"\r\n                            className=\"w-full justify-start text-green-600 hover:text-green-700 hover:bg-green-50\"\r\n                            onClick={() => performAction('start')}\r\n                            disabled={session.status === 'CONNECTED' || session.status === 'SCAN_QR'}\r\n                        >\r\n                            <Play className=\"mr-2 h-4 w-4\" /> Start Session\r\n                        </Button>\r\n\r\n                        <Button\r\n                            variant=\"outline\"\r\n                            className=\"w-full justify-start text-orange-600 hover:text-orange-700 hover:bg-orange-50\"\r\n                            onClick={() => performAction('restart')}\r\n                            disabled={!session.hasInstance && session.status !== 'CONNECTED'}\r\n                        >\r\n                            <RotateCcw className=\"mr-2 h-4 w-4\" /> Restart Session\r\n                        </Button>\r\n\r\n                        <Button\r\n                            variant=\"outline\"\r\n                            className=\"w-full justify-start text-red-600 hover:text-red-700 hover:bg-red-50\"\r\n                            onClick={() => performAction('stop')}\r\n                            disabled={session.status === 'STOPPED'}\r\n                        >\r\n                            <Square className=\"mr-2 h-4 w-4\" /> Stop Session\r\n                        </Button>\r\n\r\n                        <div className=\"border-t my-4 pt-4 space-y-3\">\r\n                            <Button\r\n                                variant=\"outline\"\r\n                                className=\"w-full justify-start\"\r\n                                onClick={() => performAction('logout')}\r\n                                disabled={session.status !== 'CONNECTED'}\r\n                            >\r\n                                <LogOut className=\"mr-2 h-4 w-4\" /> Logout\r\n                            </Button>\r\n\r\n                            <AlertDialog>\r\n                                <AlertDialogTrigger asChild>\r\n                                    <Button\r\n                                        variant=\"destructive\"\r\n                                        className=\"w-full justify-start\"\r\n                                    >\r\n                                        <Trash2 className=\"mr-2 h-4 w-4\" /> Delete Session\r\n                                    </Button>\r\n                                </AlertDialogTrigger>\r\n                                <AlertDialogContent>\r\n                                    <AlertDialogHeader>\r\n                                        <AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>\r\n                                        <AlertDialogDescription>\r\n                                            This action cannot be undone. This will permanently delete the session\r\n                                            and remove your connection data from the server.\r\n                                        </AlertDialogDescription>\r\n                                    </AlertDialogHeader>\r\n                                    <AlertDialogFooter>\r\n                                        <AlertDialogCancel>Cancel</AlertDialogCancel>\r\n                                        <AlertDialogAction onClick={deleteSession} className=\"bg-red-600 hover:bg-red-700\">\r\n                                            Delete\r\n                                        </AlertDialogAction>\r\n                                    </AlertDialogFooter>\r\n                                </AlertDialogContent>\r\n                            </AlertDialog>\r\n                        </div>\r\n                    </CardContent>\r\n                </Card>\r\n            </div>\r\n        </div>\r\n    );\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\dashboard\\sessions\\page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\dashboard\\settings\\page.tsx","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":16,"column":48,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":16,"endColumn":51,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[734,737],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[734,737],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":16,"column":101,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":16,"endColumn":104,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[787,790],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[787,790],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'e' is defined but never used.","line":252,"column":38,"nodeType":"Identifier","messageId":"unusedVar","endLine":252,"endColumn":39}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\"use client\";\r\n\r\nimport { useState, useEffect } from \"react\";\r\nimport { useSession as useSessionProvider } from \"@/components/dashboard/session-provider\";\r\nimport { useSession } from \"next-auth/react\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { Card, CardContent, CardHeader, CardTitle, CardDescription } from \"@/components/ui/card\";\r\nimport { Switch } from \"@/components/ui/switch\";\r\nimport { Label } from \"@/components/ui/label\";\r\nimport { RefreshCw, Save, AlertCircle } from \"lucide-react\";\r\nimport { toast } from \"sonner\";\r\n\r\nexport default function SettingsPage() {\r\n    const { data: authSession } = useSession();\r\n    const { sessionId } = useSessionProvider();\r\n    const isSuperAdmin = (authSession?.user as any)?.role === \"SUPERADMIN\" || (authSession?.user as any)?.role === \"OWNER\";\r\n\r\n    const [config, setConfig] = useState({\r\n        ghostMode: false,\r\n        antiDelete: false,\r\n        readReceipts: true,\r\n    });\r\n    const [loading, setLoading] = useState(false);\r\n\r\n    const [systemConfig, setSystemConfig] = useState({\r\n        appName: \"WA-AKG\",\r\n        logoUrl: \"\",\r\n        timezone: \"Asia/Jakarta\",\r\n        enableRegistration: true\r\n    });\r\n    const [systemLoading, setSystemLoading] = useState(false);\r\n\r\n    const [botConfig, setBotConfig] = useState({\r\n        botName: \"WA-AKG Bot\",\r\n        enableSticker: true,\r\n        enableVideoSticker: true,\r\n        maxStickerDuration: 10,\r\n        enablePing: true,\r\n        enableUptime: true,\r\n        removeBgApiKey: \"\",\r\n        botMode: \"OWNER\",\r\n        autoReplyMode: \"ALL\"\r\n    });\r\n    const [botLoading, setBotLoading] = useState(false);\r\n\r\n    useEffect(() => {\r\n        // Fetch System Config\r\n        fetch('/api/settings/system').then(r => r.json()).then(data => {\r\n            if (data && !data.error) {\r\n                setSystemConfig({\r\n                    appName: data.appName || \"WA-AKG\",\r\n                    logoUrl: data.logoUrl || \"\",\r\n                    timezone: data.timezone || \"Asia/Jakarta\",\r\n                    enableRegistration: data.enableRegistration !== undefined ? data.enableRegistration : true\r\n                });\r\n            }\r\n        });\r\n    }, []);\r\n\r\n    // Fetch Session and Bot Config\r\n    useEffect(() => {\r\n        if (!sessionId) return;\r\n        fetch(`/api/sessions/${sessionId}/settings`)\r\n            .then(res => res.json())\r\n            .then(data => {\r\n                if (data && !data.error) {\r\n                    setConfig({\r\n                        ghostMode: data.config?.ghostMode || false,\r\n                        antiDelete: data.config?.antiDelete || false,\r\n                        readReceipts: data.config?.readReceipts ?? true\r\n                    });\r\n                }\r\n            });\r\n\r\n        fetch(`/api/sessions/${sessionId}/bot-config`)\r\n            .then(res => res.json())\r\n            .then(data => {\r\n                if (data && !data.error) {\r\n                    setBotConfig(prev => ({ ...prev, ...data, removeBgApiKey: data.removeBgApiKey || \"\" }));\r\n                }\r\n            });\r\n    }, [sessionId]);\r\n\r\n    const handleSaveSystem = async () => {\r\n        setSystemLoading(true);\r\n        try {\r\n            const res = await fetch('/api/settings/system', {\r\n                method: \"POST\",\r\n                headers: { \"Content-Type\": \"application/json\" },\r\n                body: JSON.stringify(systemConfig)\r\n            });\r\n\r\n            if (res.ok) {\r\n                toast.success(\"System settings updated. Refresh to see changes.\");\r\n            } else {\r\n                toast.error(\"Failed to update system settings\");\r\n            }\r\n        } catch (e) {\r\n            console.error(e);\r\n            toast.error(\"Error saving system settings\");\r\n        } finally {\r\n            setSystemLoading(false);\r\n        }\r\n    };\r\n\r\n    const handleSaveBot = async () => {\r\n        if (!sessionId) return;\r\n        setBotLoading(true);\r\n        try {\r\n            const res = await fetch(`/api/sessions/${sessionId}/bot-config`, {\r\n                method: \"POST\",\r\n                headers: { \"Content-Type\": \"application/json\" },\r\n                body: JSON.stringify(botConfig)\r\n            });\r\n            if (res.ok) {\r\n                toast.success(\"Bot settings saved successfully\");\r\n            } else {\r\n                toast.error(\"Failed to save bot settings\");\r\n            }\r\n        } catch (e) {\r\n            console.error(e);\r\n            toast.error(\"Error saving bot settings\");\r\n        } finally {\r\n            setBotLoading(false);\r\n        }\r\n    };\r\n\r\n    const handleSave = async () => {\r\n        if (!sessionId) return;\r\n        setLoading(true);\r\n        try {\r\n            const res = await fetch(`/api/sessions/${sessionId}/settings`, {\r\n                method: \"PATCH\",\r\n                body: JSON.stringify({ config })\r\n            });\r\n            if (res.ok) {\r\n                toast.success(\"Settings saved successfully\");\r\n            } else {\r\n                toast.error(\"Failed to save settings\");\r\n            }\r\n        } catch (e) {\r\n            console.error(e);\r\n            toast.error(\"Error saving settings\");\r\n        } finally {\r\n            setLoading(false);\r\n        }\r\n    }\r\n\r\n    return (\r\n        <div className=\"space-y-6\">\r\n            <div className=\"flex justify-between items-center\">\r\n                <h2 className=\"text-3xl font-bold tracking-tight\">Settings</h2>\r\n            </div>\r\n\r\n            {!isSuperAdmin && (\r\n                <Card className=\"border-yellow-200 bg-yellow-50\">\r\n                    <CardContent className=\"pt-6\">\r\n                        <div className=\"flex items-start gap-3\">\r\n                            <AlertCircle className=\"h-5 w-5 text-yellow-600 mt-0.5\" />\r\n                            <div>\r\n                                <p className=\"text-sm font-medium text-yellow-900\">View Only Mode</p>\r\n                                <p className=\"text-xs text-yellow-700 mt-1\">\r\n                                    Only Superadmins can modify system settings. You can view current settings but cannot make changes.\r\n                                </p>\r\n                            </div>\r\n                        </div>\r\n                    </CardContent>\r\n                </Card>\r\n            )}\r\n\r\n            {/* System Configuration (Global) */}\r\n            <Card className=\"border-primary/20 bg-primary/5\">\r\n                <CardHeader>\r\n                    <CardTitle className=\"text-xl\">App Configuration</CardTitle>\r\n                    <CardDescription>Global settings for the application branding.</CardDescription>\r\n                </CardHeader>\r\n                <CardContent className=\"space-y-4\">\r\n                    <div className=\"grid gap-2\">\r\n                        <Label>Application Name</Label>\r\n                        <div className=\"flex gap-2\">\r\n                            <input\r\n                                className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50\"\r\n                                placeholder=\"WA-AKG\"\r\n                                value={systemConfig.appName}\r\n                                onChange={(e) => setSystemConfig(prev => ({ ...prev, appName: e.target.value }))}\r\n                                disabled={!isSuperAdmin}\r\n                            />\r\n                        </div>\r\n                        <p className=\"text-xs text-muted-foreground\">Changes the name in the sidebar and browser title.</p>\r\n                    </div>\r\n\r\n                    <div className=\"grid gap-2\">\r\n                        <Label>Timezone</Label>\r\n                        <div className=\"flex gap-2\">\r\n                            <select\r\n                                className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50\"\r\n                                value={systemConfig.timezone}\r\n                                onChange={(e) => setSystemConfig(prev => ({ ...prev, timezone: e.target.value }))}\r\n                                disabled={!isSuperAdmin}\r\n                            >\r\n                                <option value=\"Asia/Jakarta\">Asia/Jakarta (WIB)</option>\r\n                                <option value=\"Asia/Makassar\">Asia/Makassar (WITA)</option>\r\n                                <option value=\"Asia/Jayapura\">Asia/Jayapura (WIT)</option>\r\n                                <option value=\"UTC\">UTC</option>\r\n                            </select>\r\n                        </div>\r\n                        <p className=\"text-xs text-muted-foreground\">Scheduler will use this timezone to parse local times.</p>\r\n                    </div>\r\n\r\n                    <div className=\"flex items-center justify-between space-x-2 pt-2 border-t border-border/50\">\r\n                        <Label htmlFor=\"enable-registration\" className=\"flex flex-col space-y-1\">\r\n                            <span>Enable User Registration</span>\r\n                            <span className=\"font-normal text-xs text-muted-foreground\">Allow new users to sign up for accounts. Turn off to keep the platform private.</span>\r\n                        </Label>\r\n                        <Switch\r\n                            id=\"enable-registration\"\r\n                            checked={systemConfig.enableRegistration}\r\n                            onCheckedChange={c => setSystemConfig(prev => ({ ...prev, enableRegistration: c }))}\r\n                            disabled={!isSuperAdmin}\r\n                        />\r\n                    </div>\r\n\r\n                    <div className=\"pt-2\">\r\n                        <Button onClick={handleSaveSystem} disabled={systemLoading || !isSuperAdmin}>\r\n                            {systemLoading ? <RefreshCw className=\"h-4 w-4 animate-spin mr-2\" /> : <Save className=\"h-4 w-4 mr-2\" />}\r\n                            Save Configuration\r\n                        </Button>\r\n                    </div>\r\n                </CardContent>\r\n            </Card>\r\n\r\n            {/* System Updates */}\r\n            <Card>\r\n                <CardHeader>\r\n                    <CardTitle>System Updates</CardTitle>\r\n                    <CardDescription>Check for the latest version from GitHub.</CardDescription>\r\n                </CardHeader>\r\n                <CardContent>\r\n                    <Button\r\n                        variant=\"outline\"\r\n                        className=\"w-full\"\r\n                        onClick={async () => {\r\n                            setSystemLoading(true);\r\n                            try {\r\n                                const res = await fetch(\"/api/system/check-updates\", { method: \"POST\" });\r\n                                const data = await res.json();\r\n                                if (data.success) {\r\n                                    toast.success(data.message || \"Check complete!\");\r\n                                } else {\r\n                                    toast.error(data.message || \"Failed to check updates\");\r\n                                }\r\n                            } catch (e) {\r\n                                toast.error(\"Error checking updates\");\r\n                            } finally {\r\n                                setSystemLoading(false);\r\n                            }\r\n                        }}\r\n                        disabled={systemLoading}\r\n                    >\r\n                        <RefreshCw className={`mr-2 h-4 w-4 ${systemLoading ? 'animate-spin' : ''}`} />\r\n                        Check for Updates\r\n                    </Button>\r\n                </CardContent>\r\n            </Card>\r\n\r\n            {/* Session Selected Gateway */}\r\n            {!sessionId ? (\r\n                <Card className=\"border-dashed border-2 bg-background/50\">\r\n                    <CardContent className=\"flex flex-col items-center justify-center py-12 text-center\">\r\n                        <div className=\"h-12 w-12 rounded-full bg-primary/10 flex items-center justify-center mb-4\">\r\n                            <AlertCircle className=\"h-6 w-6 text-primary\" />\r\n                        </div>\r\n                        <h3 className=\"text-lg font-semibold text-foreground\">No Session Selected</h3>\r\n                        <p className=\"text-sm text-muted-foreground mt-1 max-w-sm\">\r\n                            Please select an active WhatsApp session from the navigation bar above to configure its Bot, Auto Reply, and Privacy settings.\r\n                        </p>\r\n                    </CardContent>\r\n                </Card>\r\n            ) : (\r\n                <>\r\n                    {/* Bot & Auto Reply Configuration (Per Session) */}\r\n                    <Card>\r\n                        <CardHeader>\r\n                            <CardTitle>Bot & Auto Reply Configuration</CardTitle>\r\n                            <CardDescription>Manage automated features and commands for this session.</CardDescription>\r\n                        </CardHeader>\r\n                        <CardContent className=\"space-y-6\">\r\n                            <div className=\"grid gap-2\">\r\n                                <Label>Bot Name</Label>\r\n                                <input\r\n                                    className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50\"\r\n                                    placeholder=\"WA-AKG Bot\"\r\n                                    value={botConfig.botName}\r\n                                    onChange={(e) => setBotConfig(prev => ({ ...prev, botName: e.target.value }))}\r\n                                />\r\n                                <p className=\"text-xs text-muted-foreground\">The display name used by the bot in automated responses.</p>\r\n                            </div>\r\n\r\n                            <div className=\"grid sm:grid-cols-2 gap-4 pt-2\">\r\n                                <div className=\"flex items-center justify-between space-x-2 border p-3 rounded-lg\">\r\n                                    <Label htmlFor=\"enable-ping\" className=\"flex flex-col space-y-1\">\r\n                                        <span>Ping Command</span>\r\n                                        <span className=\"font-normal text-xs text-muted-foreground\">Respond to /ping</span>\r\n                                    </Label>\r\n                                    <Switch\r\n                                        id=\"enable-ping\"\r\n                                        checked={botConfig.enablePing}\r\n                                        onCheckedChange={c => setBotConfig(prev => ({ ...prev, enablePing: c }))}\r\n                                    />\r\n                                </div>\r\n                                <div className=\"flex items-center justify-between space-x-2 border p-3 rounded-lg\">\r\n                                    <Label htmlFor=\"enable-uptime\" className=\"flex flex-col space-y-1\">\r\n                                        <span>Uptime Command</span>\r\n                                        <span className=\"font-normal text-xs text-muted-foreground\">Respond to /uptime</span>\r\n                                    </Label>\r\n                                    <Switch\r\n                                        id=\"enable-uptime\"\r\n                                        checked={botConfig.enableUptime}\r\n                                        onCheckedChange={c => setBotConfig(prev => ({ ...prev, enableUptime: c }))}\r\n                                    />\r\n                                </div>\r\n                            </div>\r\n\r\n                            <div className=\"grid sm:grid-cols-2 gap-4\">\r\n                                <div className=\"flex items-center justify-between space-x-2 border p-3 rounded-lg\">\r\n                                    <Label htmlFor=\"enable-sticker\" className=\"flex flex-col space-y-1\">\r\n                                        <span>Image to Sticker</span>\r\n                                        <span className=\"font-normal text-xs text-muted-foreground\">Auto-convert images</span>\r\n                                    </Label>\r\n                                    <Switch\r\n                                        id=\"enable-sticker\"\r\n                                        checked={botConfig.enableSticker}\r\n                                        onCheckedChange={c => setBotConfig(prev => ({ ...prev, enableSticker: c }))}\r\n                                    />\r\n                                </div>\r\n                                <div className=\"flex items-center justify-between space-x-2 border p-3 rounded-lg\">\r\n                                    <Label htmlFor=\"enable-video-sticker\" className=\"flex flex-col space-y-1\">\r\n                                        <span>Video to Sticker</span>\r\n                                        <span className=\"font-normal text-xs text-muted-foreground\">Auto-convert short videos</span>\r\n                                    </Label>\r\n                                    <Switch\r\n                                        id=\"enable-video-sticker\"\r\n                                        checked={botConfig.enableVideoSticker}\r\n                                        onCheckedChange={c => setBotConfig(prev => ({ ...prev, enableVideoSticker: c }))}\r\n                                    />\r\n                                </div>\r\n                            </div>\r\n\r\n                            <div className=\"grid gap-2 border-t pt-4 border-border/50\">\r\n                                <Label>Remove.bg API Key (Optional)</Label>\r\n                                <input\r\n                                    type=\"password\"\r\n                                    className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50\"\r\n                                    placeholder=\"Enter your Remove.bg API Key\"\r\n                                    value={botConfig.removeBgApiKey || \"\"}\r\n                                    onChange={(e) => setBotConfig(prev => ({ ...prev, removeBgApiKey: e.target.value }))}\r\n                                />\r\n                                <p className=\"text-xs text-muted-foreground\">Enables background removal for stickers (e.g. /sticker nocrop).</p>\r\n                            </div>\r\n\r\n                            <div className=\"pt-2\">\r\n                                <Button onClick={handleSaveBot} disabled={botLoading || !sessionId}>\r\n                                    {botLoading ? <RefreshCw className=\"mr-2 h-4 w-4 animate-spin\" /> : <Save className=\"mr-2 h-4 w-4\" />}\r\n                                    Save Bot Configuration\r\n                                </Button>\r\n                            </div>\r\n                        </CardContent>\r\n                    </Card>\r\n\r\n                    <Card>\r\n                        <CardHeader>\r\n                            <CardTitle>Privacy & Utility</CardTitle>\r\n                            <CardDescription>Configure ghost mode and other features for your active session.</CardDescription>\r\n                        </CardHeader>\r\n                        <CardContent className=\"space-y-6\">\r\n                            <div className=\"flex items-center justify-between space-x-2\">\r\n                                <Label htmlFor=\"ghost-mode\" className=\"flex flex-col space-y-1\">\r\n                                    <span>Ghost Mode</span>\r\n                                    <span className=\"font-normal text-xs text-muted-foreground\">View status and read messages without sending blue ticks.</span>\r\n                                </Label>\r\n                                <Switch\r\n                                    id=\"ghost-mode\"\r\n                                    checked={config.ghostMode}\r\n                                    onCheckedChange={c => setConfig({ ...config, ghostMode: c })}\r\n                                />\r\n                            </div>\r\n\r\n                            <div className=\"flex items-center justify-between space-x-2\">\r\n                                <Label htmlFor=\"anti-delete\" className=\"flex flex-col space-y-1\">\r\n                                    <span>Anti-Delete</span>\r\n                                    <span className=\"font-normal text-xs text-muted-foreground\">Keep messages even if the sender deletes them for everyone.</span>\r\n                                </Label>\r\n                                <Switch\r\n                                    id=\"anti-delete\"\r\n                                    checked={config.antiDelete}\r\n                                    onCheckedChange={c => setConfig({ ...config, antiDelete: c })}\r\n                                />\r\n                            </div>\r\n\r\n                            <div className=\"pt-4\">\r\n                                <Button onClick={handleSave} disabled={loading || !sessionId}>\r\n                                    <Save className=\"mr-2 h-4 w-4\" /> Save Configuration\r\n                                </Button>\r\n                            </div>\r\n                        </CardContent>\r\n                    </Card>\r\n                </>\r\n            )}\r\n        </div>\r\n    );\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\dashboard\\sticker\\page.tsx","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'useEffect' is defined but never used.","line":3,"column":20,"nodeType":"Identifier","messageId":"unusedVar","endLine":3,"endColumn":29,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"useEffect"},"fix":{"range":[34,45],"text":""},"desc":"Remove unused variable \"useEffect\"."}]},{"ruleId":"prefer-const","severity":2,"message":"'jid' is never reassigned. Use 'const' instead.","line":39,"column":13,"nodeType":"Identifier","messageId":"useConst","endLine":39,"endColumn":16,"fix":{"range":[1515,1584],"text":"const jid = target.includes('@') ? target : `${target}@s.whatsapp.net`;"}},{"ruleId":"@next/next/no-img-element","severity":1,"message":"Using `<img>` could result in slower LCP and higher bandwidth. Consider using `<Image />` from `next/image` or a custom image loader to automatically optimize images. This may incur additional usage or cost from your provider. See: https://nextjs.org/docs/messages/no-img-element","line":165,"column":37,"nodeType":"JSXOpeningElement","endLine":165,"endColumn":188}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":1,"fixableWarningCount":0,"source":"\"use client\";\r\n\r\nimport { useState, useEffect } from \"react\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { Input } from \"@/components/ui/input\";\r\nimport { Label } from \"@/components/ui/label\";\r\nimport { Card, CardContent, CardHeader, CardTitle, CardDescription } from \"@/components/ui/card\";\r\nimport { RefreshCw, Send, Image as ImageIcon } from \"lucide-react\";\r\nimport { toast } from \"sonner\";\r\n\r\nimport { useSession } from \"@/components/dashboard/session-provider\";\r\nimport { SessionGuard } from \"@/components/dashboard/session-guard\";\r\n\r\nexport default function StickerPage() {\r\n    const { sessionId } = useSession();\r\n    const [target, setTarget] = useState(\"\");\r\n    const [file, setFile] = useState<File | null>(null);\r\n    const [preview, setPreview] = useState<string | null>(null);\r\n    const [loading, setLoading] = useState(false);\r\n\r\n    // Advanced options\r\n    const [pack, setPack] = useState(\"WA-AKG\");\r\n    const [author, setAuthor] = useState(\"User\");\r\n    const [quality, setQuality] = useState(50);\r\n    const [type, setType] = useState(\"full\");\r\n    const [showAdvanced, setShowAdvanced] = useState(false);\r\n\r\n    const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {\r\n        const f = e.target.files?.[0];\r\n        if (f) {\r\n            setFile(f);\r\n            setPreview(URL.createObjectURL(f));\r\n        }\r\n    };\r\n\r\n    const handleSend = async () => {\r\n        if (!sessionId || !target || !file) return toast.error(\"Please fill all fields\");\r\n\r\n        let jid = target.includes('@') ? target : `${target}@s.whatsapp.net`;\r\n        const encodedJid = encodeURIComponent(jid);\r\n\r\n        setLoading(true);\r\n        try {\r\n            const formData = new FormData();\r\n            formData.append(\"file\", file);\r\n            formData.append(\"pack\", pack);\r\n            formData.append(\"author\", author);\r\n            formData.append(\"quality\", quality.toString());\r\n            formData.append(\"type\", type);\r\n\r\n            const res = await fetch(`/api/messages/${sessionId}/${encodedJid}/sticker`, {\r\n                method: \"POST\",\r\n                body: formData\r\n            });\r\n\r\n            if (res.ok) {\r\n                toast.success(\"Sticker sent!\");\r\n                setFile(null);\r\n                setPreview(null);\r\n                setTarget(\"\");\r\n            } else {\r\n                const err = await res.json();\r\n                toast.error(err.error || \"Failed to send sticker\");\r\n            }\r\n        } catch (e) {\r\n            console.error(e);\r\n            toast.error(\"Error sending sticker\");\r\n        } finally {\r\n            setLoading(false);\r\n        }\r\n    };\r\n\r\n    return (\r\n        <SessionGuard>\r\n            <div className=\"space-y-6\">\r\n                <div className=\"flex justify-between items-center\">\r\n                    <h2 className=\"text-3xl font-bold tracking-tight\">Sticker Maker</h2>\r\n                </div>\r\n\r\n                <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\r\n                    <Card>\r\n                        <CardHeader>\r\n                            <CardTitle>Create Configuration</CardTitle>\r\n                            <CardDescription>Upload an image and configure sticker meta.</CardDescription>\r\n                        </CardHeader>\r\n                        <CardContent className=\"space-y-4\">\r\n                            <div className=\"space-y-2\">\r\n                                <Label>Target Number</Label>\r\n                                <Input\r\n                                    placeholder=\"628123456789\"\r\n                                    value={target}\r\n                                    onChange={e => setTarget(e.target.value)}\r\n                                />\r\n                            </div>\r\n\r\n                            <div className=\"space-y-2\">\r\n                                <Label>Image File</Label>\r\n                                <div className=\"flex items-center justify-center w-full\">\r\n                                    <label htmlFor=\"dropzone-file\" className=\"flex flex-col items-center justify-center w-full h-32 border-2 border-dashed rounded-lg cursor-pointer bg-slate-50 hover:bg-slate-100\">\r\n                                        <div className=\"flex flex-col items-center justify-center pt-5 pb-6\">\r\n                                            <ImageIcon className=\"w-8 h-8 mb-2 text-gray-500\" />\r\n                                            <p className=\"text-sm text-gray-500\"><span className=\"font-semibold\">Click to upload</span> or drag and drop</p>\r\n                                        </div>\r\n                                        <input id=\"dropzone-file\" type=\"file\" className=\"hidden\" accept=\"image/*\" onChange={handleFileChange} />\r\n                                    </label>\r\n                                </div>\r\n                            </div>\r\n\r\n                            <div className=\"pt-2\">\r\n                                <Button variant=\"ghost\" size=\"sm\" onClick={() => setShowAdvanced(!showAdvanced)} className=\"w-full\">\r\n                                    {showAdvanced ? \"Hide Advanced Options\" : \"Show Advanced Options\"}\r\n                                </Button>\r\n                            </div>\r\n\r\n                            {showAdvanced && (\r\n                                <div className=\"space-y-4 border p-4 rounded-md bg-slate-50\">\r\n                                    <div className=\"grid grid-cols-2 gap-4\">\r\n                                        <div className=\"space-y-2\">\r\n                                            <Label>Pack Name</Label>\r\n                                            <Input value={pack} onChange={e => setPack(e.target.value)} />\r\n                                        </div>\r\n                                        <div className=\"space-y-2\">\r\n                                            <Label>Author</Label>\r\n                                            <Input value={author} onChange={e => setAuthor(e.target.value)} />\r\n                                        </div>\r\n                                    </div>\r\n                                    <div className=\"grid grid-cols-2 gap-4\">\r\n                                        <div className=\"space-y-2\">\r\n                                            <Label>Quality (1-100)</Label>\r\n                                            <Input type=\"number\" min={1} max={100} value={quality} onChange={e => setQuality(parseInt(e.target.value))} />\r\n                                        </div>\r\n                                        <div className=\"space-y-2\">\r\n                                            <Label>Type</Label>\r\n                                            <select\r\n                                                className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50\"\r\n                                                value={type}\r\n                                                onChange={e => setType(e.target.value)}\r\n                                            >\r\n                                                <option value=\"full\">Full</option>\r\n                                                <option value=\"crop\">Crop</option>\r\n                                                <option value=\"circle\">Circle</option>\r\n                                            </select>\r\n                                        </div>\r\n                                    </div>\r\n                                </div>\r\n                            )}\r\n\r\n                            <div className=\"pt-2\">\r\n                                <Button className=\"w-full\" onClick={handleSend} disabled={loading || !sessionId || !file}>\r\n                                    {loading ? <RefreshCw className=\"mr-2 h-4 w-4 animate-spin\" /> : <Send className=\"mr-2 h-4 w-4\" />}\r\n                                    Send Sticker\r\n                                </Button>\r\n                            </div>\r\n                        </CardContent>\r\n                    </Card>\r\n\r\n                    <Card>\r\n                        <CardHeader>\r\n                            <CardTitle>Preview</CardTitle>\r\n                            <CardDescription>This is how your image looks.</CardDescription>\r\n                        </CardHeader>\r\n                        <CardContent className=\"flex flex-col items-center justify-center h-[300px] bg-slate-100/50 rounded-lg m-6 mt-0\">\r\n                            {preview ? (\r\n                                <div className=\"relative w-64 h-64 flex items-center justify-center\">\r\n                                    <img src={preview} alt=\"Preview\" className={`max-w-full max-h-full object-contain shadow-lg ${type === 'circle' ? 'rounded-full' : 'rounded-none'}`} />\r\n                                    {/* Mock overlay for crop if needed, but styling is enough for now */}\r\n                                </div>\r\n                            ) : (\r\n                                <div className=\"text-center text-muted-foreground\">\r\n                                    <ImageIcon className=\"w-12 h-12 mx-auto mb-2 opacity-50\" />\r\n                                    <p>No image selected</p>\r\n                                </div>\r\n                            )}\r\n                        </CardContent>\r\n                    </Card>\r\n                </div>\r\n            </div>\r\n        </SessionGuard>\r\n    );\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\dashboard\\users\\page.tsx","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'CardDescription' is defined but never used.","line":4,"column":52,"nodeType":"Identifier","messageId":"unusedVar","endLine":4,"endColumn":67,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"CardDescription"},"fix":{"range":[112,129],"text":""},"desc":"Remove unused variable \"CardDescription\"."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'Shield' is defined but never used.","line":10,"column":36,"nodeType":"Identifier","messageId":"unusedVar","endLine":10,"endColumn":42,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"Shield"},"fix":{"range":[494,502],"text":""},"desc":"Remove unused variable \"Shield\"."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'session' is assigned a value but never used.","line":36,"column":19,"nodeType":"Identifier","messageId":"unusedVar","endLine":36,"endColumn":26},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'error' is defined but never used.","line":93,"column":18,"nodeType":"Identifier","messageId":"unusedVar","endLine":93,"endColumn":23},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'error' is defined but never used.","line":116,"column":18,"nodeType":"Identifier","messageId":"unusedVar","endLine":116,"endColumn":23},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":284,"column":27,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":284,"endColumn":30,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[12994,12997],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[12994,12997],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":5,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\"use client\";\r\n\r\nimport { useState, useEffect } from \"react\";\r\nimport { Card, CardContent, CardHeader, CardTitle, CardDescription } from \"@/components/ui/card\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { Input } from \"@/components/ui/input\";\r\nimport { Label } from \"@/components/ui/label\";\r\nimport { Badge } from \"@/components/ui/badge\";\r\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"@/components/ui/select\";\r\nimport { Trash2, Plus, Edit, User, Shield, ShieldAlert, ShieldCheck } from \"lucide-react\";\r\nimport { toast } from \"sonner\";\r\nimport { useSession } from \"next-auth/react\";\r\nimport {\r\n  AlertDialog,\r\n  AlertDialogAction,\r\n  AlertDialogCancel,\r\n  AlertDialogContent,\r\n  AlertDialogDescription,\r\n  AlertDialogFooter,\r\n  AlertDialogHeader,\r\n  AlertDialogTitle,\r\n} from \"@/components/ui/alert-dialog\";\r\n\r\ninterface UserProfile {\r\n    id: string;\r\n    name: string | null;\r\n    email: string;\r\n    role: \"SUPERADMIN\" | \"OWNER\" | \"STAFF\";\r\n    createdAt: string;\r\n    _count?: {\r\n        sessions: number;\r\n    }\r\n}\r\n\r\nexport default function UsersPage() {\r\n    const { data: session } = useSession();\r\n    const [users, setUsers] = useState<UserProfile[]>([]);\r\n    const [loading, setLoading] = useState(true);\r\n    const [showForm, setShowForm] = useState(false);\r\n    const [editingUser, setEditingUser] = useState<UserProfile | null>(null);\r\n\r\n    // Form state\r\n    const [formData, setFormData] = useState({\r\n        name: \"\",\r\n        email: \"\",\r\n        password: \"\",\r\n        role: \"OWNER\"\r\n    });\r\n\r\n    useEffect(() => {\r\n        fetchUsers();\r\n    }, []);\r\n\r\n    const fetchUsers = async () => {\r\n        try {\r\n            const res = await fetch(\"/api/users\");\r\n            if (res.ok) {\r\n                const data = await res.json();\r\n                setUsers(data);\r\n            } else if (res.status === 403) {\r\n                toast.error(\"Unauthorized. Only Super Admin can view users.\");\r\n            }\r\n        } catch (error) {\r\n            console.error(\"Failed to fetch users\", error);\r\n        } finally {\r\n            setLoading(false);\r\n        }\r\n    };\r\n\r\n    const handleSubmit = async (e: React.FormEvent) => {\r\n        e.preventDefault();\r\n        \r\n        try {\r\n            const url = editingUser ? `/api/users/${editingUser.id}` : \"/api/users\";\r\n            const method = editingUser ? \"PATCH\" : \"POST\";\r\n\r\n            const res = await fetch(url, {\r\n                method,\r\n                headers: { \"Content-Type\": \"application/json\" },\r\n                body: JSON.stringify(formData)\r\n            });\r\n\r\n            if (res.ok) {\r\n                toast.success(editingUser ? \"User updated\" : \"User created\");\r\n                setShowForm(false);\r\n                setEditingUser(null);\r\n                setFormData({ name: \"\", email: \"\", password: \"\", role: \"OWNER\" });\r\n                fetchUsers();\r\n            } else {\r\n                const error = await res.json();\r\n                toast.error(error.error || \"Operation failed\");\r\n            }\r\n        } catch (error) {\r\n            toast.error(\"Operation failed\");\r\n        }\r\n    };\r\n\r\n    const [deleteId, setDeleteId] = useState<string | null>(null);\r\n\r\n    const handleDelete = async (id: string) => {\r\n        setDeleteId(id);\r\n    };\r\n\r\n    const confirmDelete = async () => {\r\n        if (!deleteId) return;\r\n        \r\n        try {\r\n            const res = await fetch(`/api/users/${deleteId}`, { method: \"DELETE\" });\r\n            if (res.ok) {\r\n                toast.success(\"User deleted\");\r\n                fetchUsers();\r\n            } else {\r\n                const error = await res.json();\r\n                toast.error(error.error || \"Failed to delete\");\r\n            }\r\n        } catch (error) {\r\n            toast.error(\"Failed to delete user\");\r\n        } finally {\r\n            setDeleteId(null);\r\n        }\r\n    };\r\n\r\n    const getRoleIcon = (role: string) => {\r\n        switch (role) {\r\n            case \"SUPERADMIN\": return <ShieldAlert className=\"h-4 w-4 text-red-500\" />;\r\n            case \"OWNER\": return <ShieldCheck className=\"h-4 w-4 text-blue-500\" />;\r\n            default: return <User className=\"h-4 w-4 text-gray-500\" />;\r\n        }\r\n    };\r\n\r\n    if (loading) return <div className=\"p-8 text-center text-muted-foreground\">Loading...</div>;\r\n\r\n    // TODO: Improve RBAC check here if strictly needed, but API protects it.\r\n    // If empty list and not loading, likely unauthorized or empty.\r\n\r\n    return (\r\n        <div className=\"space-y-6\">\r\n            <div className=\"flex justify-between items-center\">\r\n                <div>\r\n                    <h1 className=\"text-2xl font-bold flex items-center gap-2\">\r\n                        <UsersIcon className=\"h-6 w-6\" /> User Management\r\n                    </h1>\r\n                    <p className=\"text-muted-foreground\">Manage users and roles</p>\r\n                </div>\r\n                <Button onClick={() => {\r\n                    setEditingUser(null);\r\n                    setFormData({ name: \"\", email: \"\", password: \"\", role: \"OWNER\" });\r\n                    setShowForm(true);\r\n                }}>\r\n                    <Plus className=\"h-4 w-4 mr-2\" /> Add User\r\n                </Button>\r\n            </div>\r\n\r\n            {/* User Form Modal/Card */}\r\n            {showForm && (\r\n                <Card className=\"border-2 border-primary/20\">\r\n                    <CardHeader>\r\n                        <CardTitle>{editingUser ? \"Edit User\" : \"New User\"}</CardTitle>\r\n                    </CardHeader>\r\n                    <CardContent>\r\n                        <form onSubmit={handleSubmit} className=\"space-y-4\">\r\n                            <div className=\"grid grid-cols-2 gap-4\">\r\n                                <div className=\"space-y-2\">\r\n                                    <Label>Name</Label>\r\n                                    <Input \r\n                                        value={formData.name}\r\n                                        onChange={e => setFormData({...formData, name: e.target.value})}\r\n                                        required\r\n                                    />\r\n                                </div>\r\n                                <div className=\"space-y-2\">\r\n                                    <Label>Email</Label>\r\n                                    <Input \r\n                                        type=\"email\"\r\n                                        value={formData.email}\r\n                                        onChange={e => setFormData({...formData, email: e.target.value})}\r\n                                        required\r\n                                    />\r\n                                </div>\r\n                            </div>\r\n                            <div className=\"grid grid-cols-2 gap-4\">\r\n                                <div className=\"space-y-2\">\r\n                                    <Label>{editingUser ? \"New Password (leave blank to keep)\" : \"Password\"}</Label>\r\n                                    <Input \r\n                                        type=\"password\"\r\n                                        value={formData.password}\r\n                                        onChange={e => setFormData({...formData, password: e.target.value})}\r\n                                        required={!editingUser}\r\n                                    />\r\n                                </div>\r\n                                <div className=\"space-y-2\">\r\n                                    <Label>Role</Label>\r\n                                    <Select \r\n                                        value={formData.role} \r\n                                        onValueChange={(v: string) => setFormData({...formData, role: v})}\r\n                                    >\r\n                                        <SelectTrigger>\r\n                                            <SelectValue />\r\n                                        </SelectTrigger>\r\n                                        <SelectContent>\r\n                                            <SelectItem value=\"SUPERADMIN\">Super Admin</SelectItem>\r\n                                            <SelectItem value=\"OWNER\">Owner</SelectItem>\r\n                                            <SelectItem value=\"STAFF\">Staff</SelectItem>\r\n                                        </SelectContent>\r\n                                    </Select>\r\n                                </div>\r\n                            </div>\r\n                            <div className=\"flex justify-end gap-2\">\r\n                                <Button type=\"button\" variant=\"ghost\" onClick={() => setShowForm(false)}>Cancel</Button>\r\n                                <Button type=\"submit\">{editingUser ? \"Update\" : \"Create\"}</Button>\r\n                            </div>\r\n                        </form>\r\n                    </CardContent>\r\n                </Card>\r\n            )}\r\n\r\n            {/* Users Table */}\r\n            <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-3\">\r\n                {users.map(user => (\r\n                    <Card key={user.id} className=\"overflow-hidden\">\r\n                        <CardContent className=\"p-0\">\r\n                            <div className=\"p-6\">\r\n                                <div className=\"flex justify-between items-start mb-4\">\r\n                                    <div className=\"flex items-center gap-3\">\r\n                                        <div className=\"h-10 w-10 rounded-full bg-slate-100 flex items-center justify-center font-bold text-slate-500\">\r\n                                            {user.name?.charAt(0) || user.email.charAt(0)}\r\n                                        </div>\r\n                                        <div>\r\n                                            <h3 className=\"font-semibold\">{user.name || \"User\"}</h3>\r\n                                            <p className=\"text-xs text-muted-foreground\">{user.email}</p>\r\n                                        </div>\r\n                                    </div>\r\n                                    <Badge variant=\"outline\" className=\"flex items-center gap-1\">\r\n                                        {getRoleIcon(user.role)}\r\n                                        {user.role}\r\n                                    </Badge>\r\n                                </div>\r\n                                \r\n                                <div className=\"flex justify-between items-center text-sm text-muted-foreground\">\r\n                                    <span>{user._count?.sessions || 0} Sessions</span>\r\n                                    <span>Joined {new Date(user.createdAt).toLocaleDateString()}</span>\r\n                                </div>\r\n                            </div>\r\n                            <div className=\"bg-slate-50 p-3 flex justify-end gap-2 border-t\">\r\n                                <Button size=\"sm\" variant=\"ghost\" onClick={() => {\r\n                                    setEditingUser(user);\r\n                                    setFormData({\r\n                                        name: user.name || \"\",\r\n                                        email: user.email,\r\n                                        password: \"\",\r\n                                        role: user.role\r\n                                    });\r\n                                    setShowForm(true);\r\n                                }}>\r\n                                    <Edit className=\"h-4 w-4 mr-1\" /> Edit\r\n                                </Button>\r\n                                <Button size=\"sm\" variant=\"ghost\" className=\"text-destructive hover:text-destructive\" onClick={() => handleDelete(user.id)}>\r\n                                    <Trash2 className=\"h-4 w-4 mr-1\" /> Delete\r\n                                </Button>\r\n                            </div>\r\n                        </CardContent>\r\n                    </Card>\r\n                ))}\r\n            </div>\r\n            {/* Confirmation Dialog */}\r\n            <AlertDialog open={!!deleteId} onOpenChange={(open) => !open && setDeleteId(null)}>\r\n                <AlertDialogContent>\r\n                    <AlertDialogHeader>\r\n                        <AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>\r\n                        <AlertDialogDescription>\r\n                            This action cannot be undone. This will permanently delete the user request and remove their data from our servers.\r\n                        </AlertDialogDescription>\r\n                    </AlertDialogHeader>\r\n                    <AlertDialogFooter>\r\n                        <AlertDialogCancel>Cancel</AlertDialogCancel>\r\n                        <AlertDialogAction onClick={confirmDelete} className=\"bg-red-600 hover:bg-red-700\">Continue</AlertDialogAction>\r\n                    </AlertDialogFooter>\r\n                </AlertDialogContent>\r\n            </AlertDialog>\r\n        </div>\r\n    );\r\n}\r\n\r\nfunction UsersIcon(props: any) {\r\n  return (\r\n    <svg\r\n      {...props}\r\n      xmlns=\"http://www.w3.org/2000/svg\"\r\n      width=\"24\"\r\n      height=\"24\"\r\n      viewBox=\"0 0 24 24\"\r\n      fill=\"none\"\r\n      stroke=\"currentColor\"\r\n      strokeWidth=\"2\"\r\n      strokeLinecap=\"round\"\r\n      strokeLinejoin=\"round\"\r\n    >\r\n      <path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\" />\r\n      <circle cx=\"9\" cy=\"7\" r=\"4\" />\r\n      <path d=\"M22 21v-2a4 4 0 0 0-3-3.87\" />\r\n      <path d=\"M16 3.13a4 4 0 0 1 0 7.75\" />\r\n    </svg>\r\n  )\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\dashboard\\webhooks\\page.tsx","messages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'fetchWebhooks'. Either include it or remove the dependency array.","line":65,"column":8,"nodeType":"ArrayExpression","endLine":65,"endColumn":29,"suggestions":[{"desc":"Update the dependencies array to be: [fetchWebhooks, sessionId, sessions]","fix":{"range":[2650,2671],"text":"[fetchWebhooks, sessionId, sessions]"}}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'error' is defined but never used.","line":114,"column":18,"nodeType":"Identifier","messageId":"unusedVar","endLine":114,"endColumn":23},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":152,"column":28,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":152,"endColumn":31,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[5688,5691],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[5688,5691],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'error' is defined but never used.","line":181,"column":18,"nodeType":"Identifier","messageId":"unusedVar","endLine":181,"endColumn":23},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'error' is defined but never used.","line":198,"column":18,"nodeType":"Identifier","messageId":"unusedVar","endLine":198,"endColumn":23},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'error' is defined but never used.","line":221,"column":18,"nodeType":"Identifier","messageId":"unusedVar","endLine":221,"endColumn":23},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'error' is defined but never used.","line":241,"column":18,"nodeType":"Identifier","messageId":"unusedVar","endLine":241,"endColumn":23},{"ruleId":"react/no-unescaped-entities","severity":2,"message":"`\"` can be escaped with `&quot;`, `&ldquo;`, `&#34;`, `&rdquo;`.","line":295,"column":97,"nodeType":"JSXText","messageId":"unescapedEntityAlts","suggestions":[{"messageId":"replaceWithAlt","data":{"alt":"&quot;"},"fix":{"range":[11653,11673],"text":"curl -H &quot;X-API-Key: "},"desc":"Replace with `&quot;`."},{"messageId":"replaceWithAlt","data":{"alt":"&ldquo;"},"fix":{"range":[11653,11673],"text":"curl -H &ldquo;X-API-Key: "},"desc":"Replace with `&ldquo;`."},{"messageId":"replaceWithAlt","data":{"alt":"&#34;"},"fix":{"range":[11653,11673],"text":"curl -H &#34;X-API-Key: "},"desc":"Replace with `&#34;`."},{"messageId":"replaceWithAlt","data":{"alt":"&rdquo;"},"fix":{"range":[11653,11673],"text":"curl -H &rdquo;X-API-Key: "},"desc":"Replace with `&rdquo;`."}]},{"ruleId":"react/no-unescaped-entities","severity":2,"message":"`\"` can be escaped with `&quot;`, `&ldquo;`, `&#34;`, `&rdquo;`.","line":295,"column":134,"nodeType":"JSXText","messageId":"unescapedEntityAlts","suggestions":[{"messageId":"replaceWithAlt","data":{"alt":"&quot;"},"fix":{"range":[11695,11731],"text":"...&quot; http://your-server/api/sessions"},"desc":"Replace with `&quot;`."},{"messageId":"replaceWithAlt","data":{"alt":"&ldquo;"},"fix":{"range":[11695,11731],"text":"...&ldquo; http://your-server/api/sessions"},"desc":"Replace with `&ldquo;`."},{"messageId":"replaceWithAlt","data":{"alt":"&#34;"},"fix":{"range":[11695,11731],"text":"...&#34; http://your-server/api/sessions"},"desc":"Replace with `&#34;`."},{"messageId":"replaceWithAlt","data":{"alt":"&rdquo;"},"fix":{"range":[11695,11731],"text":"...&rdquo; http://your-server/api/sessions"},"desc":"Replace with `&rdquo;`."}]},{"ruleId":"react/no-unescaped-entities","severity":2,"message":"`\"` can be escaped with `&quot;`, `&ldquo;`, `&#34;`, `&rdquo;`.","line":412,"column":76,"nodeType":"JSXText","messageId":"unescapedEntityAlts","suggestions":[{"messageId":"replaceWithAlt","data":{"alt":"&quot;"},"fix":{"range":[18547,18678],"text":"\r\n                            No webhooks configured for this session. Click &quot;Add Webhook\" to create one.\r\n                        "},"desc":"Replace with `&quot;`."},{"messageId":"replaceWithAlt","data":{"alt":"&ldquo;"},"fix":{"range":[18547,18678],"text":"\r\n                            No webhooks configured for this session. Click &ldquo;Add Webhook\" to create one.\r\n                        "},"desc":"Replace with `&ldquo;`."},{"messageId":"replaceWithAlt","data":{"alt":"&#34;"},"fix":{"range":[18547,18678],"text":"\r\n                            No webhooks configured for this session. Click &#34;Add Webhook\" to create one.\r\n                        "},"desc":"Replace with `&#34;`."},{"messageId":"replaceWithAlt","data":{"alt":"&rdquo;"},"fix":{"range":[18547,18678],"text":"\r\n                            No webhooks configured for this session. Click &rdquo;Add Webhook\" to create one.\r\n                        "},"desc":"Replace with `&rdquo;`."}]},{"ruleId":"react/no-unescaped-entities","severity":2,"message":"`\"` can be escaped with `&quot;`, `&ldquo;`, `&#34;`, `&rdquo;`.","line":412,"column":88,"nodeType":"JSXText","messageId":"unescapedEntityAlts","suggestions":[{"messageId":"replaceWithAlt","data":{"alt":"&quot;"},"fix":{"range":[18547,18678],"text":"\r\n                            No webhooks configured for this session. Click \"Add Webhook&quot; to create one.\r\n                        "},"desc":"Replace with `&quot;`."},{"messageId":"replaceWithAlt","data":{"alt":"&ldquo;"},"fix":{"range":[18547,18678],"text":"\r\n                            No webhooks configured for this session. Click \"Add Webhook&ldquo; to create one.\r\n                        "},"desc":"Replace with `&ldquo;`."},{"messageId":"replaceWithAlt","data":{"alt":"&#34;"},"fix":{"range":[18547,18678],"text":"\r\n                            No webhooks configured for this session. Click \"Add Webhook&#34; to create one.\r\n                        "},"desc":"Replace with `&#34;`."},{"messageId":"replaceWithAlt","data":{"alt":"&rdquo;"},"fix":{"range":[18547,18678],"text":"\r\n                            No webhooks configured for this session. Click \"Add Webhook&rdquo; to create one.\r\n                        "},"desc":"Replace with `&rdquo;`."}]}],"suppressedMessages":[],"errorCount":5,"fatalErrorCount":0,"warningCount":6,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\"use client\";\r\n\r\nimport { useState, useEffect } from \"react\";\r\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from \"@/components/ui/card\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { Input } from \"@/components/ui/input\";\r\nimport { Label } from \"@/components/ui/label\";\r\nimport { Switch } from \"@/components/ui/switch\";\r\nimport { Badge } from \"@/components/ui/badge\";\r\nimport { Trash2, Plus, Copy, RefreshCw, Webhook, Key, Eye, EyeOff } from \"lucide-react\";\r\nimport { toast } from \"sonner\";\r\nimport {\r\n    AlertDialog,\r\n    AlertDialogAction,\r\n    AlertDialogCancel,\r\n    AlertDialogContent,\r\n    AlertDialogDescription,\r\n    AlertDialogFooter,\r\n    AlertDialogHeader,\r\n    AlertDialogTitle,\r\n} from \"@/components/ui/alert-dialog\";\r\n\r\ninterface WebhookConfig {\r\n    id: string;\r\n    name: string;\r\n    url: string;\r\n    secret?: string;\r\n    sessionId?: string;\r\n    events: string[];\r\n    isActive: boolean;\r\n    createdAt: string;\r\n}\r\n\r\nconst AVAILABLE_EVENTS = [\r\n    { id: \"message.received\", label: \"Message Received\", description: \"When a new message is received\" },\r\n    { id: \"message.sent\", label: \"Message Sent\", description: \"When a message is sent\" },\r\n    { id: \"message.status\", label: \"Message Status\", description: \"When message status changes (delivered, read)\" },\r\n    { id: \"connection.update\", label: \"Connection Update\", description: \"When session connects/disconnects\" },\r\n    { id: \"group.update\", label: \"Group Update\", description: \"When group info changes\" },\r\n    { id: \"contact.update\", label: \"Contact Update\", description: \"When contact info changes\" },\r\n    { id: \"status.update\", label: \"Status/Story\", description: \"When a status is posted or viewed\" },\r\n];\r\n\r\nimport { useSession } from \"@/components/dashboard/session-provider\";\r\n\r\nexport default function WebhooksPage() {\r\n    const { sessionId, sessions } = useSession(); // Get active session ID and list of sessions\r\n    const [webhooks, setWebhooks] = useState<WebhookConfig[]>([]);\r\n    const [apiKey, setApiKey] = useState<string | null>(null);\r\n    const [showApiKey, setShowApiKey] = useState(false);\r\n    const [loading, setLoading] = useState(true);\r\n\r\n    // New webhook form\r\n    const [showNewForm, setShowNewForm] = useState(false);\r\n    const [newName, setNewName] = useState(\"\");\r\n    const [newUrl, setNewUrl] = useState(\"\");\r\n    const [newSecret, setNewSecret] = useState(\"\");\r\n    const [newEvents, setNewEvents] = useState<string[]>([\"message.received\", \"message.sent\"]);\r\n\r\n    useEffect(() => {\r\n        if (sessions.length > 0) {\r\n            fetchWebhooks();\r\n        }\r\n        fetchApiKey();\r\n    }, [sessionId, sessions]); // Refetch when sessionId changes or sessions are loaded\r\n\r\n    const fetchWebhooks = async () => {\r\n        setLoading(true);\r\n        try {\r\n            // Fetch webhooks using the new session-scoped endpoint\r\n            const res = await fetch(`/api/webhooks/${sessionId}`);\r\n            if (res.ok) {\r\n                const data = await res.json();\r\n\r\n                // Find current session to get its internal ID (CUID)\r\n                const currentSession = sessions.find(s => s.sessionId === sessionId);\r\n                const currentSessionCuid = currentSession?.id;\r\n\r\n                // Filter by active session (check both String ID and CUID)\r\n                const filtered = data.filter((w: WebhookConfig) =>\r\n                    w.sessionId === sessionId ||\r\n                    w.sessionId === currentSessionCuid ||\r\n                    !w.sessionId\r\n                );\r\n                setWebhooks(filtered);\r\n            }\r\n        } catch (error) {\r\n            console.error(\"Failed to fetch webhooks\", error);\r\n        } finally {\r\n            setLoading(false);\r\n        }\r\n    };\r\n\r\n    const fetchApiKey = async () => {\r\n        try {\r\n            const res = await fetch(\"/api/user/api-key\");\r\n            if (res.ok) {\r\n                const data = await res.json();\r\n                setApiKey(data.apiKey);\r\n            }\r\n        } catch (error) {\r\n            console.error(\"Failed to fetch API key\", error);\r\n        }\r\n    };\r\n\r\n    const generateNewApiKey = async () => {\r\n        try {\r\n            const res = await fetch(\"/api/user/api-key\", { method: \"POST\" });\r\n            if (res.ok) {\r\n                const data = await res.json();\r\n                setApiKey(data.apiKey);\r\n                toast.success(\"New API key generated!\");\r\n            }\r\n        } catch (error) {\r\n            toast.error(\"Failed to generate API key\");\r\n        }\r\n    };\r\n\r\n    // Edit state\r\n    const [editingId, setEditingId] = useState<string | null>(null);\r\n\r\n    const handleEdit = (webhook: WebhookConfig) => {\r\n        setEditingId(webhook.id);\r\n        setNewName(webhook.name);\r\n        setNewUrl(webhook.url);\r\n        setNewSecret(webhook.secret || \"\");\r\n        setNewEvents(webhook.events);\r\n        setShowNewForm(true);\r\n    };\r\n\r\n    const handleSaveWebhook = async () => {\r\n        if (!newName || !newUrl || newEvents.length === 0) {\r\n            toast.error(\"Name, URL, and at least one event are required\");\r\n            return;\r\n        }\r\n\r\n        if (!sessionId) {\r\n            toast.error(\"No active session selected\");\r\n            return;\r\n        }\r\n\r\n        try {\r\n            const webhook = editingId ? webhooks.find(w => w.id === editingId) : null;\r\n            const targetSessionId = webhook?.sessionId || sessionId;\r\n\r\n            const url = editingId\r\n                ? `/api/webhooks/${targetSessionId}/${editingId}`\r\n                : `/api/webhooks/${sessionId}`;\r\n\r\n            const method = editingId ? \"PUT\" : \"POST\";\r\n\r\n            const payload: any = {\r\n                name: newName,\r\n                url: newUrl,\r\n                events: newEvents\r\n            };\r\n\r\n            // Only send secret if it's set or we are creating new\r\n            if (newSecret) {\r\n                payload.secret = newSecret;\r\n            }\r\n\r\n            const res = await fetch(url, {\r\n                method,\r\n                headers: { \"Content-Type\": \"application/json\" },\r\n                body: JSON.stringify(payload)\r\n            });\r\n\r\n            if (res.ok) {\r\n                toast.success(editingId ? \"Webhook updated!\" : \"Webhook created!\");\r\n                setShowNewForm(false);\r\n                setNewName(\"\");\r\n                setNewUrl(\"\");\r\n                setNewSecret(\"\");\r\n                setNewEvents([\"message.received\", \"message.sent\"]);\r\n                setEditingId(null);\r\n                fetchWebhooks();\r\n            } else {\r\n                toast.error(editingId ? \"Failed to update webhook\" : \"Failed to create webhook\");\r\n            }\r\n        } catch (error) {\r\n            toast.error(\"An error occurred\");\r\n        }\r\n    };\r\n\r\n    const toggleWebhookActive = async (id: string, isActive: boolean) => {\r\n        try {\r\n            // Find webhook to get its session ID\r\n            const webhook = webhooks.find(w => w.id === id);\r\n            const targetSessionId = webhook?.sessionId || sessionId; // Fallback to current session if missing (legacy)\r\n\r\n            await fetch(`/api/webhooks/${targetSessionId}/${id}`, {\r\n                method: \"PUT\",\r\n                headers: { \"Content-Type\": \"application/json\" },\r\n                body: JSON.stringify({ isActive })\r\n            });\r\n            setWebhooks(webhooks.map(w => w.id === id ? { ...w, isActive } : w));\r\n        } catch (error) {\r\n            toast.error(\"Failed to update webhook\");\r\n        }\r\n    };\r\n\r\n    const toggleEventForWebhook = async (webhookId: string, eventId: string) => {\r\n        const webhook = webhooks.find(w => w.id === webhookId);\r\n        if (!webhook) return;\r\n\r\n        const newEvents = webhook.events.includes(eventId)\r\n            ? webhook.events.filter(e => e !== eventId)\r\n            : [...webhook.events, eventId];\r\n\r\n        // Find webhook to get its session ID\r\n        const targetSessionId = webhook.sessionId || sessionId;\r\n\r\n        try {\r\n            await fetch(`/api/webhooks/${targetSessionId}/${webhookId}`, {\r\n                method: \"PUT\",\r\n                headers: { \"Content-Type\": \"application/json\" },\r\n                body: JSON.stringify({ events: newEvents })\r\n            });\r\n            setWebhooks(webhooks.map(w => w.id === webhookId ? { ...w, events: newEvents } : w));\r\n        } catch (error) {\r\n            toast.error(\"Failed to update webhook events\");\r\n        }\r\n    };\r\n\r\n    const [deleteId, setDeleteId] = useState<string | null>(null);\r\n\r\n    const deleteWebhook = async (id: string) => {\r\n        setDeleteId(id);\r\n    };\r\n\r\n    const confirmDelete = async () => {\r\n        if (!deleteId) return;\r\n\r\n        try {\r\n            const webhook = webhooks.find(w => w.id === deleteId);\r\n            const targetSessionId = webhook?.sessionId || sessionId;\r\n            await fetch(`/api/webhooks/${targetSessionId}/${deleteId}`, { method: \"DELETE\" });\r\n            setWebhooks(webhooks.filter(w => w.id !== deleteId));\r\n            toast.success(\"Webhook deleted\");\r\n        } catch (error) {\r\n            toast.error(\"Failed to delete webhook\");\r\n        } finally {\r\n            setDeleteId(null);\r\n        }\r\n    };\r\n\r\n    const copyToClipboard = (text: string) => {\r\n        navigator.clipboard.writeText(text);\r\n        toast.success(\"Copied to clipboard!\");\r\n    };\r\n\r\n    return (\r\n        <div className=\"space-y-6\">\r\n            <div className=\"flex justify-between items-center\">\r\n                <h1 className=\"text-2xl font-bold\">Webhooks & API</h1>\r\n            </div>\r\n\r\n            {/* API Key Section */}\r\n            <Card>\r\n                <CardHeader>\r\n                    <CardTitle className=\"flex items-center gap-2\">\r\n                        <Key className=\"h-5 w-5\" /> API Key\r\n                    </CardTitle>\r\n                    <CardDescription>\r\n                        Use this key to authenticate API requests. Include it in the X-API-Key header.\r\n                    </CardDescription>\r\n                </CardHeader>\r\n                <CardContent>\r\n                    <div className=\"flex items-center gap-3\">\r\n                        <div className=\"flex-1 bg-slate-100 rounded-md p-3 font-mono text-sm\">\r\n                            {apiKey ? (\r\n                                showApiKey ? apiKey : \"ΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇóΓÇó\"\r\n                            ) : (\r\n                                <span className=\"text-muted-foreground\">No API key generated</span>\r\n                            )}\r\n                        </div>\r\n                        {apiKey && (\r\n                            <>\r\n                                <Button variant=\"ghost\" size=\"icon\" onClick={() => setShowApiKey(!showApiKey)}>\r\n                                    {showApiKey ? <EyeOff className=\"h-4 w-4\" /> : <Eye className=\"h-4 w-4\" />}\r\n                                </Button>\r\n                                <Button variant=\"ghost\" size=\"icon\" onClick={() => copyToClipboard(apiKey)}>\r\n                                    <Copy className=\"h-4 w-4\" />\r\n                                </Button>\r\n                            </>\r\n                        )}\r\n                        <Button onClick={generateNewApiKey}>\r\n                            <RefreshCw className=\"h-4 w-4 mr-2\" />\r\n                            {apiKey ? \"Regenerate\" : \"Generate\"}\r\n                        </Button>\r\n                    </div>\r\n                    {apiKey && (\r\n                        <p className=\"text-xs text-muted-foreground mt-2\">\r\n                            Example: <code className=\"bg-slate-100 px-1 py-0.5 rounded\">curl -H \"X-API-Key: {apiKey?.slice(0, 10)}...\" http://your-server/api/sessions</code>\r\n                        </p>\r\n                    )}\r\n                </CardContent>\r\n            </Card>\r\n\r\n            {/* Webhooks Section */}\r\n            <Card>\r\n                <CardHeader>\r\n                    <div className=\"flex justify-between items-center\">\r\n                        <div>\r\n                            <CardTitle className=\"flex items-center gap-2\">\r\n                                <Webhook className=\"h-5 w-5\" /> Webhooks\r\n                            </CardTitle>\r\n                            <CardDescription>\r\n                                Send real-time events to external URLs when activities happen in WhatsApp.\r\n                                <br />\r\n                                <span className=\"text-xs text-blue-600 font-medium bg-blue-50 px-2 py-0.5 rounded\">\r\n                                    Active Session: {sessionId || \"None\"}\r\n                                </span>\r\n                            </CardDescription>\r\n                        </div>\r\n                        <Button onClick={() => {\r\n                            setEditingId(null);\r\n                            setNewName(\"\");\r\n                            setNewUrl(\"\");\r\n                            setNewSecret(\"\");\r\n                            setNewEvents([\"message.received\", \"message.sent\"]);\r\n                            setShowNewForm(!showNewForm);\r\n                        }} disabled={!sessionId}>\r\n                            <Plus className=\"h-4 w-4 mr-2\" /> Add Webhook\r\n                        </Button>\r\n                    </div>\r\n                </CardHeader>\r\n                <CardContent className=\"space-y-4\">\r\n                    {!sessionId && (\r\n                        <div className=\"bg-yellow-50 p-4 border border-yellow-200 rounded text-yellow-800 text-sm\">\r\n                            Please select a session in the top bar to manage webhooks.\r\n                        </div>\r\n                    )}\r\n\r\n                    {/* New Webhook Form */}\r\n                    {showNewForm && (\r\n                        <Card className=\"border-dashed border-2\">\r\n                            <CardHeader>\r\n                                <CardTitle>{editingId ? \"Edit Webhook\" : \"New Webhook\"}</CardTitle>\r\n                            </CardHeader>\r\n                            <CardContent className=\"pt-4 space-y-4\">\r\n                                <div className=\"grid grid-cols-2 gap-4\">\r\n                                    <div className=\"space-y-2\">\r\n                                        <Label>Name</Label>\r\n                                        <Input\r\n                                            placeholder=\"My Server\"\r\n                                            value={newName}\r\n                                            onChange={(e) => setNewName(e.target.value)}\r\n                                        />\r\n                                    </div>\r\n                                    <div className=\"space-y-2\">\r\n                                        <Label>Webhook URL</Label>\r\n                                        <Input\r\n                                            placeholder=\"https://example.com/webhook\"\r\n                                            value={newUrl}\r\n                                            onChange={(e) => setNewUrl(e.target.value)}\r\n                                        />\r\n                                    </div>\r\n                                </div>\r\n                                <div className=\"space-y-2\">\r\n                                    <Label>Secret (optional, for HMAC signature)</Label>\r\n                                    <Input\r\n                                        placeholder=\"your-secret-key\"\r\n                                        value={newSecret}\r\n                                        onChange={(e) => setNewSecret(e.target.value)}\r\n                                    />\r\n                                </div>\r\n                                <div className=\"space-y-2\">\r\n                                    <Label>Events</Label>\r\n                                    <div className=\"grid grid-cols-2 gap-2\">\r\n                                        {AVAILABLE_EVENTS.map(event => (\r\n                                            <div key={event.id} className=\"flex items-center gap-2 p-2 rounded border\">\r\n                                                <Switch\r\n                                                    checked={newEvents.includes(event.id)}\r\n                                                    onCheckedChange={(checked) => {\r\n                                                        if (checked) {\r\n                                                            setNewEvents([...newEvents, event.id]);\r\n                                                        } else {\r\n                                                            setNewEvents(newEvents.filter(e => e !== event.id));\r\n                                                        }\r\n                                                    }}\r\n                                                />\r\n                                                <div>\r\n                                                    <p className=\"text-sm font-medium\">{event.label}</p>\r\n                                                    <p className=\"text-xs text-muted-foreground\">{event.description}</p>\r\n                                                </div>\r\n                                            </div>\r\n                                        ))}\r\n                                    </div>\r\n                                </div>\r\n                                <div className=\"flex gap-2 justify-end\">\r\n                                    <Button variant=\"ghost\" onClick={() => {\r\n                                        setShowNewForm(false);\r\n                                        setEditingId(null);\r\n                                        // Reset fields? or keep for re-open if needed? Better reset.\r\n                                        setNewName(\"\");\r\n                                        setNewUrl(\"\");\r\n                                        setNewSecret(\"\");\r\n                                    }}>Cancel</Button>\r\n                                    <Button onClick={handleSaveWebhook}>{editingId ? \"Update Webhook\" : \"Create Webhook\"}</Button>\r\n                                </div>\r\n                            </CardContent>\r\n                        </Card>\r\n                    )}\r\n\r\n                    {/* Existing Webhooks */}\r\n                    {loading ? (\r\n                        <p className=\"text-center text-muted-foreground py-8\">Loading...</p>\r\n                    ) : webhooks.length === 0 ? (\r\n                        <p className=\"text-center text-muted-foreground py-8\">\r\n                            No webhooks configured for this session. Click \"Add Webhook\" to create one.\r\n                        </p>\r\n                    ) : (\r\n                        webhooks.map((webhook) => (\r\n                            <Card key={webhook.id} className={webhook.isActive ? \"\" : \"opacity-60\"}>\r\n                                <CardContent className=\"pt-4 space-y-3\">\r\n                                    <div className=\"flex justify-between items-start\">\r\n                                        <div>\r\n                                            <h3 className=\"font-semibold flex items-center gap-2\">\r\n                                                {webhook.name}\r\n                                                <Badge variant={webhook.isActive ? \"default\" : \"secondary\"}>\r\n                                                    {webhook.isActive ? \"Active\" : \"Inactive\"}\r\n                                                </Badge>\r\n                                                {webhook.sessionId && (\r\n                                                    <Badge variant=\"outline\" className=\"text-xs\">\r\n                                                        {webhook.sessionId}\r\n                                                    </Badge>\r\n                                                )}\r\n                                            </h3>\r\n                                            <p className=\"text-sm text-muted-foreground font-mono\">{webhook.url}</p>\r\n                                        </div>\r\n                                        <div className=\"flex items-center gap-2\">\r\n                                            <Switch\r\n                                                checked={webhook.isActive}\r\n                                                onCheckedChange={(checked) => toggleWebhookActive(webhook.id, checked)}\r\n                                            />\r\n                                            <Button variant=\"ghost\" size=\"sm\" onClick={() => handleEdit(webhook)}>\r\n                                                Edit\r\n                                            </Button>\r\n                                            <Button variant=\"ghost\" size=\"icon\" onClick={() => deleteWebhook(webhook.id)}>\r\n                                                <Trash2 className=\"h-4 w-4 text-destructive\" />\r\n                                            </Button>\r\n                                        </div>\r\n                                    </div>\r\n\r\n                                    {/* Event Toggles */}\r\n                                    <div className=\"space-y-2\">\r\n                                        <Label className=\"text-xs\">Events (click to toggle)</Label>\r\n                                        <div className=\"flex flex-wrap gap-2\">\r\n                                            {AVAILABLE_EVENTS.map(event => (\r\n                                                <Badge\r\n                                                    key={event.id}\r\n                                                    variant={webhook.events.includes(event.id) ? \"default\" : \"outline\"}\r\n                                                    className=\"cursor-pointer\"\r\n                                                    onClick={() => toggleEventForWebhook(webhook.id, event.id)}\r\n                                                >\r\n                                                    {event.label}\r\n                                                </Badge>\r\n                                            ))}\r\n                                        </div>\r\n                                    </div>\r\n                                </CardContent>\r\n                            </Card>\r\n                        ))\r\n                    )}\r\n                </CardContent>\r\n            </Card>\r\n\r\n            <AlertDialog open={!!deleteId} onOpenChange={(open) => !open && setDeleteId(null)}>\r\n                <AlertDialogContent>\r\n                    <AlertDialogHeader>\r\n                        <AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>\r\n                        <AlertDialogDescription>\r\n                            This action cannot be undone. This will permanently delete the webhook configuration.\r\n                        </AlertDialogDescription>\r\n                    </AlertDialogHeader>\r\n                    <AlertDialogFooter>\r\n                        <AlertDialogCancel>Cancel</AlertDialogCancel>\r\n                        <AlertDialogAction onClick={confirmDelete} className=\"bg-red-600 hover:bg-red-700\">Delete</AlertDialogAction>\r\n                    </AlertDialogFooter>\r\n                </AlertDialogContent>\r\n            </AlertDialog>\r\n        </div>\r\n    );\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\docs\\docs-client.tsx","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'X' is defined but never used.","line":9,"column":16,"nodeType":"Identifier","messageId":"unusedVar","endLine":9,"endColumn":17,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"X"},"fix":{"range":[346,349],"text":""},"desc":"Remove unused variable \"X\"."}]},{"ruleId":"react-hooks/set-state-in-effect","severity":2,"message":"Error: Calling setState synchronously within an effect can trigger cascading renders\n\nEffects are intended to synchronize state between React and external systems such as manually updating the DOM, state management libraries, or other platform APIs. In general, the body of an effect should do one or both of the following:\n* Update external systems with the latest state from React.\n* Subscribe for updates from some external system, calling setState in a callback function when external state changes.\n\nCalling setState synchronously within an effect body causes cascading renders that can hurt performance, and is not recommended. (https://react.dev/learn/you-might-not-need-an-effect).\n\nC:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\docs\\docs-client.tsx:41:9\n  39 |             initial[section.id] = true;\n  40 |         });\n> 41 |         setOpenSections(initial);\n     |         ^^^^^^^^^^^^^^^ Avoid calling setState() directly within an effect\n  42 |     }, [toc]);\n  43 |\n  44 |     // Debounce search query to prevent excessive re-renders","line":41,"column":9,"nodeType":null,"endLine":41,"endColumn":24},{"ruleId":"react-hooks/set-state-in-effect","severity":2,"message":"Error: Calling setState synchronously within an effect can trigger cascading renders\n\nEffects are intended to synchronize state between React and external systems such as manually updating the DOM, state management libraries, or other platform APIs. In general, the body of an effect should do one or both of the following:\n* Update external systems with the latest state from React.\n* Subscribe for updates from some external system, calling setState in a callback function when external state changes.\n\nCalling setState synchronously within an effect body causes cascading renders that can hurt performance, and is not recommended. (https://react.dev/learn/you-might-not-need-an-effect).\n\nC:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\docs\\docs-client.tsx:56:13\n  54 |     useEffect(() => {\n  55 |         if (!debouncedQuery) {\n> 56 |             setFilteredToc(toc);\n     |             ^^^^^^^^^^^^^^ Avoid calling setState() directly within an effect\n  57 |             return;\n  58 |         }\n  59 |","line":56,"column":13,"nodeType":null,"endLine":56,"endColumn":27},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'node' is defined but never used.","line":232,"column":36,"nodeType":"Identifier","messageId":"unusedVar","endLine":232,"endColumn":40},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'node' is defined but never used.","line":236,"column":36,"nodeType":"Identifier","messageId":"unusedVar","endLine":236,"endColumn":40},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'node' is defined but never used.","line":240,"column":38,"nodeType":"Identifier","messageId":"unusedVar","endLine":240,"endColumn":42},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":240,"column":85,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":240,"endColumn":88,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[11784,11787],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[11784,11787],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'node' is defined but never used.","line":263,"column":39,"nodeType":"Identifier","messageId":"unusedVar","endLine":263,"endColumn":43},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'node' is defined but never used.","line":268,"column":39,"nodeType":"Identifier","messageId":"unusedVar","endLine":268,"endColumn":43},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'node' is defined but never used.","line":269,"column":36,"nodeType":"Identifier","messageId":"unusedVar","endLine":269,"endColumn":40},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'node' is defined but never used.","line":270,"column":36,"nodeType":"Identifier","messageId":"unusedVar","endLine":270,"endColumn":40},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'node' is defined but never used.","line":271,"column":37,"nodeType":"Identifier","messageId":"unusedVar","endLine":271,"endColumn":41}],"suppressedMessages":[],"errorCount":3,"fatalErrorCount":0,"warningCount":9,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\"use client\";\r\n\r\nimport React, { useState, useEffect } from \"react\";\r\nimport ReactMarkdown from \"react-markdown\";\r\nimport remarkGfm from \"remark-gfm\";\r\nimport Link from \"next/link\";\r\nimport { Light as SyntaxHighlighter } from \"react-syntax-highlighter\";\r\nimport { atomOneDark } from \"react-syntax-highlighter/dist/esm/styles/hljs\";\r\nimport { Menu, X, Search, ChevronRight } from \"lucide-react\";\r\nimport { Sheet, SheetContent, SheetTrigger } from \"@/components/ui/sheet\";\r\nimport { Button } from \"@/components/ui/button\";\r\n\r\ninterface TocItem {\r\n    text: string;\r\n    id: string;\r\n}\r\n\r\ninterface TocSection {\r\n    title: string;\r\n    id: string;\r\n    items: TocItem[];\r\n}\r\n\r\ninterface DocsClientProps {\r\n    content: string;\r\n    toc: TocSection[];\r\n}\r\n\r\nexport function DocsClient({ content, toc }: DocsClientProps) {\r\n    const [searchQuery, setSearchQuery] = useState(\"\");\r\n    const [filteredToc, setFilteredToc] = useState(toc);\r\n    const [openMobileMenu, setOpenMobileMenu] = useState(false);\r\n    const [openSections, setOpenSections] = useState<Record<string, boolean>>({});\r\n\r\n    // Initialize openSections (all open by default or logic based)\r\n    useEffect(() => {\r\n        const initial: Record<string, boolean> = {};\r\n        toc.forEach(section => {\r\n            initial[section.id] = true;\r\n        });\r\n        setOpenSections(initial);\r\n    }, [toc]);\r\n\r\n    // Debounce search query to prevent excessive re-renders\r\n    const [debouncedQuery, setDebouncedQuery] = useState(\"\");\r\n\r\n    useEffect(() => {\r\n        const timer = setTimeout(() => {\r\n            setDebouncedQuery(searchQuery);\r\n        }, 300);\r\n        return () => clearTimeout(timer);\r\n    }, [searchQuery]);\r\n\r\n    useEffect(() => {\r\n        if (!debouncedQuery) {\r\n            setFilteredToc(toc);\r\n            return;\r\n        }\r\n\r\n        const lowerQuery = debouncedQuery.toLowerCase();\r\n        const filtered = toc.map(section => {\r\n            const titleMatches = section.title.toLowerCase().includes(lowerQuery);\r\n            const matchingItems = section.items.filter(item =>\r\n                item.text.toLowerCase().includes(lowerQuery)\r\n            );\r\n\r\n            if (titleMatches || matchingItems.length > 0) {\r\n                return {\r\n                    ...section,\r\n                    items: titleMatches ? section.items : matchingItems\r\n                };\r\n            }\r\n            return null;\r\n        }).filter(Boolean) as TocSection[];\r\n\r\n        setFilteredToc(filtered);\r\n\r\n        const allOpen: Record<string, boolean> = {};\r\n        filtered.forEach(s => allOpen[s.id] = true);\r\n        setOpenSections(allOpen);\r\n\r\n    }, [debouncedQuery, toc]);\r\n\r\n    const toggleSection = (id: string) => {\r\n        setOpenSections(prev => ({ ...prev, [id]: !prev[id] }));\r\n    };\r\n\r\n    const scrollToSection = (id: string, closeMobile = true) => {\r\n        const element = document.getElementById(id);\r\n        if (element) {\r\n            const headerOffset = 100;\r\n            const elementPosition = element.getBoundingClientRect().top;\r\n            const offsetPosition = elementPosition + window.pageYOffset - headerOffset;\r\n\r\n            window.scrollTo({\r\n                top: offsetPosition,\r\n                behavior: \"smooth\"\r\n            });\r\n            if (closeMobile) setOpenMobileMenu(false);\r\n        }\r\n    };\r\n\r\n    // Memoized Sidebar Item to prevent full list re-renders\r\n    const SidebarItem = React.memo(({ section, isOpen, onToggle, onScroll, isMobile }: {\r\n        section: TocSection,\r\n        isOpen: boolean,\r\n        onToggle: (id: string) => void,\r\n        onScroll: (id: string, mobile: boolean) => void,\r\n        isMobile: boolean\r\n    }) => (\r\n        <div className=\"space-y-1\">\r\n            <button\r\n                onClick={() => section.items.length > 0 ? onToggle(section.id) : onScroll(section.id, isMobile)}\r\n                className=\"flex items-center justify-between w-full text-left font-semibold text-gray-900 hover:text-blue-600 transition-colors py-2 group\" // Increased touch target py-2\r\n            >\r\n                <span className=\"truncate pr-2\">{section.title}</span>\r\n                {section.items.length > 0 && (\r\n                    <ChevronRight\r\n                        className={`h-4 w-4 flex-shrink-0 text-gray-400 transition-transform duration-200 group-hover:text-blue-500 ${isOpen ? \"rotate-90\" : \"\"}`}\r\n                    />\r\n                )}\r\n            </button>\r\n\r\n            {isOpen && (\r\n                <div className=\"space-y-1 ml-2 border-l-2 border-slate-100 pl-2\"> {/* Removed heavy animate-in for performance */}\r\n                    {section.items.map((item) => (\r\n                        <button\r\n                            key={item.id}\r\n                            onClick={() => onScroll(item.id, isMobile)}\r\n                            className=\"block text-left w-full text-sm text-gray-500 hover:text-blue-600 hover:bg-slate-50 py-2 px-2 rounded transition-colors truncate\" // Increased touch target py-2\r\n                            title={item.text}\r\n                        >\r\n                            {item.text}\r\n                        </button>\r\n                    ))}\r\n                    {section.items.length === 0 && (\r\n                        <p className=\"text-xs text-gray-300 italic px-2 py-1\">No subsections</p>\r\n                    )}\r\n                </div>\r\n            )}\r\n        </div>\r\n    ));\r\n    SidebarItem.displayName = \"SidebarItem\";\r\n\r\n    const renderSidebarContent = (isMobile = false) => (\r\n        <nav className=\"space-y-2 pb-8\"> {/* Reduced space-y */}\r\n            {filteredToc.length > 0 ? (\r\n                filteredToc.map((section) => (\r\n                    <SidebarItem\r\n                        key={section.id}\r\n                        section={section}\r\n                        isOpen={!!openSections[section.id]}\r\n                        onToggle={toggleSection}\r\n                        onScroll={scrollToSection}\r\n                        isMobile={isMobile}\r\n                    />\r\n                ))\r\n            ) : (\r\n                <p className=\"text-sm text-gray-400 text-center py-4\">No results found</p>\r\n            )}\r\n        </nav>\r\n    );\r\n\r\n    return (\r\n        <div className=\"flex-1 max-w-7xl mx-auto w-full flex items-start relative px-4 sm:px-6 lg:px-8\">\r\n            {/* Sidebar (Desktop) */}\r\n            <aside className=\"hidden lg:block w-72 sticky top-20 h-[calc(100vh-6rem)] overflow-y-auto border-r border-gray-100 pr-6 mt-8 scrollbar-thin scrollbar-thumb-gray-200 scrollbar-track-transparent\">\r\n                <div className=\"mb-8 relative\">\r\n                    <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400\" />\r\n                    <input\r\n                        type=\"text\"\r\n                        placeholder=\"Filter documentation...\"\r\n                        className=\"w-full pl-9 pr-4 py-2.5 text-sm bg-gray-50 border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-all placeholder:text-gray-400\"\r\n                        value={searchQuery}\r\n                        onChange={(e) => setSearchQuery(e.target.value)}\r\n                    />\r\n                </div>\r\n                {renderSidebarContent(false)}\r\n            </aside>\r\n\r\n            {/* Mobile Sidebar (Drawer) */}\r\n            <div className=\"lg:hidden fixed bottom-6 right-6 z-50\">\r\n                <Sheet open={openMobileMenu} onOpenChange={setOpenMobileMenu}>\r\n                    <SheetTrigger asChild>\r\n                        <Button size=\"icon\" className=\"h-14 w-14 rounded-full shadow-lg shadow-blue-600/20 bg-blue-600 hover:bg-blue-700 text-white transition-transform hover:scale-105 active:scale-95\">\r\n                            <Menu className=\"h-6 w-6\" />\r\n                        </Button>\r\n                    </SheetTrigger>\r\n                    <SheetContent side=\"left\" className=\"w-[85vw] sm:w-[400px] p-0 flex flex-col\"> {/* Adjusted width for mobile */}\r\n                        <div className=\"p-6 border-b bg-gray-50/50\">\r\n                            <h2 className=\"text-lg font-bold text-gray-900\">Documentation</h2>\r\n                            <p className=\"text-xs text-gray-500 mt-1\">Navigate through sections</p>\r\n                        </div>\r\n                        <div className=\"p-4 flex-1 overflow-y-auto overscroll-contain\"> {/* Added overscroll-contain */}\r\n                            <div className=\"mb-6 relative\">\r\n                                <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400\" />\r\n                                <input\r\n                                    type=\"text\"\r\n                                    placeholder=\"Search topic...\"\r\n                                    className=\"w-full pl-9 pr-4 py-3 text-base bg-gray-50 border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500\" // Larger text/padding for mobile\r\n                                    value={searchQuery}\r\n                                    onChange={(e) => setSearchQuery(e.target.value)}\r\n                                />\r\n                            </div>\r\n                            {renderSidebarContent(true)}\r\n                        </div>\r\n                    </SheetContent>\r\n                </Sheet>\r\n            </div>\r\n\r\n            {/* Main Content */}\r\n            <main className=\"flex-1 min-w-0 py-8 lg:pl-12\">\r\n                <div className=\"bg-blue-50 border-l-4 border-blue-500 p-4 mb-8 rounded-r-lg\">\r\n                    <div className=\"flex\">\r\n                        <div className=\"flex-shrink-0\">\r\n                            <svg className=\"h-5 w-5 text-blue-400\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\r\n                                <path fillRule=\"evenodd\" d=\"M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z\" clipRule=\"evenodd\" />\r\n                            </svg>\r\n                        </div>\r\n                        <div className=\"ml-3\">\r\n                            <p className=\"text-sm text-blue-700\">\r\n                                For the most up-to-date API reference and interactive testing, please check the <Link href=\"/swagger\" className=\"font-medium underline hover:text-blue-600\">Swagger UI</Link> or the <Link href=\"/dashboard/api-docs\" className=\"font-medium underline hover:text-blue-600\">Dashboard API Docs</Link>.\r\n                            </p>\r\n                        </div>\r\n                    </div>\r\n                </div>\r\n\r\n                <article className=\"prose prose-slate prose-blue max-w-none prose-headings:scroll-mt-24 prose-pre:p-0 prose-pre:bg-transparent prose-pre:border-none break-words\"> {/* Added break-words */}\r\n                    <ReactMarkdown\r\n                        remarkPlugins={[remarkGfm]}\r\n                        components={{\r\n                            h2: ({ node, ...props }) => {\r\n                                const id = props.children?.toString().toLowerCase().replace(/[^\\w]+/g, '-') || '';\r\n                                return <h2 id={id} {...props} className=\"text-2xl font-bold mt-12 mb-6 border-b pb-2 scroll-mt-24\" />\r\n                            },\r\n                            h3: ({ node, ...props }) => {\r\n                                const id = props.children?.toString().toLowerCase().replace(/[^\\w]+/g, '-') || '';\r\n                                return <h3 id={id} {...props} className=\"text-xl font-semibold mt-8 mb-4 scroll-mt-24\" />\r\n                            },\r\n                            code: ({ node, inline, className, children, ...props }: any) => {\r\n                                const match = /language-(\\w+)/.exec(className || '');\r\n                                return !inline && match ? (\r\n                                    <div className=\"rounded-lg overflow-hidden my-6 border border-gray-200 shadow-sm\">\r\n                                        <div className=\"bg-gray-800 px-4 py-2 flex items-center justify-between\">\r\n                                            <span className=\"text-xs font-mono text-gray-400 capitalize\">{match[1]}</span>\r\n                                        </div>\r\n                                        <SyntaxHighlighter\r\n                                            style={atomOneDark}\r\n                                            language={match[1]}\r\n                                            PreTag=\"div\"\r\n                                            customStyle={{ margin: 0, padding: '1rem', borderRadius: 0, fontSize: '0.9em' }}\r\n                                            {...props}\r\n                                        >\r\n                                            {String(children).replace(/\\n$/, '')}\r\n                                        </SyntaxHighlighter>\r\n                                    </div>\r\n                                ) : (\r\n                                    <code className=\"bg-gray-100 text-gray-800 px-1.5 py-0.5 rounded text-sm font-mono border border-gray-200 break-all\" {...props}> {/* break-all for inline code */}\r\n                                        {children}\r\n                                    </code>\r\n                                )\r\n                            },\r\n                            table: ({ node, ...props }) => (\r\n                                <div className=\"overflow-x-auto my-6 border rounded-lg shadow-sm\">\r\n                                    <table {...props} className=\"min-w-full divide-y divide-gray-200\" />\r\n                                </div>\r\n                            ),\r\n                            thead: ({ node, ...props }) => <thead {...props} className=\"bg-gray-50\" />,\r\n                            th: ({ node, ...props }) => <th {...props} className=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\" />,\r\n                            td: ({ node, ...props }) => <td {...props} className=\"px-6 py-4 whitespace-nowrap text-sm text-gray-500\" />,\r\n                            pre: ({ node, ...props }) => <pre {...props} /> // Passthrough to code block handler\r\n                        }}\r\n                    >\r\n                        {content}\r\n                    </ReactMarkdown>\r\n                </article>\r\n\r\n                <footer className=\"mt-20 pt-8 border-t text-center text-sm text-gray-400\">\r\n                    <p>┬⌐ {new Date().getFullYear()} WA-AKG. All rights reserved.</p>\r\n                </footer>\r\n            </main>\r\n        </div>\r\n    );\r\n}\r\n\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\docs\\page.tsx","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'ReactMarkdown' is defined but never used.","line":3,"column":8,"nodeType":"Identifier","messageId":"unusedVar","endLine":3,"endColumn":21,"suggestions":[{"messageId":"removeUnusedImportDeclaration","data":{"varName":"ReactMarkdown"},"fix":{"range":[48,91],"text":""},"desc":"Remove unused import declaration."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'remarkGfm' is defined but never used.","line":4,"column":8,"nodeType":"Identifier","messageId":"unusedVar","endLine":4,"endColumn":17,"suggestions":[{"messageId":"removeUnusedImportDeclaration","data":{"varName":"remarkGfm"},"fix":{"range":[93,128],"text":""},"desc":"Remove unused import declaration."}]}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import fs from 'fs';\r\nimport path from 'path';\r\nimport ReactMarkdown from 'react-markdown';\r\nimport remarkGfm from 'remark-gfm';\r\nimport Link from 'next/link';\r\nimport { DocsClient } from './docs-client';\r\n\r\nexport const metadata = {\r\n    title: 'Public API Documentation - WA-AKG',\r\n    description: 'Complete API reference for WA-AKG WhatsApp Gateway',\r\n};\r\n\r\n// Interface for Nested TOC\r\nexport interface TocItem {\r\n    text: string;\r\n    id: string;\r\n}\r\n\r\nexport interface TocSection {\r\n    title: string;\r\n    id: string;\r\n    items: TocItem[];\r\n}\r\n\r\nexport default async function PublicDocsPage() {\r\n    const filePath = path.join(process.cwd(), 'docs', 'API_DOCUMENTATION.md');\r\n    const packagePath = path.join(process.cwd(), 'package.json');\r\n    let content = '';\r\n    let version = 'v1.0.0';\r\n\r\n    try {\r\n        content = fs.readFileSync(filePath, 'utf8');\r\n        const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8'));\r\n        version = `v${packageJson.version}`;\r\n    } catch (err) {\r\n        content = '# Error\\n\\nCould not load documentation file.';\r\n        console.error(\"Error loading docs:\", err);\r\n    }\r\n\r\n    // Nested TOC Generation\r\n    const toc: TocSection[] = [];\r\n    let currentSection: TocSection | null = null;\r\n\r\n    content.split('\\n').forEach(line => {\r\n        if (line.startsWith('## ')) {\r\n            // H2 - New Section\r\n            const text = line.replace(/^## /, '').trim();\r\n            const id = text.toLowerCase().replace(/[^\\w]+/g, '-');\r\n\r\n            // If we have a current section, push it to toc\r\n            if (currentSection) {\r\n                toc.push(currentSection);\r\n            }\r\n\r\n            currentSection = {\r\n                title: text,\r\n                id: id,\r\n                items: []\r\n            };\r\n        } else if (line.startsWith('### ') && currentSection) {\r\n            // H3 - Item in current section\r\n            const text = line.replace(/^### /, '').trim();\r\n            const id = text.toLowerCase().replace(/[^\\w]+/g, '-');\r\n            currentSection.items.push({ text, id });\r\n        }\r\n    });\r\n\r\n    // Push the last section if exists\r\n    if (currentSection) {\r\n        toc.push(currentSection);\r\n    }\r\n\r\n    return (\r\n        <div className=\"min-h-screen bg-gray-50 flex flex-col\">\r\n            {/* Header */}\r\n            <header className=\"bg-white border-b sticky top-0 z-30 shadow-sm/50\">\r\n                <div className=\"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-16 flex items-center justify-between\">\r\n                    <div className=\"flex items-center gap-2\">\r\n                        <span className=\"text-xl font-extrabold bg-gradient-to-r from-blue-600 to-indigo-600 bg-clip-text text-transparent\">\r\n                            WA-AKG\r\n                        </span>\r\n                        <span className=\"px-2.5 py-0.5 rounded-full bg-blue-100 text-blue-700 text-xs font-semibold tracking-wide border border-blue-200\">\r\n                            {version}\r\n                        </span>\r\n                    </div>\r\n                    <div className=\"flex items-center gap-4\">\r\n                        <Link\r\n                            href=\"/swagger\"\r\n                            className=\"text-sm font-medium text-gray-500 hover:text-blue-600 transition-colors\"\r\n                        >\r\n                            Swagger UI\r\n                        </Link>\r\n                        <Link\r\n                            href=\"/dashboard\"\r\n                            className=\"text-sm font-medium px-4 py-2 bg-slate-900 text-white rounded-lg hover:bg-slate-800 transition-all shadow-md hover:shadow-lg\"\r\n                        >\r\n                            Dashboard\r\n                        </Link>\r\n                    </div>\r\n                </div>\r\n            </header>\r\n\r\n            <DocsClient content={content} toc={toc} />\r\n        </div>\r\n    );\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\icon.tsx","messages":[{"ruleId":"prefer-const","severity":2,"message":"'color' is never reassigned. Use 'const' instead.","line":18,"column":9,"nodeType":"Identifier","messageId":"useConst","endLine":18,"endColumn":14,"fix":{"range":[399,421],"text":"const color = \"#16a34a\";"}},{"ruleId":"@typescript-eslint/ban-ts-comment","severity":2,"message":"Use \"@ts-expect-error\" instead of \"@ts-ignore\", as \"@ts-ignore\" will do nothing if the following line is error-free.","line":22,"column":9,"nodeType":"Line","messageId":"tsIgnoreInsteadOfExpectError","endLine":22,"endColumn":22,"suggestions":[{"messageId":"replaceTsIgnoreWithTsExpectError","fix":{"range":[489,502],"text":"// @ts-expect-error"},"desc":"Replace \"@ts-ignore\" with \"@ts-expect-error\"."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":1,"fixableWarningCount":0,"source":"import { ImageResponse } from \"next/og\";\r\nimport { prisma } from \"@/lib/prisma\";\r\n\r\n// Use nodejs runtime to allow Prisma access\r\nexport const runtime = \"nodejs\";\r\n\r\n// Image metadata\r\nexport const size = {\r\n    width: 32,\r\n    height: 32,\r\n};\r\nexport const contentType = \"image/png\";\r\n\r\n// Image generation\r\nexport default async function Icon() {\r\n    // Default config\r\n    let letter = \"W\";\r\n    let color = \"#16a34a\"; // green-600\r\n\r\n    try {\r\n        // Fetch system config\r\n        // @ts-ignore\r\n        const config = await prisma.systemConfig.findUnique({\r\n            where: { id: \"default\" }\r\n        });\r\n\r\n        if (config?.appName) {\r\n            letter = config.appName.charAt(0).toUpperCase();\r\n        }\r\n    } catch (e) {\r\n        console.error(\"Failed to fetch favicon config\", e);\r\n    }\r\n\r\n    return new ImageResponse(\r\n        (\r\n            // ImageResponse JSX element\r\n            <div\r\n                style={{\r\n                    fontSize: 20,\r\n                    fontWeight: 800,\r\n                    background: color,\r\n                    width: \"100%\",\r\n                    height: \"100%\",\r\n                    display: \"flex\",\r\n                    alignItems: \"center\",\r\n                    justifyContent: \"center\",\r\n                    color: \"white\",\r\n                    borderRadius: \"20%\", // Rounded square looks more app-like\r\n                    fontFamily: 'sans-serif'\r\n                }}\r\n            >\r\n                {letter}\r\n            </div>\r\n        ),\r\n        // ImageResponse options\r\n        {\r\n            ...size,\r\n        }\r\n    );\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\layout.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\privacy\\page.tsx","messages":[{"ruleId":"react/no-unescaped-entities","severity":2,"message":"`'` can be escaped with `&apos;`, `&lsquo;`, `&#39;`, `&rsquo;`.","line":74,"column":131,"nodeType":"JSXText","messageId":"unescapedEntityAlts","suggestions":[{"messageId":"replaceWithAlt","data":{"alt":"&apos;"},"fix":{"range":[5519,5781],"text":" library to communicate directly with WhatsApp&apos;s servers. By using this gateway, your server will establish a direct web-socket connection to WhatsApp. Please be aware that your use of WhatsApp is still subject to Meta's Privacy Policy.\r\n                        "},"desc":"Replace with `&apos;`."},{"messageId":"replaceWithAlt","data":{"alt":"&lsquo;"},"fix":{"range":[5519,5781],"text":" library to communicate directly with WhatsApp&lsquo;s servers. By using this gateway, your server will establish a direct web-socket connection to WhatsApp. Please be aware that your use of WhatsApp is still subject to Meta's Privacy Policy.\r\n                        "},"desc":"Replace with `&lsquo;`."},{"messageId":"replaceWithAlt","data":{"alt":"&#39;"},"fix":{"range":[5519,5781],"text":" library to communicate directly with WhatsApp&#39;s servers. By using this gateway, your server will establish a direct web-socket connection to WhatsApp. Please be aware that your use of WhatsApp is still subject to Meta's Privacy Policy.\r\n                        "},"desc":"Replace with `&#39;`."},{"messageId":"replaceWithAlt","data":{"alt":"&rsquo;"},"fix":{"range":[5519,5781],"text":" library to communicate directly with WhatsApp&rsquo;s servers. By using this gateway, your server will establish a direct web-socket connection to WhatsApp. Please be aware that your use of WhatsApp is still subject to Meta's Privacy Policy.\r\n                        "},"desc":"Replace with `&rsquo;`."}]},{"ruleId":"react/no-unescaped-entities","severity":2,"message":"`'` can be escaped with `&apos;`, `&lsquo;`, `&#39;`, `&rsquo;`.","line":74,"column":303,"nodeType":"JSXText","messageId":"unescapedEntityAlts","suggestions":[{"messageId":"replaceWithAlt","data":{"alt":"&apos;"},"fix":{"range":[5519,5781],"text":" library to communicate directly with WhatsApp's servers. By using this gateway, your server will establish a direct web-socket connection to WhatsApp. Please be aware that your use of WhatsApp is still subject to Meta&apos;s Privacy Policy.\r\n                        "},"desc":"Replace with `&apos;`."},{"messageId":"replaceWithAlt","data":{"alt":"&lsquo;"},"fix":{"range":[5519,5781],"text":" library to communicate directly with WhatsApp's servers. By using this gateway, your server will establish a direct web-socket connection to WhatsApp. Please be aware that your use of WhatsApp is still subject to Meta&lsquo;s Privacy Policy.\r\n                        "},"desc":"Replace with `&lsquo;`."},{"messageId":"replaceWithAlt","data":{"alt":"&#39;"},"fix":{"range":[5519,5781],"text":" library to communicate directly with WhatsApp's servers. By using this gateway, your server will establish a direct web-socket connection to WhatsApp. Please be aware that your use of WhatsApp is still subject to Meta&#39;s Privacy Policy.\r\n                        "},"desc":"Replace with `&#39;`."},{"messageId":"replaceWithAlt","data":{"alt":"&rsquo;"},"fix":{"range":[5519,5781],"text":" library to communicate directly with WhatsApp's servers. By using this gateway, your server will establish a direct web-socket connection to WhatsApp. Please be aware that your use of WhatsApp is still subject to Meta&rsquo;s Privacy Policy.\r\n                        "},"desc":"Replace with `&rsquo;`."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import Link from \"next/link\";\r\nimport { ArrowLeft, Lock, Shield } from \"lucide-react\";\r\n\r\nexport const metadata = {\r\n    title: \"Privacy Policy | WA-AKG\",\r\n    description: \"Privacy Policy and Data Handling for WA-AKG.\",\r\n};\r\n\r\nexport default function PrivacyPage() {\r\n    return (\r\n        <div className=\"min-h-screen bg-background relative overflow-hidden py-24 selection:bg-primary/30 selection:text-primary-foreground\">\r\n            {/* Ambient background glows */}\r\n            <div className=\"fixed top-0 right-1/4 translate-x-1/2 -translate-y-1/2 w-[40rem] h-[40rem] bg-blue-500/5 dark:bg-blue-500/10 rounded-full blur-[120px] pointer-events-none -z-10\" />\r\n            <div className=\"fixed bottom-0 left-1/4 -translate-x-1/2 translate-y-1/2 w-[30rem] h-[30rem] bg-emerald-500/5 dark:bg-emerald-600/10 rounded-full blur-[100px] pointer-events-none -z-10\" />\r\n\r\n            <div className=\"container max-w-4xl px-4 mx-auto relative z-10\">\r\n\r\n                <Link href=\"/\" className=\"inline-flex items-center text-sm font-medium text-muted-foreground hover:text-foreground mb-8 transition-colors group\">\r\n                    <ArrowLeft className=\"mr-2 h-4 w-4 transition-transform group-hover:-translate-x-1\" />\r\n                    Back to Home\r\n                </Link>\r\n\r\n                <div className=\"glass-panel p-8 md:p-12 rounded-3xl shadow-xl shadow-black/5 dark:shadow-black/20 animate-in fade-in slide-in-from-bottom-8 duration-700\">\r\n                    <div className=\"flex items-center gap-4 mb-8\">\r\n                        <div className=\"p-3 bg-blue-500/10 rounded-2xl\">\r\n                            <Shield className=\"h-8 w-8 text-blue-500\" />\r\n                        </div>\r\n                        <div>\r\n                            <h1 className=\"text-3xl md:text-5xl font-bold tracking-tight text-foreground\">Privacy Policy</h1>\r\n                            <p className=\"text-muted-foreground mt-2\">Effective Date: {new Date().toLocaleDateString()}</p>\r\n                        </div>\r\n                    </div>\r\n\r\n                    <div className=\"prose prose-slate dark:prose-invert max-w-none prose-headings:font-bold prose-headings:tracking-tight prose-a:text-primary hover:prose-a:text-primary/80 prose-p:leading-relaxed\">\r\n\r\n                        <p className=\"lead text-lg text-muted-foreground mb-8\">\r\n                            At WA-AKG, we believe that your data is your property. This Privacy Policy details the strict boundaries regarding how information is handled when using our open-source, self-hosted WhatsApp Gateway.\r\n                        </p>\r\n\r\n                        <h2 className=\"flex items-center gap-2 mt-8 text-2xl border-b pb-2\">\r\n                            <Lock className=\"h-6 w-6 text-blue-500\" />\r\n                            1. Zero-Tracking Architecture\r\n                        </h2>\r\n                        <p>\r\n                            Because WA-AKG is designed to be <strong>self-hosted</strong>, all core data processing occurs exclusively on the hardware where you deploy the application.\r\n                        </p>\r\n                        <ul>\r\n                            <li><strong>No Centralized Telemetry:</strong> The creators of WA-AKG do not receive telemetry, analytics, or usage reports about your WhatsApp interactions.</li>\r\n                            <li><strong>Absolute Data Ownership:</strong> Your contacts, messages, schedules, and auto-replies remain in your own database. We cannot and will not access it.</li>\r\n                        </ul>\r\n\r\n                        <h2 className=\"mt-8 text-2xl border-b pb-2\">2. Data We Process Locally</h2>\r\n                        <p>\r\n                            When you deploy the gateway, the application running on your server interacts with:\r\n                        </p>\r\n                        <ul>\r\n                            <li><strong>Authentication Credentials:</strong> Passwords you create for the dashboard are securely hashed using bcrypt before being stored in your local database.</li>\r\n                            <li><strong>WhatsApp Sessions:</strong> WA-AKG acts as a bridge to WhatsApp Web. The session tokens (keys) necessary to maintain this connection are stored locally on your server.</li>\r\n                            <li><strong>Communication Logs:</strong> Messages sent and received via the gateway are logged within your local database to provide you with historical data and webhook functionality.</li>\r\n                        </ul>\r\n\r\n                        <h2 className=\"mt-8 text-2xl border-b pb-2\">3. Protecting Your Information</h2>\r\n                        <p>\r\n                            While WA-AKG is built with modern security practices, the ultimate safety of your data depends on your hosting environment. We strongly recommend:\r\n                        </p>\r\n                        <ul>\r\n                            <li>Deploying the application behind a reverse proxy with enforced <strong>SSL/TLS encryption</strong> (HTTPS).</li>\r\n                            <li>Securing the host server with firewalls and SSH key authentication.</li>\r\n                            <li>Keeping the underlying operating system and Node.js environment constantly updated.</li>\r\n                        </ul>\r\n\r\n                        <h2 className=\"mt-8 text-2xl border-b pb-2\">4. Third-Party Integrations</h2>\r\n                        <p>\r\n                            WA-AKG utilizes the <code>@whiskeysockets/baileys</code> library to communicate directly with WhatsApp's servers. By using this gateway, your server will establish a direct web-socket connection to WhatsApp. Please be aware that your use of WhatsApp is still subject to Meta's Privacy Policy.\r\n                        </p>\r\n\r\n                        <div className=\"mt-12 p-6 bg-blue-500/5 rounded-2xl border border-blue-500/10\">\r\n                            <p className=\"font-semibold mb-2\">Need Further Details?</p>\r\n                            <p className=\"text-sm text-muted-foreground mb-0\">If you have specific questions about data handling or wish to audit the code, please visit our <Link href=\"https://github.com/mrifqidaffaaditya/WA-AKG\">GitHub Repository</Link>.</p>\r\n                        </div>\r\n                    </div>\r\n                </div>\r\n            </div>\r\n        </div>\r\n    );\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\swagger\\page.tsx","messages":[{"ruleId":"react-hooks/set-state-in-effect","severity":2,"message":"Error: Calling setState synchronously within an effect can trigger cascading renders\n\nEffects are intended to synchronize state between React and external systems such as manually updating the DOM, state management libraries, or other platform APIs. In general, the body of an effect should do one or both of the following:\n* Update external systems with the latest state from React.\n* Subscribe for updates from some external system, calling setState in a callback function when external state changes.\n\nCalling setState synchronously within an effect body causes cascading renders that can hurt performance, and is not recommended. (https://react.dev/learn/you-might-not-need-an-effect).\n\nC:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\swagger\\page.tsx:18:13\n  16 |         const isAuth = sessionStorage.getItem(\"swagger_auth\") === \"true\";\n  17 |         if (isAuth) {\n> 18 |             setAuthorized(true);\n     |             ^^^^^^^^^^^^^ Avoid calling setState() directly within an effect\n  19 |         }\n  20 |         setLoading(false);\n  21 |     }, []);","line":18,"column":13,"nodeType":null,"endLine":18,"endColumn":26}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\"use client\";\r\n\r\nimport { useEffect, useState } from \"react\";\r\nimport SwaggerUI from \"swagger-ui-react\";\r\nimport \"swagger-ui-react/swagger-ui.css\";\r\n\r\nexport default function ApiDocsPage() {\r\n    const [authorized, setAuthorized] = useState(false);\r\n    const [loading, setLoading] = useState(true);\r\n    const [username, setUsername] = useState(\"\");\r\n    const [password, setPassword] = useState(\"\");\r\n    const [error, setError] = useState(\"\");\r\n\r\n    useEffect(() => {\r\n        // Check if already authorized via session storage\r\n        const isAuth = sessionStorage.getItem(\"swagger_auth\") === \"true\";\r\n        if (isAuth) {\r\n            setAuthorized(true);\r\n        }\r\n        setLoading(false);\r\n    }, []);\r\n\r\n    const handleLogin = (e: React.FormEvent) => {\r\n        e.preventDefault();\r\n\r\n        // Basic auth - compare with env variables or hardcoded (for demo)\r\n        const validUsername = process.env.NEXT_PUBLIC_SWAGGER_USERNAME || \"admin\";\r\n        const validPassword = process.env.NEXT_PUBLIC_SWAGGER_PASSWORD || \"admin123\";\r\n\r\n        if (username === validUsername && password === validPassword) {\r\n            sessionStorage.setItem(\"swagger_auth\", \"true\");\r\n            setAuthorized(true);\r\n            setError(\"\");\r\n        } else {\r\n            setError(\"Invalid credentials\");\r\n        }\r\n    };\r\n\r\n    const handleLogout = () => {\r\n        sessionStorage.removeItem(\"swagger_auth\");\r\n        setAuthorized(false);\r\n        setUsername(\"\");\r\n        setPassword(\"\");\r\n    };\r\n\r\n    if (loading) {\r\n        return (\r\n            <div className=\"flex items-center justify-center min-h-screen bg-gray-50\">\r\n                <div className=\"text-gray-600\">Loading...</div>\r\n            </div>\r\n        );\r\n    }\r\n\r\n    if (!authorized) {\r\n        return (\r\n            <div className=\"flex items-center justify-center min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100\">\r\n                <div className=\"bg-white p-8 rounded-lg shadow-xl w-full max-w-md\">\r\n                    <div className=\"text-center mb-6\">\r\n                        <h1 className=\"text-3xl font-bold text-gray-800 mb-2\">\r\n                            WA-AKG API Documentation\r\n                        </h1>\r\n                        <p className=\"text-gray-600 text-sm\">\r\n                            Please authenticate to access Swagger UI\r\n                        </p>\r\n                    </div>\r\n\r\n                    <form onSubmit={handleLogin} className=\"space-y-4\">\r\n                        <div>\r\n                            <label className=\"block text-sm font-medium text-gray-700 mb-2\">\r\n                                Username\r\n                            </label>\r\n                            <input\r\n                                type=\"text\"\r\n                                value={username}\r\n                                onChange={(e) => setUsername(e.target.value)}\r\n                                className=\"w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none\"\r\n                                placeholder=\"Enter username\"\r\n                                required\r\n                            />\r\n                        </div>\r\n\r\n                        <div>\r\n                            <label className=\"block text-sm font-medium text-gray-700 mb-2\">\r\n                                Password\r\n                            </label>\r\n                            <input\r\n                                type=\"password\"\r\n                                value={password}\r\n                                onChange={(e) => setPassword(e.target.value)}\r\n                                className=\"w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none\"\r\n                                placeholder=\"Enter password\"\r\n                                required\r\n                            />\r\n                        </div>\r\n\r\n                        {error && (\r\n                            <div className=\"bg-red-50 border border-red-200 text-red-700 px-4 py-3 rounded-lg text-sm\">\r\n                                {error}\r\n                            </div>\r\n                        )}\r\n\r\n                        <button\r\n                            type=\"submit\"\r\n                            className=\"w-full bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded-lg transition-colors\"\r\n                        >\r\n                            Access Documentation\r\n                        </button>\r\n                    </form>\r\n\r\n                    <div className=\"mt-6 text-center text-sm text-gray-500\">\r\n                        <p>Default credentials:</p>\r\n                        <p className=\"font-mono mt-1\">\r\n                            Username: <span className=\"font-semibold\">admin</span> |\r\n                            Password: <span className=\"font-semibold\">admin123</span>\r\n                        </p>\r\n                    </div>\r\n                </div>\r\n            </div>\r\n        );\r\n    }\r\n\r\n    return (\r\n        <div className=\"min-h-screen bg-white\">\r\n            <div className=\"bg-gradient-to-r from-blue-600 to-indigo-600 text-white p-4 shadow-lg\">\r\n                <div className=\"container mx-auto flex justify-between items-center\">\r\n                    <div>\r\n                        <h1 className=\"text-2xl font-bold\">WA-AKG API Documentation</h1>\r\n                        <p className=\"text-blue-100 text-sm mt-1\">\r\n                            Interactive API documentation with 58+ endpoints\r\n                        </p>\r\n                    </div>\r\n                    <button\r\n                        onClick={handleLogout}\r\n                        className=\"bg-white/20 hover:bg-white/30 px-4 py-2 rounded-lg transition-colors text-sm font-medium\"\r\n                    >\r\n                        Logout\r\n                    </button>\r\n                </div>\r\n            </div>\r\n\r\n            <div className=\"container mx-auto\">\r\n                <SwaggerUI url=\"/api/docs\" />\r\n            </div>\r\n        </div>\r\n    );\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\app\\terms\\page.tsx","messages":[{"ruleId":"react/no-unescaped-entities","severity":2,"message":"`'` can be escaped with `&apos;`, `&lsquo;`, `&#39;`, `&rsquo;`.","line":55,"column":50,"nodeType":"JSXText","messageId":"unescapedEntityAlts","suggestions":[{"messageId":"replaceWithAlt","data":{"alt":"&apos;"},"fix":{"range":[3818,4048],"text":"\r\n                            When utilizing WA-AKG&apos;s API, auto-replies, and broadcasting capabilities, you agree to abide by WhatsApp's official Terms of Service and Anti-Spam policies. You agree not to:\r\n                        "},"desc":"Replace with `&apos;`."},{"messageId":"replaceWithAlt","data":{"alt":"&lsquo;"},"fix":{"range":[3818,4048],"text":"\r\n                            When utilizing WA-AKG&lsquo;s API, auto-replies, and broadcasting capabilities, you agree to abide by WhatsApp's official Terms of Service and Anti-Spam policies. You agree not to:\r\n                        "},"desc":"Replace with `&lsquo;`."},{"messageId":"replaceWithAlt","data":{"alt":"&#39;"},"fix":{"range":[3818,4048],"text":"\r\n                            When utilizing WA-AKG&#39;s API, auto-replies, and broadcasting capabilities, you agree to abide by WhatsApp's official Terms of Service and Anti-Spam policies. You agree not to:\r\n                        "},"desc":"Replace with `&#39;`."},{"messageId":"replaceWithAlt","data":{"alt":"&rsquo;"},"fix":{"range":[3818,4048],"text":"\r\n                            When utilizing WA-AKG&rsquo;s API, auto-replies, and broadcasting capabilities, you agree to abide by WhatsApp's official Terms of Service and Anti-Spam policies. You agree not to:\r\n                        "},"desc":"Replace with `&rsquo;`."}]},{"ruleId":"react/no-unescaped-entities","severity":2,"message":"`'` can be escaped with `&apos;`, `&lsquo;`, `&#39;`, `&rsquo;`.","line":55,"column":133,"nodeType":"JSXText","messageId":"unescapedEntityAlts","suggestions":[{"messageId":"replaceWithAlt","data":{"alt":"&apos;"},"fix":{"range":[3818,4048],"text":"\r\n                            When utilizing WA-AKG's API, auto-replies, and broadcasting capabilities, you agree to abide by WhatsApp&apos;s official Terms of Service and Anti-Spam policies. You agree not to:\r\n                        "},"desc":"Replace with `&apos;`."},{"messageId":"replaceWithAlt","data":{"alt":"&lsquo;"},"fix":{"range":[3818,4048],"text":"\r\n                            When utilizing WA-AKG's API, auto-replies, and broadcasting capabilities, you agree to abide by WhatsApp&lsquo;s official Terms of Service and Anti-Spam policies. You agree not to:\r\n                        "},"desc":"Replace with `&lsquo;`."},{"messageId":"replaceWithAlt","data":{"alt":"&#39;"},"fix":{"range":[3818,4048],"text":"\r\n                            When utilizing WA-AKG's API, auto-replies, and broadcasting capabilities, you agree to abide by WhatsApp&#39;s official Terms of Service and Anti-Spam policies. You agree not to:\r\n                        "},"desc":"Replace with `&#39;`."},{"messageId":"replaceWithAlt","data":{"alt":"&rsquo;"},"fix":{"range":[3818,4048],"text":"\r\n                            When utilizing WA-AKG's API, auto-replies, and broadcasting capabilities, you agree to abide by WhatsApp&rsquo;s official Terms of Service and Anti-Spam policies. You agree not to:\r\n                        "},"desc":"Replace with `&rsquo;`."}]},{"ruleId":"react/no-unescaped-entities","severity":2,"message":"`\"` can be escaped with `&quot;`, `&ldquo;`, `&#34;`, `&rdquo;`.","line":58,"column":50,"nodeType":"JSXText","messageId":"unescapedEntityAlts","suggestions":[{"messageId":"replaceWithAlt","data":{"alt":"&quot;"},"fix":{"range":[4116,4221],"text":"Send unsolicited &quot;spam\" messages or bulk promotional campaigns to users who have not explicitly opted-in."},"desc":"Replace with `&quot;`."},{"messageId":"replaceWithAlt","data":{"alt":"&ldquo;"},"fix":{"range":[4116,4221],"text":"Send unsolicited &ldquo;spam\" messages or bulk promotional campaigns to users who have not explicitly opted-in."},"desc":"Replace with `&ldquo;`."},{"messageId":"replaceWithAlt","data":{"alt":"&#34;"},"fix":{"range":[4116,4221],"text":"Send unsolicited &#34;spam\" messages or bulk promotional campaigns to users who have not explicitly opted-in."},"desc":"Replace with `&#34;`."},{"messageId":"replaceWithAlt","data":{"alt":"&rdquo;"},"fix":{"range":[4116,4221],"text":"Send unsolicited &rdquo;spam\" messages or bulk promotional campaigns to users who have not explicitly opted-in."},"desc":"Replace with `&rdquo;`."}]},{"ruleId":"react/no-unescaped-entities","severity":2,"message":"`\"` can be escaped with `&quot;`, `&ldquo;`, `&#34;`, `&rdquo;`.","line":58,"column":55,"nodeType":"JSXText","messageId":"unescapedEntityAlts","suggestions":[{"messageId":"replaceWithAlt","data":{"alt":"&quot;"},"fix":{"range":[4116,4221],"text":"Send unsolicited \"spam&quot; messages or bulk promotional campaigns to users who have not explicitly opted-in."},"desc":"Replace with `&quot;`."},{"messageId":"replaceWithAlt","data":{"alt":"&ldquo;"},"fix":{"range":[4116,4221],"text":"Send unsolicited \"spam&ldquo; messages or bulk promotional campaigns to users who have not explicitly opted-in."},"desc":"Replace with `&ldquo;`."},{"messageId":"replaceWithAlt","data":{"alt":"&#34;"},"fix":{"range":[4116,4221],"text":"Send unsolicited \"spam&#34; messages or bulk promotional campaigns to users who have not explicitly opted-in."},"desc":"Replace with `&#34;`."},{"messageId":"replaceWithAlt","data":{"alt":"&rdquo;"},"fix":{"range":[4116,4221],"text":"Send unsolicited \"spam&rdquo; messages or bulk promotional campaigns to users who have not explicitly opted-in."},"desc":"Replace with `&rdquo;`."}]},{"ruleId":"react/no-unescaped-entities","severity":2,"message":"`\"` can be escaped with `&quot;`, `&ldquo;`, `&#34;`, `&rdquo;`.","line":70,"column":48,"nodeType":"JSXText","messageId":"unescapedEntityAlts","suggestions":[{"messageId":"replaceWithAlt","data":{"alt":"&quot;"},"fix":{"range":[5102,5483],"text":"\r\n                            WA-AKG is provided &quot;as is\" and without warranties of any kind. We utilize third-party libraries (such as Baileys) to connect to WhatsApp web protocols. Changes to WhatsApp's internal systems may occasionally disrupt service. We are not liable for any account suspensions or bans imposed by WhatsApp as a result of your usage.\r\n                        "},"desc":"Replace with `&quot;`."},{"messageId":"replaceWithAlt","data":{"alt":"&ldquo;"},"fix":{"range":[5102,5483],"text":"\r\n                            WA-AKG is provided &ldquo;as is\" and without warranties of any kind. We utilize third-party libraries (such as Baileys) to connect to WhatsApp web protocols. Changes to WhatsApp's internal systems may occasionally disrupt service. We are not liable for any account suspensions or bans imposed by WhatsApp as a result of your usage.\r\n                        "},"desc":"Replace with `&ldquo;`."},{"messageId":"replaceWithAlt","data":{"alt":"&#34;"},"fix":{"range":[5102,5483],"text":"\r\n                            WA-AKG is provided &#34;as is\" and without warranties of any kind. We utilize third-party libraries (such as Baileys) to connect to WhatsApp web protocols. Changes to WhatsApp's internal systems may occasionally disrupt service. We are not liable for any account suspensions or bans imposed by WhatsApp as a result of your usage.\r\n                        "},"desc":"Replace with `&#34;`."},{"messageId":"replaceWithAlt","data":{"alt":"&rdquo;"},"fix":{"range":[5102,5483],"text":"\r\n                            WA-AKG is provided &rdquo;as is\" and without warranties of any kind. We utilize third-party libraries (such as Baileys) to connect to WhatsApp web protocols. Changes to WhatsApp's internal systems may occasionally disrupt service. We are not liable for any account suspensions or bans imposed by WhatsApp as a result of your usage.\r\n                        "},"desc":"Replace with `&rdquo;`."}]},{"ruleId":"react/no-unescaped-entities","severity":2,"message":"`\"` can be escaped with `&quot;`, `&ldquo;`, `&#34;`, `&rdquo;`.","line":70,"column":54,"nodeType":"JSXText","messageId":"unescapedEntityAlts","suggestions":[{"messageId":"replaceWithAlt","data":{"alt":"&quot;"},"fix":{"range":[5102,5483],"text":"\r\n                            WA-AKG is provided \"as is&quot; and without warranties of any kind. We utilize third-party libraries (such as Baileys) to connect to WhatsApp web protocols. Changes to WhatsApp's internal systems may occasionally disrupt service. We are not liable for any account suspensions or bans imposed by WhatsApp as a result of your usage.\r\n                        "},"desc":"Replace with `&quot;`."},{"messageId":"replaceWithAlt","data":{"alt":"&ldquo;"},"fix":{"range":[5102,5483],"text":"\r\n                            WA-AKG is provided \"as is&ldquo; and without warranties of any kind. We utilize third-party libraries (such as Baileys) to connect to WhatsApp web protocols. Changes to WhatsApp's internal systems may occasionally disrupt service. We are not liable for any account suspensions or bans imposed by WhatsApp as a result of your usage.\r\n                        "},"desc":"Replace with `&ldquo;`."},{"messageId":"replaceWithAlt","data":{"alt":"&#34;"},"fix":{"range":[5102,5483],"text":"\r\n                            WA-AKG is provided \"as is&#34; and without warranties of any kind. We utilize third-party libraries (such as Baileys) to connect to WhatsApp web protocols. Changes to WhatsApp's internal systems may occasionally disrupt service. We are not liable for any account suspensions or bans imposed by WhatsApp as a result of your usage.\r\n                        "},"desc":"Replace with `&#34;`."},{"messageId":"replaceWithAlt","data":{"alt":"&rdquo;"},"fix":{"range":[5102,5483],"text":"\r\n                            WA-AKG is provided \"as is&rdquo; and without warranties of any kind. We utilize third-party libraries (such as Baileys) to connect to WhatsApp web protocols. Changes to WhatsApp's internal systems may occasionally disrupt service. We are not liable for any account suspensions or bans imposed by WhatsApp as a result of your usage.\r\n                        "},"desc":"Replace with `&rdquo;`."}]},{"ruleId":"react/no-unescaped-entities","severity":2,"message":"`'` can be escaped with `&apos;`, `&lsquo;`, `&#39;`, `&rsquo;`.","line":70,"column":200,"nodeType":"JSXText","messageId":"unescapedEntityAlts","suggestions":[{"messageId":"replaceWithAlt","data":{"alt":"&apos;"},"fix":{"range":[5102,5483],"text":"\r\n                            WA-AKG is provided \"as is\" and without warranties of any kind. We utilize third-party libraries (such as Baileys) to connect to WhatsApp web protocols. Changes to WhatsApp&apos;s internal systems may occasionally disrupt service. We are not liable for any account suspensions or bans imposed by WhatsApp as a result of your usage.\r\n                        "},"desc":"Replace with `&apos;`."},{"messageId":"replaceWithAlt","data":{"alt":"&lsquo;"},"fix":{"range":[5102,5483],"text":"\r\n                            WA-AKG is provided \"as is\" and without warranties of any kind. We utilize third-party libraries (such as Baileys) to connect to WhatsApp web protocols. Changes to WhatsApp&lsquo;s internal systems may occasionally disrupt service. We are not liable for any account suspensions or bans imposed by WhatsApp as a result of your usage.\r\n                        "},"desc":"Replace with `&lsquo;`."},{"messageId":"replaceWithAlt","data":{"alt":"&#39;"},"fix":{"range":[5102,5483],"text":"\r\n                            WA-AKG is provided \"as is\" and without warranties of any kind. We utilize third-party libraries (such as Baileys) to connect to WhatsApp web protocols. Changes to WhatsApp&#39;s internal systems may occasionally disrupt service. We are not liable for any account suspensions or bans imposed by WhatsApp as a result of your usage.\r\n                        "},"desc":"Replace with `&#39;`."},{"messageId":"replaceWithAlt","data":{"alt":"&rsquo;"},"fix":{"range":[5102,5483],"text":"\r\n                            WA-AKG is provided \"as is\" and without warranties of any kind. We utilize third-party libraries (such as Baileys) to connect to WhatsApp web protocols. Changes to WhatsApp&rsquo;s internal systems may occasionally disrupt service. We are not liable for any account suspensions or bans imposed by WhatsApp as a result of your usage.\r\n                        "},"desc":"Replace with `&rsquo;`."}]}],"suppressedMessages":[],"errorCount":7,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import Link from \"next/link\";\r\nimport { ArrowLeft, ShieldCheck, Scale } from \"lucide-react\";\r\n\r\nexport const metadata = {\r\n    title: \"Terms of Service | WA-AKG\",\r\n    description: \"Terms of Service and Usage Guidelines for WA-AKG.\",\r\n};\r\n\r\nexport default function TermsPage() {\r\n    return (\r\n        <div className=\"min-h-screen bg-background relative overflow-hidden py-24 selection:bg-primary/30 selection:text-primary-foreground\">\r\n            {/* Ambient background glows */}\r\n            <div className=\"fixed top-0 left-1/4 -translate-x-1/2 -translate-y-1/2 w-[40rem] h-[40rem] bg-emerald-500/5 dark:bg-emerald-500/10 rounded-full blur-[120px] pointer-events-none -z-10\" />\r\n            <div className=\"fixed bottom-0 right-1/4 translate-x-1/2 translate-y-1/2 w-[30rem] h-[30rem] bg-blue-500/5 dark:bg-blue-600/10 rounded-full blur-[100px] pointer-events-none -z-10\" />\r\n\r\n            <div className=\"container max-w-4xl px-4 mx-auto relative z-10\">\r\n\r\n                <Link href=\"/\" className=\"inline-flex items-center text-sm font-medium text-muted-foreground hover:text-foreground mb-8 transition-colors group\">\r\n                    <ArrowLeft className=\"mr-2 h-4 w-4 transition-transform group-hover:-translate-x-1\" />\r\n                    Back to Home\r\n                </Link>\r\n\r\n                <div className=\"glass-panel p-8 md:p-12 rounded-3xl shadow-xl shadow-black/5 dark:shadow-black/20 animate-in fade-in slide-in-from-bottom-8 duration-700\">\r\n                    <div className=\"flex items-center gap-4 mb-8\">\r\n                        <div className=\"p-3 bg-primary/10 rounded-2xl\">\r\n                            <Scale className=\"h-8 w-8 text-primary\" />\r\n                        </div>\r\n                        <div>\r\n                            <h1 className=\"text-3xl md:text-5xl font-bold tracking-tight text-foreground\">Terms of Service</h1>\r\n                            <p className=\"text-muted-foreground mt-2\">Last updated: {new Date().toLocaleDateString()}</p>\r\n                        </div>\r\n                    </div>\r\n\r\n                    <div className=\"prose prose-slate dark:prose-invert max-w-none prose-headings:font-bold prose-headings:tracking-tight prose-a:text-primary hover:prose-a:text-primary/80 prose-p:leading-relaxed\">\r\n\r\n                        <p className=\"lead text-lg text-muted-foreground mb-8\">\r\n                            Welcome to WA-AKG. By accessing or using our WhatsApp Gateway platform, you agree to be bound by these Terms. If you do not agree, please do not use the service.\r\n                        </p>\r\n\r\n                        <h2 className=\"flex items-center gap-2 mt-8 text-2xl border-b pb-2\">\r\n                            <ShieldCheck className=\"h-6 w-6 text-emerald-500\" />\r\n                            1. Data Security & Responsibility\r\n                        </h2>\r\n                        <p>\r\n                            Security forms the core of our service. As a self-hosted platform, WA-AKG ensures that your data remains strictly within your own infrastructure.\r\n                        </p>\r\n                        <ul>\r\n                            <li><strong>Your Data is Yours:</strong> We do not track, intercept, or sell your WhatsApp messages, contact lists, or session data. Your information is secure and not misused.</li>\r\n                            <li><strong>Safe Usage:</strong> You are responsible for ensuring your hardware and server environments are properly secured.</li>\r\n                            <li><strong>Authentication:</strong> You must safeguard your account credentials. Do not share your login details with unauthorized personnel.</li>\r\n                        </ul>\r\n\r\n                        <h2 className=\"mt-8 text-2xl border-b pb-2\">2. Acceptable Use Policy</h2>\r\n                        <p>\r\n                            When utilizing WA-AKG's API, auto-replies, and broadcasting capabilities, you agree to abide by WhatsApp's official Terms of Service and Anti-Spam policies. You agree not to:\r\n                        </p>\r\n                        <ul>\r\n                            <li>Send unsolicited \"spam\" messages or bulk promotional campaigns to users who have not explicitly opted-in.</li>\r\n                            <li>Use the platform to distribute malicious software, phishing links, or illegal content.</li>\r\n                            <li>Attempt to reverse-engineer the core API or overload the service with excessive requests.</li>\r\n                        </ul>\r\n\r\n                        <h2 className=\"mt-8 text-2xl border-b pb-2\">3. Account Integrity</h2>\r\n                        <p>\r\n                            WA-AKG provides tools to manage multiple WhatsApp sessions. It is crucial to monitor your active devices. If you suspect unauthorized access to your gateway dashboard, immediately change your password and revoke any connected WhatsApp sessions from your physical device.\r\n                        </p>\r\n\r\n                        <h2 className=\"mt-8 text-2xl border-b pb-2\">4. Disclaimers and Limitations</h2>\r\n                        <p>\r\n                            WA-AKG is provided \"as is\" and without warranties of any kind. We utilize third-party libraries (such as Baileys) to connect to WhatsApp web protocols. Changes to WhatsApp's internal systems may occasionally disrupt service. We are not liable for any account suspensions or bans imposed by WhatsApp as a result of your usage.\r\n                        </p>\r\n\r\n                        <div className=\"mt-12 p-6 bg-primary/5 rounded-2xl border border-primary/10\">\r\n                            <p className=\"font-semibold mb-2\">Have questions about these terms?</p>\r\n                            <p className=\"text-sm text-muted-foreground mb-0\">Please review our <Link href=\"/docs\">Documentation</Link> or reach out to the project maintainers for further clarification.</p>\r\n                        </div>\r\n                    </div>\r\n                </div>\r\n            </div>\r\n        </div>\r\n    );\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\auth.config.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":23,"column":39,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":23,"endColumn":42,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[846,849],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[846,849],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":30,"column":34,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":30,"endColumn":37,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1087,1090],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1087,1090],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import type { NextAuthConfig } from \"next-auth\";\r\n\r\nexport const authConfig = {\r\n    pages: {\r\n        signIn: '/auth/login',\r\n    },\r\n    callbacks: {\r\n        authorized({ auth, request: { nextUrl } }) {\r\n            const isLoggedIn = !!auth?.user;\r\n            const isOnDashboard = nextUrl.pathname.startsWith('/dashboard');\r\n            \r\n            if (isOnDashboard) {\r\n                if (isLoggedIn) return true;\r\n                return false; // Redirect unauthenticated users to login page\r\n            } else if (isLoggedIn && nextUrl.pathname === '/auth/login') {\r\n                return Response.redirect(new URL('/dashboard', nextUrl));\r\n            }\r\n            return true;\r\n        },\r\n        async jwt({ token, user }) {\r\n            if (user) {\r\n                token.id = user.id;\r\n                token.role = (user as any).role;\r\n            }\r\n            return token;\r\n        },\r\n        async session({ session, token }) {\r\n            if (token && session.user) {\r\n                session.user.id = token.id as string;\r\n                (session.user as any).role = token.role;\r\n            }\r\n            return session;\r\n        }\r\n    },\r\n    providers: [], // Configured in auth.ts\r\n    session: {\r\n        strategy: 'jwt'\r\n    },\r\n    trustHost: true,\r\n} satisfies NextAuthConfig;\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\chat\\chat-interface.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\chat\\chat-layout-client.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\chat\\chat-list.tsx","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":64,"column":55,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":64,"endColumn":58,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1939,1942],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1939,1942],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"prefer-const","severity":2,"message":"'updatedChats' is never reassigned. Use 'const' instead.","line":69,"column":25,"nodeType":"Identifier","messageId":"useConst","endLine":69,"endColumn":37,"fix":{"range":[2192,2226],"text":"const updatedChats = [...prevChats];"}}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":1,"fixableWarningCount":0,"source":"\"use client\";\r\n\r\nimport { useEffect, useState } from \"react\";\r\nimport { Avatar, AvatarFallback, AvatarImage } from \"@/components/ui/avatar\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { Input } from \"@/components/ui/input\";\r\nimport { Label } from \"@/components/ui/label\";\r\nimport { MessageSquarePlus } from \"lucide-react\";\r\nimport { Card } from \"@/components/ui/card\";\r\nimport { Skeleton } from \"@/components/ui/skeleton\";\r\n\r\nimport { cn } from \"@/lib/utils\";\r\nimport { io } from \"socket.io-client\";\r\n\r\ninterface ChatContact {\r\n    jid: string;\r\n    name: string | null;\r\n    notify: string | null;\r\n    profilePic: string | null;\r\n    lastMessage?: {\r\n        content: string | null;\r\n        timestamp: string;\r\n        type: string;\r\n    }\r\n}\r\n\r\ninterface ChatListProps {\r\n    sessionId: string;\r\n    onSelectChat: (jid: string, name?: string) => void;\r\n    selectedJid?: string;\r\n}\r\n\r\nexport function ChatList({ sessionId, onSelectChat, selectedJid }: ChatListProps) {\r\n    const [chats, setChats] = useState<ChatContact[]>([]);\r\n    const [loading, setLoading] = useState(true);\r\n\r\n    useEffect(() => {\r\n        const fetchChats = async () => {\r\n            try {\r\n                const res = await fetch(`/api/chat/${sessionId}`);\r\n                if (res.ok) {\r\n                    const data = await res.json();\r\n                    setChats(data);\r\n                }\r\n            } catch (error) {\r\n                console.error(\"Failed to load chats\", error);\r\n            } finally {\r\n                setLoading(false);\r\n            }\r\n        };\r\n\r\n        if (sessionId) {\r\n            fetchChats();\r\n\r\n            const socket = io({\r\n                path: \"/api/socket/io\",\r\n                addTrailingSlash: false,\r\n            });\r\n\r\n            socket.on(\"connect\", () => {\r\n                socket.emit(\"join-session\", sessionId);\r\n            });\r\n\r\n            socket.on(\"message.update\", (newMessages: any[]) => {\r\n                // We could optimise this by only updating the specific chat\r\n                // But simplified: Update last message for existing chat OR Refetch if new chat\r\n\r\n                setChats((prevChats) => {\r\n                    let updatedChats = [...prevChats];\r\n                    let needsReorder = false;\r\n\r\n                    newMessages.forEach(msg => {\r\n                        const chatIndex = updatedChats.findIndex(c => c.jid === msg.remoteJid);\r\n                        if (chatIndex !== -1) {\r\n                            // Update existing\r\n                            updatedChats[chatIndex] = {\r\n                                ...updatedChats[chatIndex],\r\n                                lastMessage: {\r\n                                    content: msg.content,\r\n                                    timestamp: msg.timestamp,\r\n                                    type: msg.type\r\n                                }\r\n                            };\r\n                            needsReorder = true;\r\n                        } else {\r\n                            // New chat - fetch all again to get profile pic etc? \r\n                            // Or just optimistic add? \r\n                            // Let's refetch to be safe for now, or just ignore until user refresh \r\n                            fetchChats();\r\n                        }\r\n                    });\r\n\r\n                    if (needsReorder) {\r\n                        updatedChats.sort((a, b) => {\r\n                            const tA = a.lastMessage?.timestamp ? new Date(a.lastMessage.timestamp).getTime() : 0;\r\n                            const tB = b.lastMessage?.timestamp ? new Date(b.lastMessage.timestamp).getTime() : 0;\r\n                            return tB - tA;\r\n                        });\r\n                    }\r\n\r\n                    return updatedChats;\r\n                });\r\n            });\r\n\r\n            return () => {\r\n                socket.disconnect();\r\n            };\r\n        }\r\n    }, [sessionId]);\r\n\r\n    const [isNewChatOpen, setIsNewChatOpen] = useState(false);\r\n    const [newChatNumber, setNewChatNumber] = useState(\"\");\r\n\r\n    if (loading) {\r\n        return <div className=\"space-y-4\">\r\n            {[1, 2, 3].map(i => <Skeleton key={i} className=\"h-16 w-full\" />)}\r\n        </div>;\r\n    }\r\n\r\n    const handleStartNewChat = () => {\r\n        if (!newChatNumber) return;\r\n        // Basic cleaning\r\n        let clean = newChatNumber.replace(/\\D/g, '');\r\n        if (clean.startsWith('0')) clean = '62' + clean.substring(1); // ID Auto-fix\r\n        const jid = `${clean}@s.whatsapp.net`;\r\n        onSelectChat(jid); // No name for new chats\r\n        setIsNewChatOpen(false);\r\n        setNewChatNumber(\"\");\r\n    };\r\n\r\n    // Helper to get display name from contact\r\n    const getContactDisplayName = (chat: ChatContact): string => {\r\n        return chat.name || chat.notify || chat.jid.split('@')[0];\r\n    };\r\n\r\n    return (\r\n        <div className=\"flex flex-col space-y-2\">\r\n            <div className=\"flex justify-between items-center mb-2 px-1\">\r\n                <h3 className=\"font-semibold text-lg\">Chats</h3>\r\n                <Button variant=\"outline\" size=\"sm\" onClick={() => setIsNewChatOpen(!isNewChatOpen)}>\r\n                    <MessageSquarePlus className=\"h-4 w-4 mr-1\" /> New\r\n                </Button>\r\n            </div>\r\n\r\n            {isNewChatOpen && (\r\n                <div className=\"p-3 bg-white border rounded-md shadow-sm mb-2 space-y-2\">\r\n                    <Label className=\"text-xs\">Phone Number (e.g. 628...)</Label>\r\n                    <div className=\"flex gap-2\">\r\n                        <Input\r\n                            placeholder=\"628123456789\"\r\n                            value={newChatNumber}\r\n                            onChange={(e) => setNewChatNumber(e.target.value)}\r\n                            className=\"h-8\"\r\n                        />\r\n                        <Button size=\"sm\" onClick={handleStartNewChat}>Go</Button>\r\n                    </div>\r\n                </div>\r\n            )}\r\n\r\n            <div className=\"overflow-y-auto h-[calc(100vh-200px)] space-y-2\">\r\n                {chats.map((chat) => {\r\n                    const displayName = getContactDisplayName(chat);\r\n                    return (\r\n                        <Card\r\n                            key={chat.jid}\r\n                            className={cn(\r\n                                \"p-3 cursor-pointer hover:bg-slate-50 transition-colors flex items-center gap-3\",\r\n                                selectedJid === chat.jid && \"bg-slate-100 border-primary\"\r\n                            )}\r\n                            onClick={() => onSelectChat(chat.jid, displayName)}\r\n                        >\r\n                            <Avatar>\r\n                                <AvatarImage src={chat.profilePic || \"\"} />\r\n                                <AvatarFallback>{displayName.slice(0, 2).toUpperCase()}</AvatarFallback>\r\n                            </Avatar>\r\n                            <div className=\"flex-1 min-w-0\">\r\n                                <div className=\"flex justify-between items-center mb-1\">\r\n                                    <h4 className=\"font-semibold text-sm truncate\">{displayName}</h4>\r\n                                    {chat.lastMessage && (\r\n                                        <span className=\"text-xs text-muted-foreground whitespace-nowrap ml-2\">\r\n                                            {new Date(chat.lastMessage.timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}\r\n                                        </span>\r\n                                    )}\r\n                                </div>\r\n                                <p className=\"text-xs text-muted-foreground block w-full truncate\">\r\n                                    {chat.lastMessage?.content\r\n                                        ? chat.lastMessage.content.length > 15\r\n                                            ? chat.lastMessage.content.slice(0, 15) + \"...\"\r\n                                            : chat.lastMessage.content\r\n                                        : \"No messages\"}\r\n\r\n                                </p>\r\n                            </div>\r\n                        </Card>\r\n                    );\r\n                })}\r\n            </div>\r\n            {chats.length === 0 && (\r\n                <div className=\"text-center text-muted-foreground py-8\">\r\n                    No chats found.\r\n                </div>\r\n            )}\r\n        </div>\r\n    );\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\chat\\chat-window.tsx","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'AvatarImage' is defined but never used.","line":4,"column":34,"nodeType":"Identifier","messageId":"unusedVar","endLine":4,"endColumn":45,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"AvatarImage"},"fix":{"range":[102,115],"text":""},"desc":"Remove unused variable \"AvatarImage\"."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'AlertCircle' is defined but never used.","line":10,"column":78,"nodeType":"Identifier","messageId":"unusedVar","endLine":10,"endColumn":89,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"AlertCircle"},"fix":{"range":[515,528],"text":""},"desc":"Remove unused variable \"AlertCircle\"."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'socket' is assigned a value but never used.","line":37,"column":12,"nodeType":"Identifier","messageId":"unusedVar","endLine":37,"endColumn":18},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'fetchMessages'. Either include it or remove the dependency array.","line":99,"column":8,"nodeType":"ArrayExpression","endLine":99,"endColumn":24,"suggestions":[{"desc":"Update the dependencies array to be: [sessionId, jid, fetchMessages]","fix":{"range":[3321,3337],"text":"[sessionId, jid, fetchMessages]"}}]},{"ruleId":"@next/next/no-img-element","severity":1,"message":"Using `<img>` could result in slower LCP and higher bandwidth. Consider using `<Image />` from `next/image` or a custom image loader to automatically optimize images. This may incur additional usage or cost from your provider. See: https://nextjs.org/docs/messages/no-img-element","line":191,"column":33,"nodeType":"JSXOpeningElement","endLine":191,"endColumn":121},{"ruleId":"@next/next/no-img-element","severity":1,"message":"Using `<img>` could result in slower LCP and higher bandwidth. Consider using `<Image />` from `next/image` or a custom image loader to automatically optimize images. This may incur additional usage or cost from your provider. See: https://nextjs.org/docs/messages/no-img-element","line":194,"column":33,"nodeType":"JSXOpeningElement","endLine":194,"endColumn":125}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":6,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\"use client\";\r\n\r\nimport { useEffect, useRef, useState } from \"react\";\r\nimport { Avatar, AvatarFallback, AvatarImage } from \"@/components/ui/avatar\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { Input } from \"@/components/ui/input\";\r\nimport { ScrollArea } from \"@/components/ui/scroll-area\";\r\nimport { Send, Paperclip } from \"lucide-react\";\r\nimport { Popover, PopoverContent, PopoverTrigger } from \"@/components/ui/popover\";\r\nimport { Image as ImageIcon, FileText, Music, Sticker as StickerIcon, Video, AlertCircle } from \"lucide-react\";\r\nimport { cn } from \"@/lib/utils\";\r\nimport { io, Socket } from \"socket.io-client\";\r\nimport { toast } from \"sonner\";\r\n\r\ninterface Message {\r\n    keyId: string;\r\n    content: string;\r\n    fromMe: boolean;\r\n    timestamp: string;\r\n    type: string;\r\n    status: string;\r\n    pushName?: string;\r\n    mediaUrl?: string;\r\n    remoteJid?: string;\r\n}\r\n\r\ninterface ChatWindowProps {\r\n    sessionId: string;\r\n    jid: string;\r\n    name?: string;\r\n}\r\n\r\nexport function ChatWindow({ sessionId, jid, name }: ChatWindowProps) {\r\n    const [messages, setMessages] = useState<Message[]>([]);\r\n    const [newMessage, setNewMessage] = useState(\"\");\r\n    const scrollRef = useRef<HTMLDivElement>(null);\r\n    const [socket, setSocket] = useState<Socket | null>(null);\r\n    const fileInputRef = useRef<HTMLInputElement>(null);\r\n    const [uploadType, setUploadType] = useState<string>(\"image\");\r\n\r\n    // Scroll to bottom helper\r\n    const scrollToBottom = (smooth = true) => {\r\n        if (scrollRef.current) {\r\n            scrollRef.current.scrollIntoView({ behavior: smooth ? \"smooth\" : \"auto\", block: \"end\" });\r\n        }\r\n    };\r\n\r\n    // Auto-scroll on messages change\r\n    useEffect(() => {\r\n        scrollToBottom();\r\n    }, [messages]);\r\n\r\n    const fetchMessages = async () => {\r\n        try {\r\n            const res = await fetch(`/api/chat/${sessionId}/${encodeURIComponent(jid)}`);\r\n            if (res.ok) {\r\n                const data = await res.json();\r\n                setMessages(data);\r\n                // Force scroll buffer\r\n                setTimeout(() => scrollToBottom(false), 100);\r\n            }\r\n        } catch (error) {\r\n            console.error(\"Failed to load messages\", error);\r\n        }\r\n    }\r\n\r\n\r\n\r\n    useEffect(() => {\r\n        // Initial Fetch\r\n        fetchMessages();\r\n\r\n        // Socket Connection\r\n        const newSocket = io({\r\n            path: \"/api/socket/io\",\r\n            addTrailingSlash: false,\r\n        });\r\n\r\n        newSocket.on(\"connect\", () => {\r\n            console.log(\"Connected to socket\");\r\n            newSocket.emit(\"join-session\", sessionId);\r\n        });\r\n\r\n        newSocket.on(\"message.update\", (newMessages: Message[]) => {\r\n            setMessages((prev) => {\r\n                // De-duplicate and sort\r\n                const combined = [...prev, ...newMessages.filter(m => m.remoteJid === jid)];\r\n                const unique = Array.from(new Map(combined.map(m => [m.keyId, m])).values());\r\n                return unique.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());\r\n            });\r\n            // Scroll will happen via the [messages] dependency\r\n        });\r\n\r\n        setSocket(newSocket);\r\n\r\n        return () => {\r\n            newSocket.disconnect();\r\n        };\r\n    }, [sessionId, jid]);\r\n\r\n    const handleSend = async () => {\r\n        if (!newMessage.trim()) return;\r\n\r\n        try {\r\n            await fetch(`/api/chat/send`, {\r\n                method: \"POST\",\r\n                headers: { \"Content-Type\": \"application/json\" },\r\n                body: JSON.stringify({\r\n                    sessionId,\r\n                    jid,\r\n                    message: { text: newMessage }\r\n                })\r\n            });\r\n            setNewMessage(\"\");\r\n            fetchMessages(); // Refresh immediately\r\n        } catch (e) {\r\n            console.error(e);\r\n        }\r\n    };\r\n\r\n    const handleFileUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {\r\n        const file = e.target.files?.[0];\r\n        if (!file) return;\r\n\r\n        const formData = new FormData();\r\n        formData.append(\"file\", file);\r\n        formData.append(\"type\", uploadType);\r\n        // formData.append(\"caption\", newMessage); // Optional: Send current text as caption\r\n\r\n        try {\r\n            toast.info(\"Sending...\");\r\n            const res = await fetch(`/api/messages/${sessionId}/${encodeURIComponent(jid)}/media`, {\r\n                method: \"POST\",\r\n                body: formData\r\n            });\r\n\r\n            if (!res.ok) throw new Error(\"Failed to send media\");\r\n            toast.success(\"Sent!\");\r\n            // Socket will handle update\r\n        } catch (error) {\r\n            console.error(error);\r\n            toast.error(\"Failed to send media\");\r\n        } finally {\r\n            if (fileInputRef.current) fileInputRef.current.value = \"\";\r\n        }\r\n    };\r\n\r\n    const triggerUpload = (type: string) => {\r\n        setUploadType(type);\r\n        if (fileInputRef.current) {\r\n            fileInputRef.current.accept = type === 'image' ? \"image/*\" : type === 'video' ? \"video/*\" : type === 'audio' ? \"audio/*\" : type === 'sticker' ? \"image/*\" : \"*/*\";\r\n            // For sticker, we accept image to convert\r\n            fileInputRef.current.click();\r\n        }\r\n    };\r\n\r\n    return (\r\n        <div className=\"flex flex-col h-full bg-slate-50\">\r\n            {/* Header */}\r\n            <div className=\"p-4 border-b bg-white flex items-center space-x-3 shadow-sm\">\r\n                <Avatar>\r\n                    <AvatarFallback>{(name || jid).slice(0, 2).toUpperCase()}</AvatarFallback>\r\n                </Avatar>\r\n                <div>\r\n                    <h3 className=\"font-semibold\">{name || jid}</h3>\r\n                    <span className=\"text-xs text-muted-foreground\">{jid}</span>\r\n                </div>\r\n            </div>\r\n\r\n            {/* Messages Area */}\r\n            <ScrollArea className=\"flex-1 min-h-0 p-4\">\r\n                <div className=\"space-y-4 pb-4\">\r\n                    {messages.map((msg) => (\r\n                        <div\r\n                            key={msg.keyId}\r\n                            className={cn(\r\n                                \"flex w-fit max-w-[75%] flex-col gap-1 rounded-lg px-3 py-2 text-sm shadow-sm break-words whitespace-pre-wrap\",\r\n                                msg.fromMe\r\n                                    ? \"ml-auto bg-primary text-primary-foreground\"\r\n                                    : \"bg-white border\"\r\n                            )}\r\n                        >\r\n                            {/* Sender Name (for received messages in groups) */}\r\n                            {!msg.fromMe && msg.pushName && (\r\n                                <span className=\"text-[10px] font-bold text-orange-600 mb-0.5\">\r\n                                    {msg.pushName}\r\n                                </span>\r\n                            )}\r\n\r\n                            {msg.type === 'IMAGE' && msg.mediaUrl && (\r\n                                <img src={msg.mediaUrl} alt=\"Image\" className=\"rounded-md max-h-64 object-cover mb-1\" />\r\n                            )}\r\n                            {msg.type === 'STICKER' && msg.mediaUrl && (\r\n                                <img src={msg.mediaUrl} alt=\"Sticker\" className=\"rounded-md max-h-32 object-contain mb-1\" />\r\n                            )}\r\n                            {/* Simple fallback for other media */}\r\n                            {msg.type !== 'TEXT' && msg.type !== 'IMAGE' && msg.type !== 'STICKER' && (\r\n                                <div className=\"flex items-center gap-2 p-2 bg-black/10 rounded\">\r\n                                    <FileText className=\"h-4 w-4\" />\r\n                                    <span className=\"text-xs italic\">{msg.type} Message</span>\r\n                                </div>\r\n                            )}\r\n\r\n                            {msg.content}\r\n                            <span className={cn(\"text-[10px] self-end opacity-70\", msg.fromMe ? \"text-primary-foreground\" : \"text-muted-foreground\")}>\r\n                                {new Date(msg.timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}\r\n                            </span>\r\n                        </div>\r\n                    ))}\r\n                    <div ref={scrollRef} />\r\n                </div>\r\n            </ScrollArea>\r\n\r\n            {/* Input Area */}\r\n            <div className=\"p-4 bg-white border-t flex items-center gap-2\">\r\n                <input\r\n                    type=\"file\"\r\n                    ref={fileInputRef}\r\n                    className=\"hidden\"\r\n                    onChange={handleFileUpload}\r\n                />\r\n                <Popover>\r\n                    <PopoverTrigger asChild>\r\n                        <Button variant=\"ghost\" size=\"icon\">\r\n                            <Paperclip className=\"h-5 w-5 text-muted-foreground\" />\r\n                        </Button>\r\n                    </PopoverTrigger>\r\n                    <PopoverContent className=\"w-48 p-2\" side=\"top\" align=\"start\">\r\n                        <div className=\"flex flex-col gap-1\">\r\n                            <Button variant=\"ghost\" size=\"sm\" className=\"justify-start gap-2\" onClick={() => triggerUpload('image')}>\r\n                                <ImageIcon className=\"h-4 w-4\" /> Image\r\n                            </Button>\r\n                            <Button variant=\"ghost\" size=\"sm\" className=\"justify-start gap-2\" onClick={() => triggerUpload('video')}>\r\n                                <Video className=\"h-4 w-4\" /> Video\r\n                            </Button>\r\n                            <Button variant=\"ghost\" size=\"sm\" className=\"justify-start gap-2\" onClick={() => triggerUpload('audio')}>\r\n                                <Music className=\"h-4 w-4\" /> Audio\r\n                            </Button>\r\n                            <Button variant=\"ghost\" size=\"sm\" className=\"justify-start gap-2\" onClick={() => triggerUpload('document')}>\r\n                                <FileText className=\"h-4 w-4\" /> Document\r\n                            </Button>\r\n                            <Button variant=\"ghost\" size=\"sm\" className=\"justify-start gap-2\" onClick={() => triggerUpload('sticker')}>\r\n                                <StickerIcon className=\"h-4 w-4\" /> Sticker\r\n                            </Button>\r\n                        </div>\r\n                    </PopoverContent>\r\n                </Popover>\r\n                <Input\r\n                    placeholder=\"Type a message...\"\r\n                    value={newMessage}\r\n                    onChange={(e) => setNewMessage(e.target.value)}\r\n                    onKeyDown={(e) => e.key === \"Enter\" && handleSend()}\r\n                    className=\"flex-1\"\r\n                />\r\n                <Button onClick={handleSend} disabled={!newMessage.trim()}>\r\n                    <Send className=\"h-4 w-4\" />\r\n                </Button>\r\n            </div>\r\n        </div>\r\n    )\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\dashboard\\mobile-nav.tsx","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'ChevronDown' is defined but never used.","line":6,"column":16,"nodeType":"Identifier","messageId":"unusedVar","endLine":6,"endColumn":27,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"ChevronDown"},"fix":{"range":[216,229],"text":""},"desc":"Remove unused variable \"ChevronDown\"."}]},{"ruleId":"@typescript-eslint/ban-ts-comment","severity":2,"message":"Use \"@ts-expect-error\" instead of \"@ts-ignore\", as \"@ts-ignore\" will do nothing if the following line is error-free.","line":88,"column":5,"nodeType":"Line","messageId":"tsIgnoreInsteadOfExpectError","endLine":88,"endColumn":18,"suggestions":[{"messageId":"replaceTsIgnoreWithTsExpectError","fix":{"range":[2876,2889],"text":"// @ts-expect-error"},"desc":"Replace \"@ts-ignore\" with \"@ts-expect-error\"."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\"use client\";\r\n\r\nimport { useState } from \"react\";\r\nimport { Sheet, SheetContent, SheetTrigger, SheetHeader, SheetTitle } from \"@/components/ui/sheet\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { Menu, ChevronDown } from \"lucide-react\";\r\nimport Link from \"next/link\";\r\nimport {\r\n    LayoutDashboard,\r\n    MessageSquare,\r\n    Users,\r\n    Settings,\r\n    LogOut,\r\n    QrCode,\r\n    ImageIcon,\r\n    Webhook,\r\n    CalendarClock,\r\n    Bot,\r\n    Bell,\r\n    FileText,\r\n    Code,\r\n    Send,\r\n    UserCheck,\r\n    Megaphone,\r\n} from \"lucide-react\";\r\nimport { usePathname } from \"next/navigation\";\r\nimport { useSession, signOut } from \"next-auth/react\";\r\nimport pkg from \"../../../package.json\";\r\n\r\ninterface NavGroup {\r\n    label: string;\r\n    items: { href: string; label: string; icon: React.ElementType; external?: boolean; superadminOnly?: boolean }[];\r\n}\r\n\r\nconst navGroups: NavGroup[] = [\r\n    {\r\n        label: \"Main\",\r\n        items: [\r\n            { href: \"/dashboard\", label: \"Dashboard\", icon: LayoutDashboard },\r\n        ],\r\n    },\r\n    {\r\n        label: \"Messaging\",\r\n        items: [\r\n            { href: \"/dashboard/chat\", label: \"Chat\", icon: MessageSquare },\r\n            { href: \"/dashboard/broadcast\", label: \"Broadcast\", icon: Megaphone },\r\n            { href: \"/dashboard/autoreply\", label: \"Auto Reply\", icon: Send },\r\n            { href: \"/dashboard/sticker\", label: \"Sticker Maker\", icon: ImageIcon },\r\n        ],\r\n    },\r\n    {\r\n        label: \"Contacts\",\r\n        items: [\r\n            { href: \"/dashboard/groups\", label: \"Groups\", icon: Users },\r\n            { href: \"/dashboard/contacts\", label: \"Contacts\", icon: UserCheck },\r\n        ],\r\n    },\r\n    {\r\n        label: \"Automation\",\r\n        items: [\r\n            { href: \"/dashboard/bot-settings\", label: \"Bot Settings\", icon: Bot },\r\n            { href: \"/dashboard/scheduler\", label: \"Scheduler\", icon: CalendarClock },\r\n            { href: \"/dashboard/webhooks\", label: \"Webhooks & API\", icon: Webhook },\r\n        ],\r\n    },\r\n    {\r\n        label: \"Developer\",\r\n        items: [\r\n            { href: \"/docs\", label: \"API Docs\", icon: FileText },\r\n            { href: \"/swagger\", label: \"Swagger UI\", icon: Code, external: true },\r\n        ],\r\n    },\r\n    {\r\n        label: \"Administration\",\r\n        items: [\r\n            { href: \"/dashboard/sessions\", label: \"Sessions / QR\", icon: QrCode },\r\n            { href: \"/dashboard/users\", label: \"Users\", icon: Users },\r\n            { href: \"/dashboard/settings\", label: \"Settings\", icon: Settings },\r\n            { href: \"/dashboard/notifications\", label: \"Notifications\", icon: Bell, superadminOnly: true },\r\n        ],\r\n    },\r\n];\r\n\r\nexport function MobileNav({ appName = \"WA-AKG\" }: { appName?: string }) {\r\n    const [open, setOpen] = useState(false);\r\n    const pathname = usePathname();\r\n    const { data: session } = useSession();\r\n    // @ts-ignore\r\n    const userRole = session?.user?.role;\r\n\r\n    const isActive = (href: string) => {\r\n        if (href === \"/dashboard\") return pathname === \"/dashboard\";\r\n        return pathname.startsWith(href);\r\n    };\r\n\r\n    return (\r\n        <Sheet open={open} onOpenChange={setOpen}>\r\n            <SheetTrigger asChild>\r\n                <Button variant=\"ghost\" size=\"icon\" className=\"md:hidden\">\r\n                    <Menu className=\"h-5 w-5\" />\r\n                </Button>\r\n            </SheetTrigger>\r\n            <SheetContent side=\"left\" className=\"w-[85vw] sm:w-[320px] p-0 flex flex-col\">\r\n                <SheetHeader className=\"px-5 py-4 text-left border-b border-slate-100\">\r\n                    <SheetTitle className=\"text-xl font-bold text-slate-800\">{appName}</SheetTitle>\r\n                    <p className=\"text-[11px] text-slate-400 -mt-1\">WhatsApp Gateway</p>\r\n                </SheetHeader>\r\n\r\n                <nav className=\"flex-1 px-3 py-3 overflow-y-auto space-y-1\">\r\n                    {navGroups.map((group) => {\r\n                        const visibleItems = group.items.filter(\r\n                            (item) => !item.superadminOnly || userRole === \"SUPERADMIN\"\r\n                        );\r\n                        if (visibleItems.length === 0) return null;\r\n\r\n                        return (\r\n                            <div key={group.label} className=\"mb-1\">\r\n                                {group.label !== \"Main\" && (\r\n                                    <p className=\"px-3 py-1.5 text-[11px] font-semibold uppercase tracking-wider text-slate-400\">\r\n                                        {group.label}\r\n                                    </p>\r\n                                )}\r\n                                <div className=\"space-y-0.5\">\r\n                                    {visibleItems.map(({ href, label, icon: Icon, external }) => (\r\n                                        <Link\r\n                                            key={href}\r\n                                            href={href}\r\n                                            target={external ? \"_blank\" : undefined}\r\n                                            onClick={() => setOpen(false)}\r\n                                            className={`\r\n                                                flex items-center gap-2.5 px-3 py-2.5 rounded-lg text-sm font-medium\r\n                                                transition-all duration-150\r\n                                                ${isActive(href)\r\n                                                    ? \"bg-slate-900 text-white shadow-sm\"\r\n                                                    : \"text-slate-600 hover:bg-slate-100 hover:text-slate-900\"\r\n                                                }\r\n                                            `}\r\n                                        >\r\n                                            <Icon\r\n                                                size={18}\r\n                                                className={`flex-shrink-0 ${isActive(href) ? \"text-white\" : \"text-slate-400\"}`}\r\n                                            />\r\n                                            <span>{label}</span>\r\n                                        </Link>\r\n                                    ))}\r\n                                </div>\r\n                            </div>\r\n                        );\r\n                    })}\r\n                </nav>\r\n\r\n                <div className=\"p-4 border-t border-slate-100 bg-slate-50/50\">\r\n                    <div className=\"flex items-center gap-3 mb-3\">\r\n                        <div className=\"h-8 w-8 rounded-full bg-slate-200 flex items-center justify-center text-xs font-semibold text-slate-600\">\r\n                            {session?.user?.name?.charAt(0)?.toUpperCase() || \"U\"}\r\n                        </div>\r\n                        <div className=\"flex-1 min-w-0\">\r\n                            <p className=\"text-sm font-medium text-slate-700 truncate\">{session?.user?.name || \"User\"}</p>\r\n                            <p className=\"text-[11px] text-slate-400 truncate\">{session?.user?.email}</p>\r\n                        </div>\r\n                    </div>\r\n                    <Button\r\n                        variant=\"outline\"\r\n                        size=\"sm\"\r\n                        className=\"w-full flex items-center justify-center gap-2 text-xs h-8\"\r\n                        onClick={async () => {\r\n                            setOpen(false);\r\n                            await signOut({ callbackUrl: \"/auth/login\" });\r\n                        }}\r\n                    >\r\n                        <LogOut size={14} /> Sign Out\r\n                    </Button>\r\n                    <p className=\"text-[10px] text-slate-300 text-center mt-2 font-mono\">v{pkg.version}</p>\r\n                </div>\r\n            </SheetContent>\r\n        </Sheet>\r\n    );\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\dashboard\\navbar.tsx","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'socket' is assigned a value but never used.","line":36,"column":12,"nodeType":"Identifier","messageId":"unusedVar","endLine":36,"endColumn":18},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'e' is defined but never used.","line":46,"column":18,"nodeType":"Identifier","messageId":"unusedVar","endLine":46,"endColumn":19},{"ruleId":"react-hooks/set-state-in-effect","severity":2,"message":"Error: Calling setState synchronously within an effect can trigger cascading renders\n\nEffects are intended to synchronize state between React and external systems such as manually updating the DOM, state management libraries, or other platform APIs. In general, the body of an effect should do one or both of the following:\n* Update external systems with the latest state from React.\n* Subscribe for updates from some external system, calling setState in a callback function when external state changes.\n\nCalling setState synchronously within an effect body causes cascading renders that can hurt performance, and is not recommended. (https://react.dev/learn/you-might-not-need-an-effect).\n\nC:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\dashboard\\navbar.tsx:53:9\n  51 |     useEffect(() => {\n  52 |         // Initial fetch\n> 53 |         fetchNotifications();\n     |         ^^^^^^^^^^^^^^^^^^ Avoid calling setState() directly within an effect\n  54 |\n  55 |         // Setup Socket.IO connection\n  56 |         if (session?.user?.id) {","line":53,"column":9,"nodeType":null,"endLine":53,"endColumn":27},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'router'. Either include it or remove the dependency array.","line":90,"column":8,"nodeType":"ArrayExpression","endLine":90,"endColumn":27,"suggestions":[{"desc":"Update the dependencies array to be: [router, session.user.id]","fix":{"range":[3102,3121],"text":"[router, session.user.id]"}}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'e' is defined but never used.","line":109,"column":18,"nodeType":"Identifier","messageId":"unusedVar","endLine":109,"endColumn":19},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'e' is defined but never used.","line":127,"column":18,"nodeType":"Identifier","messageId":"unusedVar","endLine":127,"endColumn":19},{"ruleId":"react/no-unescaped-entities","severity":2,"message":"`'` can be escaped with `&apos;`, `&lsquo;`, `&#39;`, `&rsquo;`.","line":180,"column":98,"nodeType":"JSXText","messageId":"unescapedEntityAlts","suggestions":[{"messageId":"replaceWithAlt","data":{"alt":"&apos;"},"fix":{"range":[7868,7918],"text":"We&apos;ll notify you when something important arrives."},"desc":"Replace with `&apos;`."},{"messageId":"replaceWithAlt","data":{"alt":"&lsquo;"},"fix":{"range":[7868,7918],"text":"We&lsquo;ll notify you when something important arrives."},"desc":"Replace with `&lsquo;`."},{"messageId":"replaceWithAlt","data":{"alt":"&#39;"},"fix":{"range":[7868,7918],"text":"We&#39;ll notify you when something important arrives."},"desc":"Replace with `&#39;`."},{"messageId":"replaceWithAlt","data":{"alt":"&rsquo;"},"fix":{"range":[7868,7918],"text":"We&rsquo;ll notify you when something important arrives."},"desc":"Replace with `&rsquo;`."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":5,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\"use client\";\r\n\r\nimport { useState, useEffect } from \"react\";\r\nimport { MobileNav } from \"@/components/dashboard/mobile-nav\";\r\nimport { SessionSelector } from \"@/components/dashboard/session-selector\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { RealtimeClock } from \"@/components/dashboard/realtime-clock\";\r\nimport { Popover, PopoverContent, PopoverTrigger } from \"@/components/ui/popover\";\r\nimport { Bell, Inbox, Trash2 } from \"lucide-react\";\r\nimport { useRouter } from \"next/navigation\";\r\nimport { formatDistanceToNow } from \"date-fns\";\r\nimport { useSession } from \"next-auth/react\";\r\nimport { toast } from \"sonner\";\r\nimport { io, Socket } from \"socket.io-client\";\r\n\r\ninterface NavbarProps {\r\n    appName?: string;\r\n}\r\n\r\ninterface Notification {\r\n    id: string;\r\n    title: string;\r\n    message: string;\r\n    type: string;\r\n    read: boolean;\r\n    href?: string;\r\n    createdAt: string;\r\n}\r\n\r\nexport function Navbar({ appName }: NavbarProps) {\r\n    const router = useRouter();\r\n    const { data: session } = useSession();\r\n    const [notifications, setNotifications] = useState<Notification[]>([]);\r\n    const [unreadCount, setUnreadCount] = useState(0);\r\n    const [isOpen, setIsOpen] = useState(false);\r\n    const [socket, setSocket] = useState<Socket | null>(null);\r\n\r\n    const fetchNotifications = async () => {\r\n        try {\r\n            const res = await fetch(\"/api/notifications\");\r\n            if (res.ok) {\r\n                const data = await res.json();\r\n                setNotifications(data);\r\n                setUnreadCount(data.filter((n: Notification) => !n.read).length);\r\n            }\r\n        } catch (e) {\r\n            console.error(\"Failed to fetch notifications\");\r\n        }\r\n    };\r\n\r\n    useEffect(() => {\r\n        // Initial fetch\r\n        fetchNotifications();\r\n\r\n        // Setup Socket.IO connection\r\n        if (session?.user?.id) {\r\n            const socketInstance = io({\r\n                path: \"/api/socket/io\",\r\n            });\r\n\r\n            socketInstance.on(\"connect\", () => {\r\n                console.log(\"Socket connected for notifications\");\r\n                // Join user-specific room\r\n                socketInstance.emit(\"join-user-room\", session.user.id);\r\n            });\r\n\r\n            socketInstance.on(\"notification:new\", (notification: Notification) => {\r\n                console.log(\"New notification received:\", notification);\r\n\r\n                // Add to notifications list\r\n                setNotifications(prev => [notification, ...prev]);\r\n                setUnreadCount(prev => prev + 1);\r\n\r\n                // Show toast popup\r\n                toast.info(notification.title, {\r\n                    description: notification.message,\r\n                    action: notification.href ? {\r\n                        label: \"View\",\r\n                        onClick: () => router.push(notification.href!)\r\n                    } : undefined,\r\n                });\r\n            });\r\n\r\n            setSocket(socketInstance);\r\n\r\n            return () => {\r\n                socketInstance.disconnect();\r\n            };\r\n        }\r\n    }, [session?.user?.id]);\r\n\r\n    const markAsRead = async (id?: string) => {\r\n        try {\r\n            const ids = id ? [id] : []; // Empty array means mark all\r\n            const res = await fetch(\"/api/notifications/read\", {\r\n                method: \"PATCH\",\r\n                headers: { \"Content-Type\": \"application/json\" },\r\n                body: JSON.stringify({ ids })\r\n            });\r\n            if (res.ok) {\r\n                if (id) {\r\n                    setNotifications(prev => prev.map(n => n.id === id ? { ...n, read: true } : n));\r\n                    setUnreadCount(prev => Math.max(0, prev - 1));\r\n                } else {\r\n                    setNotifications(prev => prev.map(n => ({ ...n, read: true })));\r\n                    setUnreadCount(0);\r\n                }\r\n            }\r\n        } catch (e) {\r\n            console.error(\"Failed to mark read\");\r\n        }\r\n    };\r\n\r\n    const deleteNotification = async (id: string) => {\r\n        try {\r\n            const res = await fetch(`/api/notifications/delete?id=${id}`, {\r\n                method: \"DELETE\"\r\n            });\r\n            if (res.ok) {\r\n                setNotifications(prev => prev.filter(n => n.id !== id));\r\n                setUnreadCount(prev => {\r\n                    const notification = notifications.find(n => n.id === id);\r\n                    return notification && !notification.read ? Math.max(0, prev - 1) : prev;\r\n                });\r\n                toast.success(\"Notification deleted\");\r\n            }\r\n        } catch (e) {\r\n            console.error(\"Failed to delete notification\");\r\n            toast.error(\"Failed to delete notification\");\r\n        }\r\n    };\r\n\r\n    const handleNotificationClick = (n: Notification) => {\r\n        if (!n.read) markAsRead(n.id);\r\n        if (n.href) router.push(n.href);\r\n        setIsOpen(false);\r\n    };\r\n\r\n    return (\r\n        <header className=\"bg-background/40 backdrop-blur-2xl border-b border-border/50 h-16 flex items-center justify-between px-4 sm:px-6 sticky top-0 z-30 w-full shadow-sm\">\r\n            <div className=\"flex items-center gap-3\">\r\n                <MobileNav appName={appName} />\r\n            </div>\r\n\r\n            <div className=\"flex items-center gap-4\">\r\n                <RealtimeClock />\r\n                <SessionSelector />\r\n                <div className=\"h-6 w-px bg-border/50 mx-2\" />\r\n\r\n                <Popover open={isOpen} onOpenChange={setIsOpen}>\r\n                    <PopoverTrigger asChild>\r\n                        <Button variant=\"ghost\" size=\"icon\" className=\"relative hover:bg-muted/50 rounded-full h-10 w-10\">\r\n                            <Bell className={`h-5 w-5 transition-colors ${unreadCount > 0 ? 'text-primary' : 'text-muted-foreground hover:text-foreground'}`} />\r\n                            {unreadCount > 0 && (\r\n                                <span className=\"absolute top-1.5 right-2.5 h-2.5 w-2.5 bg-red-500 rounded-full animate-pulse border-2 border-background\" />\r\n                            )}\r\n                        </Button>\r\n                    </PopoverTrigger>\r\n                    <PopoverContent className=\"w-80 p-0 rounded-2xl border border-border/50 shadow-2xl glass-panel\" align=\"end\">\r\n                        <div className=\"p-4 border-b border-border/50 flex justify-between items-center bg-background/50\">\r\n                            <div>\r\n                                <h4 className=\"font-semibold leading-none text-foreground\">Notifications</h4>\r\n                                <p className=\"text-xs text-muted-foreground mt-1\">\r\n                                    {unreadCount > 0 ? `You have ${unreadCount} unread updates.` : \"No new notifications.\"}\r\n                                </p>\r\n                            </div>\r\n                            {unreadCount > 0 && (\r\n                                <Button variant=\"ghost\" size=\"sm\" onClick={() => markAsRead()} className=\"h-auto py-1 px-2 text-xs\">\r\n                                    Mark all read\r\n                                </Button>\r\n                            )}\r\n                        </div>\r\n                        <div className=\"max-h-[300px] overflow-y-auto\">\r\n                            {notifications.length === 0 ? (\r\n                                <div className=\"min-h-[150px] flex flex-col items-center justify-center text-center p-4\">\r\n                                    <div className=\"bg-slate-100 p-3 rounded-full mb-3\">\r\n                                        <Inbox className=\"h-6 w-6 text-slate-400\" />\r\n                                    </div>\r\n                                    <p className=\"text-sm font-medium\">No new notifications</p>\r\n                                    <p className=\"text-xs text-muted-foreground max-w-[180px]\">We'll notify you when something important arrives.</p>\r\n                                </div>\r\n                            ) : (\r\n                                <div className=\"divide-y\">\r\n                                    {notifications.map(n => (\r\n                                        <div\r\n                                            key={n.id}\r\n                                            className={`p-4 hover:bg-slate-50 transition-colors ${!n.read ? 'bg-blue-50/50' : ''}`}\r\n                                        >\r\n                                            <div className=\"flex justify-between items-start gap-3\">\r\n                                                <div\r\n                                                    className=\"flex-1 space-y-1 cursor-pointer\"\r\n                                                    onClick={() => handleNotificationClick(n)}\r\n                                                >\r\n                                                    <p className={`text-sm font-medium leading-none ${!n.read ? 'text-blue-700' : 'text-slate-900'}`}>\r\n                                                        {n.title}\r\n                                                    </p>\r\n                                                    <p className=\"text-xs text-muted-foreground line-clamp-2\">\r\n                                                        {n.message}\r\n                                                    </p>\r\n                                                    <p className=\"text-[10px] text-slate-400\">\r\n                                                        {formatDistanceToNow(new Date(n.createdAt), { addSuffix: true })}\r\n                                                    </p>\r\n                                                </div>\r\n                                                <div className=\"flex items-center gap-2\">\r\n                                                    {!n.read && <span className=\"h-2 w-2 bg-blue-500 rounded-full flex-shrink-0\" />}\r\n                                                    <Button\r\n                                                        variant=\"ghost\"\r\n                                                        size=\"icon\"\r\n                                                        className=\"h-8 w-8\"\r\n                                                        onClick={(e) => {\r\n                                                            e.stopPropagation();\r\n                                                            deleteNotification(n.id);\r\n                                                        }}\r\n                                                    >\r\n                                                        <Trash2 className=\"h-4 w-4 text-red-500\" />\r\n                                                    </Button>\r\n                                                </div>\r\n                                            </div>\r\n                                        </div>\r\n                                    ))}\r\n                                </div>\r\n                            )}\r\n                        </div>\r\n                    </PopoverContent>\r\n                </Popover>\r\n            </div>\r\n        </header>\r\n    );\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\dashboard\\realtime-clock.tsx","messages":[{"ruleId":"react-hooks/set-state-in-effect","severity":2,"message":"Error: Calling setState synchronously within an effect can trigger cascading renders\n\nEffects are intended to synchronize state between React and external systems such as manually updating the DOM, state management libraries, or other platform APIs. In general, the body of an effect should do one or both of the following:\n* Update external systems with the latest state from React.\n* Subscribe for updates from some external system, calling setState in a callback function when external state changes.\n\nCalling setState synchronously within an effect body causes cascading renders that can hurt performance, and is not recommended. (https://react.dev/learn/you-might-not-need-an-effect).\n\nC:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\dashboard\\realtime-clock.tsx:13:9\n  11 |\n  12 |     useEffect(() => {\n> 13 |         setMounted(true);\n     |         ^^^^^^^^^^ Avoid calling setState() directly within an effect\n  14 |         // Fetch global timezone\n  15 |         fetch('/api/settings/system')\n  16 |             .then(r => r.json())","line":13,"column":9,"nodeType":null,"endLine":13,"endColumn":19}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\"use client\";\r\n\r\nimport { useEffect, useState } from \"react\";\r\nimport moment from \"moment-timezone\";\r\nimport { Clock } from \"lucide-react\";\r\n\r\nexport function RealtimeClock() {\r\n    const [time, setTime] = useState(\"\");\r\n    const [timezone, setTimezone] = useState(\"Asia/Jakarta\");\r\n    const [mounted, setMounted] = useState(false);\r\n\r\n    useEffect(() => {\r\n        setMounted(true);\r\n        // Fetch global timezone\r\n        fetch('/api/settings/system')\r\n            .then(r => r.json())\r\n            .then(data => {\r\n                if (data && data.timezone) {\r\n                    setTimezone(data.timezone);\r\n                }\r\n            })\r\n            .catch(() => { });\r\n    }, []);\r\n\r\n    useEffect(() => {\r\n        if (!mounted) return;\r\n\r\n        const updateTime = () => {\r\n            setTime(moment().tz(timezone).format(\"HH:mm:ss\"));\r\n        };\r\n\r\n        updateTime();\r\n        const interval = setInterval(updateTime, 1000);\r\n        return () => clearInterval(interval);\r\n    }, [timezone, mounted]);\r\n\r\n    if (!mounted) return null;\r\n\r\n    return (\r\n        <div className=\"flex items-center gap-2 px-3 py-1.5 bg-slate-100 rounded-md border border-slate-200 text-sm font-medium text-slate-700\">\r\n            <Clock className=\"h-4 w-4 text-slate-500\" />\r\n            <span>{time}</span>\r\n            <span className=\"text-xs text-slate-400 border-l border-slate-300 pl-2 ml-1\">{timezone}</span>\r\n        </div>\r\n    );\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\dashboard\\search-filter.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\dashboard\\session-guard.tsx","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'Bot' is defined but never used.","line":4,"column":10,"nodeType":"Identifier","messageId":"unusedVar","endLine":4,"endColumn":13,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"Bot"},"fix":{"range":[76,80],"text":""},"desc":"Remove unused variable \"Bot\"."}]},{"ruleId":"react/no-unescaped-entities","severity":2,"message":"`'` can be escaped with `&apos;`, `&lsquo;`, `&#39;`, `&rsquo;`.","line":31,"column":69,"nodeType":"JSXText","messageId":"unescapedEntityAlts","suggestions":[{"messageId":"replaceWithAlt","data":{"alt":"&apos;"},"fix":{"range":[1327,1359],"text":"You don&apos;t have any sessions yet."},"desc":"Replace with `&apos;`."},{"messageId":"replaceWithAlt","data":{"alt":"&lsquo;"},"fix":{"range":[1327,1359],"text":"You don&lsquo;t have any sessions yet."},"desc":"Replace with `&lsquo;`."},{"messageId":"replaceWithAlt","data":{"alt":"&#39;"},"fix":{"range":[1327,1359],"text":"You don&#39;t have any sessions yet."},"desc":"Replace with `&#39;`."},{"messageId":"replaceWithAlt","data":{"alt":"&rsquo;"},"fix":{"range":[1327,1359],"text":"You don&rsquo;t have any sessions yet."},"desc":"Replace with `&rsquo;`."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\"use client\";\r\n\r\nimport { useSession } from \"./session-provider\";\r\nimport { Bot, QrCode } from \"lucide-react\";\r\nimport { ReactNode } from \"react\";\r\nimport Link from \"next/link\";\r\nimport { Button } from \"@/components/ui/button\";\r\n\r\nexport function SessionGuard({ children }: { children: ReactNode }) {\r\n    const { sessionId, loading, sessions } = useSession();\r\n\r\n    if (loading) {\r\n        return <div className=\"flex h-full items-center justify-center p-8\">Loading session...</div>;\r\n    }\r\n\r\n    if (!sessionId) {\r\n        return (\r\n            <div className=\"flex h-full flex-col items-center justify-center space-y-6 text-center p-8\">\r\n                <div className=\"rounded-full bg-green-100 p-6\">\r\n                    <QrCode className=\"h-12 w-12 text-green-600\" />\r\n                </div>\r\n                <div className=\"space-y-2 max-w-md\">\r\n                    <h2 className=\"text-2xl font-bold tracking-tight\">No Active Session</h2>\r\n                    <p className=\"text-gray-500\">\r\n                        Please select a WhatsApp session from the top navigation bar to access this feature.\r\n                    </p>\r\n                </div>\r\n\r\n                {sessions.length === 0 && (\r\n                    <div className=\"flex flex-col gap-2\">\r\n                        <p className=\"text-sm text-gray-500\">You don't have any sessions yet.</p>\r\n                        <Link href=\"/dashboard/sessions\">\r\n                            <Button variant=\"outline\">Create a Session</Button>\r\n                        </Link>\r\n                    </div>\r\n                )}\r\n            </div>\r\n        );\r\n    }\r\n\r\n    return <>{children}</>;\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\dashboard\\session-manager.tsx","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'QRCode' is defined but never used.","line":5,"column":8,"nodeType":"Identifier","messageId":"unusedVar","endLine":5,"endColumn":14,"suggestions":[{"messageId":"removeUnusedImportDeclaration","data":{"varName":"QRCode"},"fix":{"range":[111,139],"text":""},"desc":"Remove unused import declaration."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'Trash2' is defined but never used.","line":12,"column":28,"nodeType":"Identifier","messageId":"unusedVar","endLine":12,"endColumn":34,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"Trash2"},"fix":{"range":[502,510],"text":""},"desc":"Remove unused variable \"Trash2\"."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'RefreshCw' is defined but never used.","line":12,"column":46,"nodeType":"Identifier","messageId":"unusedVar","endLine":12,"endColumn":55,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"RefreshCw"},"fix":{"range":[520,531],"text":""},"desc":"Remove unused variable \"RefreshCw\"."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'Power' is defined but never used.","line":12,"column":57,"nodeType":"Identifier","messageId":"unusedVar","endLine":12,"endColumn":62,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"Power"},"fix":{"range":[531,538],"text":""},"desc":"Remove unused variable \"Power\"."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":23,"column":50,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":23,"endColumn":53,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[792,795],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[792,795],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'socket' is assigned a value but never used.","line":28,"column":12,"nodeType":"Identifier","messageId":"unusedVar","endLine":28,"endColumn":18},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":105,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":105,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3636,3639],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3636,3639],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":5,"fixableErrorCount":0,"fixableWarningCount":0,"source":"'use client';\r\n\r\nimport { useState, useEffect } from 'react';\r\nimport { io, Socket } from 'socket.io-client';\r\nimport QRCode from 'qrcode';\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { Input } from \"@/components/ui/input\";\r\nimport { Card, CardContent, CardHeader, CardTitle, CardFooter, CardDescription } from \"@/components/ui/card\";\r\nimport { useRouter } from 'next/navigation';\r\nimport { toast } from \"sonner\";\r\nimport { Label } from '@/components/ui/label';\r\nimport { Smartphone, Plus, Trash2, Settings, RefreshCw, Power } from 'lucide-react';\r\nimport { Badge } from '@/components/ui/badge';\r\n\r\ntype Session = {\r\n    id: string;\r\n    name: string;\r\n    sessionId: string;\r\n    status: string;\r\n    qr?: string | null;\r\n};\r\n\r\nexport function SessionManager({ user }: { user: any }) {\r\n    const [sessions, setSessions] = useState<Session[]>([]);\r\n    const [newSessionName, setNewSessionName] = useState(\"\");\r\n    const [newSessionId, setNewSessionId] = useState(\"\");\r\n    const [loading, setLoading] = useState(false);\r\n    const [socket, setSocket] = useState<Socket | null>(null);\r\n    const router = useRouter();\r\n\r\n    useEffect(() => {\r\n        fetchSessions();\r\n\r\n        // Init Socket\r\n        const socketInstance = io({\r\n            path: \"/api/socket/io\",\r\n            addTrailingSlash: false,\r\n        });\r\n\r\n        socketInstance.on('connect', () => {\r\n            console.log('Socket connected');\r\n        });\r\n\r\n        socketInstance.on('connection.update', (data: { sessionId: string, status: string, qr: string }) => {\r\n            // Update specific session status if match\r\n            setSessions(prev => prev.map(s => {\r\n                if (s.sessionId === data.sessionId) {\r\n                    return { ...s, status: data.status, qr: data.qr };\r\n                }\r\n                return s;\r\n            }));\r\n\r\n            if (data.status === 'CONNECTED') {\r\n                fetchSessions(); // Refresh purely to get updated state from DB if needed\r\n            }\r\n        });\r\n\r\n        setSocket(socketInstance);\r\n\r\n        return () => {\r\n            socketInstance.disconnect();\r\n        };\r\n    }, []);\r\n\r\n    const fetchSessions = () => {\r\n        fetch('/api/sessions').then(res => res.json()).then(data => {\r\n            if (Array.isArray(data)) setSessions(data);\r\n        });\r\n    }\r\n\r\n    const createSession = async () => {\r\n        if (!newSessionName) {\r\n            toast.error(\"Session name is required\");\r\n            return;\r\n        }\r\n\r\n        // If ID matches existing\r\n        if (newSessionId && sessions.some(s => s.sessionId === newSessionId)) {\r\n            toast.error(\"Session ID already exists\");\r\n            return;\r\n        }\r\n\r\n        setLoading(true);\r\n        try {\r\n            const res = await fetch('/api/sessions', {\r\n                method: 'POST',\r\n                headers: { 'Content-Type': 'application/json' },\r\n                body: JSON.stringify({\r\n                    userId: user.id,\r\n                    name: newSessionName,\r\n                    sessionId: newSessionId || undefined // Optional, backend will generate if empty\r\n                })\r\n            });\r\n            const session = await res.json();\r\n\r\n            if (!res.ok) throw new Error(session.error || \"Failed to create\");\r\n\r\n            setSessions([...sessions, session]);\r\n            setNewSessionName(\"\");\r\n            setNewSessionId(\"\");\r\n            toast.success(\"Session created successfully\");\r\n\r\n            // Optionally redirect immediately or let user choose\r\n            // router.push(`/dashboard/sessions/${session.sessionId}`);\r\n        } catch (e: any) {\r\n            console.error(e);\r\n            toast.error(e.message || \"Failed to create session\");\r\n        } finally {\r\n            setLoading(false);\r\n        }\r\n    };\r\n\r\n    const handleManageSession = (sessionId: string) => {\r\n        router.push(`/dashboard/sessions/${sessionId}`);\r\n    }\r\n\r\n    return (\r\n        <div className=\"space-y-8\">\r\n            {/* Create New Session Card */}\r\n            <Card className=\"bg-slate-50 border-dashed border-2\">\r\n                <CardHeader>\r\n                    <CardTitle className=\"text-lg flex items-center gap-2\">\r\n                        <Plus className=\"h-5 w-5\" /> Create New Session\r\n                    </CardTitle>\r\n                    <CardDescription>\r\n                        Add a new WhatsApp account to manage.\r\n                    </CardDescription>\r\n                </CardHeader>\r\n                <CardContent>\r\n                    <div className=\"grid grid-cols-1 md:grid-cols-3 gap-4 items-end\">\r\n                        <div className=\"space-y-2\">\r\n                            <Label htmlFor=\"session-name\">Session Name</Label>\r\n                            <Input\r\n                                id=\"session-name\"\r\n                                value={newSessionName}\r\n                                onChange={e => setNewSessionName(e.target.value)}\r\n                                placeholder=\"My Business WA\"\r\n                            />\r\n                        </div>\r\n                        <div className=\"space-y-2\">\r\n                            <Label htmlFor=\"session-id\">Custom Session ID (Optional)</Label>\r\n                            <Input\r\n                                id=\"session-id\"\r\n                                value={newSessionId}\r\n                                onChange={e => setNewSessionId(e.target.value.replace(/[^a-zA-Z0-9-_]/g, ''))}\r\n                                placeholder=\"unique-id-123\"\r\n                            />\r\n                            <p className=\"text-[10px] text-muted-foreground\">Only letters, numbers, hyphens.</p>\r\n                        </div>\r\n                        <Button onClick={createSession} disabled={loading}>\r\n                            {loading ? 'Creating...' : 'Create Session'}\r\n                        </Button>\r\n                    </div>\r\n                </CardContent>\r\n            </Card>\r\n\r\n            {/* Sessions Grid */}\r\n            <div>\r\n                <h2 className=\"text-xl font-semibold mb-4 text-slate-800\">Active Sessions ({sessions.length})</h2>\r\n                {sessions.length === 0 ? (\r\n                    <div className=\"text-center py-10 text-muted-foreground bg-slate-50 rounded-lg border\">\r\n                        No sessions found. Create one above to get started.\r\n                    </div>\r\n                ) : (\r\n                    <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6\">\r\n                        {sessions.map(session => (\r\n                            <Card key={session.id} className=\"hover:shadow-md transition-shadow\">\r\n                                <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\r\n                                    <CardTitle className=\"text-base font-medium truncate\">\r\n                                        {session.name}\r\n                                    </CardTitle>\r\n                                    <Smartphone className=\"h-4 w-4 text-muted-foreground\" />\r\n                                </CardHeader>\r\n                                <CardContent>\r\n                                    <div className=\"text-2xl font-bold truncate mb-2\">{session.sessionId}</div>\r\n                                    <div className=\"flex items-center space-x-2\">\r\n                                        <Badge variant={session.status === 'CONNECTED' ? 'default' : 'secondary'}\r\n                                            className={session.status === 'CONNECTED' ? 'bg-green-500 hover:bg-green-600' : ''}>\r\n                                            {session.status}\r\n                                        </Badge>\r\n                                    </div>\r\n                                </CardContent>\r\n                                <CardFooter className=\"bg-slate-50/50 p-3 flex justify-end gap-2\">\r\n                                    <Button variant=\"outline\" size=\"sm\" onClick={() => handleManageSession(session.sessionId)}>\r\n                                        <Settings className=\"h-4 w-4 mr-1\" /> Manage\r\n                                    </Button>\r\n                                </CardFooter>\r\n                            </Card>\r\n                        ))}\r\n                    </div>\r\n                )}\r\n            </div>\r\n        </div>\r\n    );\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\dashboard\\session-provider.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\dashboard\\session-selector.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\dashboard\\sidebar-nav.tsx","messages":[{"ruleId":"@typescript-eslint/ban-ts-comment","severity":2,"message":"Use \"@ts-expect-error\" instead of \"@ts-ignore\", as \"@ts-ignore\" will do nothing if the following line is error-free.","line":91,"column":5,"nodeType":"Line","messageId":"tsIgnoreInsteadOfExpectError","endLine":91,"endColumn":18,"suggestions":[{"messageId":"replaceTsIgnoreWithTsExpectError","fix":{"range":[2622,2635],"text":"// @ts-expect-error"},"desc":"Replace \"@ts-ignore\" with \"@ts-expect-error\"."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\"use client\";\r\n\r\nimport { useState } from \"react\";\r\nimport Link from \"next/link\";\r\nimport { usePathname } from \"next/navigation\";\r\nimport { useSession } from \"next-auth/react\";\r\nimport { ChevronDown } from \"lucide-react\";\r\nimport {\r\n    LayoutDashboard,\r\n    MessageSquare,\r\n    Users,\r\n    Settings,\r\n    QrCode,\r\n    ImageIcon,\r\n    Webhook,\r\n    CalendarClock,\r\n    Bot,\r\n    Bell,\r\n    FileText,\r\n    Code,\r\n    Send,\r\n    UserCheck,\r\n    Megaphone,\r\n} from \"lucide-react\";\r\n\r\ninterface NavGroup {\r\n    label: string;\r\n    items: NavItem[];\r\n}\r\n\r\ninterface NavItem {\r\n    href: string;\r\n    label: string;\r\n    icon: React.ElementType;\r\n    external?: boolean;\r\n    superadminOnly?: boolean;\r\n}\r\n\r\nconst navGroups: NavGroup[] = [\r\n    {\r\n        label: \"Main\",\r\n        items: [\r\n            { href: \"/dashboard\", label: \"Dashboard\", icon: LayoutDashboard },\r\n        ],\r\n    },\r\n    {\r\n        label: \"Messaging\",\r\n        items: [\r\n            { href: \"/dashboard/chat\", label: \"Chat\", icon: MessageSquare },\r\n            { href: \"/dashboard/broadcast\", label: \"Broadcast\", icon: Megaphone },\r\n            { href: \"/dashboard/autoreply\", label: \"Auto Reply\", icon: Send },\r\n            { href: \"/dashboard/sticker\", label: \"Sticker Maker\", icon: ImageIcon },\r\n        ],\r\n    },\r\n    {\r\n        label: \"Contacts\",\r\n        items: [\r\n            { href: \"/dashboard/groups\", label: \"Groups\", icon: Users },\r\n            { href: \"/dashboard/contacts\", label: \"Contacts\", icon: UserCheck },\r\n        ],\r\n    },\r\n    {\r\n        label: \"Automation\",\r\n        items: [\r\n            { href: \"/dashboard/bot-settings\", label: \"Bot Settings\", icon: Bot },\r\n            { href: \"/dashboard/scheduler\", label: \"Scheduler\", icon: CalendarClock },\r\n            { href: \"/dashboard/webhooks\", label: \"Webhooks & API\", icon: Webhook },\r\n        ],\r\n    },\r\n    {\r\n        label: \"Developer\",\r\n        items: [\r\n            { href: \"/docs\", label: \"API Docs\", icon: FileText },\r\n            { href: \"/swagger\", label: \"Swagger UI\", icon: Code, external: true },\r\n        ],\r\n    },\r\n    {\r\n        label: \"Administration\",\r\n        items: [\r\n            { href: \"/dashboard/sessions\", label: \"Sessions / QR\", icon: QrCode },\r\n            { href: \"/dashboard/users\", label: \"Users\", icon: Users },\r\n            { href: \"/dashboard/settings\", label: \"Settings\", icon: Settings },\r\n            { href: \"/dashboard/notifications\", label: \"Notifications\", icon: Bell, superadminOnly: true },\r\n        ],\r\n    },\r\n];\r\n\r\nexport function SidebarNav() {\r\n    const pathname = usePathname();\r\n    const { data: session } = useSession();\r\n    // @ts-ignore\r\n    const userRole = session?.user?.role;\r\n\r\n    // Track collapsed groups ΓÇö all expanded by default\r\n    const [collapsed, setCollapsed] = useState<Record<string, boolean>>({});\r\n\r\n    const toggleGroup = (label: string) => {\r\n        setCollapsed(prev => ({ ...prev, [label]: !prev[label] }));\r\n    };\r\n\r\n    const isActive = (href: string) => {\r\n        if (href === \"/dashboard\") return pathname === \"/dashboard\";\r\n        return pathname.startsWith(href);\r\n    };\r\n\r\n    return (\r\n        <nav className=\"flex-1 px-3 py-2 overflow-y-auto space-y-1\">\r\n            {navGroups.map((group) => {\r\n                const visibleItems = group.items.filter(\r\n                    (item) => !item.superadminOnly || userRole === \"SUPERADMIN\"\r\n                );\r\n                if (visibleItems.length === 0) return null;\r\n\r\n                const isCollapsed = collapsed[group.label] ?? false;\r\n\r\n                // \"Main\" group doesn't show a collapsible header\r\n                if (group.label === \"Main\") {\r\n                    return (\r\n                        <div key={group.label} className=\"mb-1\">\r\n                            {visibleItems.map((item) => (\r\n                                <NavLink\r\n                                    key={item.href}\r\n                                    item={item}\r\n                                    active={isActive(item.href)}\r\n                                />\r\n                            ))}\r\n                        </div>\r\n                    );\r\n                }\r\n\r\n                return (\r\n                    <div key={group.label} className=\"mb-2\">\r\n                        <button\r\n                            onClick={() => toggleGroup(group.label)}\r\n                            className=\"flex items-center justify-between w-full px-4 py-2 text-[11px] font-bold uppercase tracking-widest text-muted-foreground/70 hover:text-foreground transition-colors group\"\r\n                        >\r\n                            {group.label}\r\n                            <ChevronDown\r\n                                size={14}\r\n                                className={`transition-transform duration-300 ease-out group-hover:text-primary ${isCollapsed ? \"-rotate-90\" : \"\"}`}\r\n                            />\r\n                        </button>\r\n                        {!isCollapsed && (\r\n                            <div className=\"space-y-1 mt-1\">\r\n                                {visibleItems.map((item) => (\r\n                                    <NavLink\r\n                                        key={item.href}\r\n                                        item={item}\r\n                                        active={isActive(item.href)}\r\n                                    />\r\n                                ))}\r\n                            </div>\r\n                        )}\r\n                    </div>\r\n                );\r\n            })}\r\n        </nav>\r\n    );\r\n}\r\n\r\nfunction NavLink({ item, active }: { item: NavItem; active: boolean }) {\r\n    const Icon = item.icon;\r\n    return (\r\n        <Link\r\n            href={item.href}\r\n            target={item.external ? \"_blank\" : undefined}\r\n            className={`\r\n                flex items-center gap-3 px-4 py-2.5 rounded-xl text-sm font-medium\r\n                transition-all duration-300 ease-out group relative overflow-hidden\r\n                ${active\r\n                    ? \"text-primary bg-primary/10 shadow-sm border border-primary/20\"\r\n                    : \"text-muted-foreground hover:bg-muted/50 hover:text-foreground border border-transparent\"\r\n                }\r\n            `}\r\n        >\r\n            {active && (\r\n                <div className=\"absolute left-0 top-1/2 -translate-y-1/2 w-1 h-8 bg-primary rounded-r-full shadow-[0_0_10px_rgba(var(--color-primary),0.5)]\" />\r\n            )}\r\n            <Icon\r\n                size={18}\r\n                className={`flex-shrink-0 transition-all duration-300 ${active ? \"text-primary scale-110\" : \"text-muted-foreground/70 group-hover:text-foreground group-hover:scale-110\"}`}\r\n            />\r\n            <span className=\"truncate\">{item.label}</span>\r\n        </Link>\r\n    );\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\dashboard\\update-checker.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\providers.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\ui\\alert-dialog.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\ui\\avatar.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\ui\\badge.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\ui\\button.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\ui\\card.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\ui\\dialog.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\ui\\form.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\ui\\input.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\ui\\label.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\ui\\pagination.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\ui\\popover.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\ui\\scroll-area.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\ui\\select.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\ui\\sheet.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\ui\\skeleton.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\ui\\slider.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\ui\\switch.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\ui\\table.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\ui\\textarea.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\components\\ui\\top-loader.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\lib\\api-auth.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\lib\\auth.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\lib\\client-cookie.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\lib\\cron.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\lib\\github.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\lib\\prisma.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\lib\\swagger.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\lib\\utils.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\lib\\validations.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\lib\\webhook.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'pino' is defined but never used.","line":6,"column":8,"nodeType":"Identifier","messageId":"unusedVar","endLine":6,"endColumn":12,"suggestions":[{"messageId":"removeUnusedImportDeclaration","data":{"varName":"pino"},"fix":{"range":[242,266],"text":""},"desc":"Remove unused import declaration."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":22,"column":11,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":22,"endColumn":14,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[632,635],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[632,635],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":31,"column":11,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":31,"endColumn":14,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[806,809],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[806,809],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":87,"column":62,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":87,"endColumn":65,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2673,2676],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2673,2676],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":87,"column":68,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":87,"endColumn":71,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2679,2682],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2679,2682],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":103,"column":43,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":103,"endColumn":46,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3278,3281],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3278,3281],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":191,"column":41,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":191,"endColumn":44,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[6068,6071],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[6068,6071],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":222,"column":69,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":222,"endColumn":72,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[7152,7155],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[7152,7155],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":236,"column":17,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":236,"endColumn":20,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[7910,7913],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[7910,7913],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":242,"column":28,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":242,"endColumn":31,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[8102,8105],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[8102,8105],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":264,"column":57,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":264,"endColumn":60,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[8912,8915],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[8912,8915],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":322,"column":65,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":322,"endColumn":68,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[10948,10951],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[10948,10951],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'e' is defined but never used.","line":332,"column":18,"nodeType":"Identifier","messageId":"unusedVar","endLine":332,"endColumn":19},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'getChatType' is defined but never used.","line":363,"column":10,"nodeType":"Identifier","messageId":"unusedVar","endLine":363,"endColumn":21},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":385,"column":37,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":385,"endColumn":40,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[13084,13087],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[13084,13087],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":429,"column":47,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":429,"endColumn":50,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[14856,14859],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[14856,14859],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":429,"column":80,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":429,"endColumn":83,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[14889,14892],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[14889,14892],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":434,"column":22,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":434,"endColumn":25,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[15083,15086],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[15083,15086],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":15,"fatalErrorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { prisma } from \"./prisma\";\r\nimport crypto from \"crypto\";\r\nimport { normalizeMessageContent, downloadMediaMessage, WAMessage } from \"@whiskeysockets/baileys\";\r\nimport { writeFile, mkdir } from \"fs/promises\";\r\nimport path from \"path\";\r\nimport pino from \"pino\";\r\n\r\n// Event types that can trigger webhooks\r\nexport type WebhookEventType = \r\n    | \"message.received\"\r\n    | \"message.sent\"\r\n    | \"message.status\"\r\n    | \"connection.update\"\r\n    | \"group.update\"\r\n    | \"contact.update\"\r\n    | \"status.update\";\r\n\r\ninterface WebhookPayload {\r\n    event: WebhookEventType;\r\n    sessionId: string;\r\n    timestamp: string;\r\n    data: any;\r\n}\r\n\r\n/**\r\n * Dispatch webhook to all matching endpoints\r\n */\r\nexport async function dispatchWebhook(\r\n    sessionId: string, \r\n    event: WebhookEventType, \r\n    data: any\r\n) {\r\n    try {\r\n        // Get the session to find the userId\r\n        const session = await prisma.session.findUnique({\r\n            where: { sessionId },\r\n            select: { id: true, userId: true }\r\n        });\r\n\r\n        if (!session) {\r\n            console.warn(`Webhook dispatch: Session ${sessionId} not found`);\r\n            return;\r\n        }\r\n\r\n        // Find all active webhooks for this user/session\r\n        const webhooks = await prisma.webhook.findMany({\r\n            where: {\r\n                userId: session.userId,\r\n                isActive: true,\r\n                OR: [\r\n                    { sessionId: null }, // Global webhooks\r\n                    { sessionId: session.id } // Session-specific webhooks\r\n                ]\r\n            }\r\n        });\r\n\r\n        if (webhooks.length === 0) return;\r\n\r\n        const payload: WebhookPayload = {\r\n            event,\r\n            sessionId,\r\n            timestamp: new Date().toISOString(),\r\n            data: normalizePayloadData(event, data) // Normalize data before sending\r\n        };\r\n\r\n        // Dispatch to all matching webhooks\r\n        for (const webhook of webhooks) {\r\n            // Check if this webhook subscribes to this event\r\n            const events = (webhook.events as string[]) || [];\r\n            if (!events.includes(event) && !events.includes(\"*\")) {\r\n                continue;\r\n            }\r\n\r\n            // Send webhook in background\r\n            sendWebhookRequest(webhook.url, payload, webhook.secret).catch(err => {\r\n                console.error(`Webhook ${webhook.id} failed:`, err);\r\n            });\r\n        }\r\n    } catch (error) {\r\n        console.error(\"Webhook dispatch error:\", error);\r\n    }\r\n}\r\n\r\n/**\r\n * Normalize payload data to match API format and avoid Circular/BigInt errors\r\n */\r\nfunction normalizePayloadData(event: WebhookEventType, data: any): any {\r\n    if (event === \"message.received\" || event === \"message.sent\") {\r\n        // If data is already simplified, return it\r\n        if (data.type && data.content) return data;\r\n\r\n        // If data is raw Baileys message (which we shouldn't be passing raw anymore, but just in case)\r\n        // Ideally the caller (onMessageReceived) should have already simplified it.\r\n        // But let's handle the specific fields passed by onMessageReceived below.\r\n        return data; \r\n    }\r\n    return data;\r\n}\r\n\r\n/**\r\n * JSON Replacer to handle BigInt\r\n */\r\nfunction jsonReplacer(key: string, value: any) {\r\n    if (typeof value === 'bigint') {\r\n        return value.toString();\r\n    }\r\n    return value;\r\n}\r\n\r\n/**\r\n * Send HTTP POST request to webhook endpoint\r\n */\r\nasync function sendWebhookRequest(url: string, payload: WebhookPayload, secret?: string | null) {\r\n    // Use custom replacer for BigInt support\r\n    const body = JSON.stringify(payload, jsonReplacer);\r\n    \r\n    const headers: Record<string, string> = {\r\n        \"Content-Type\": \"application/json\",\r\n        \"User-Agent\": \"WA-AKG-Webhook/1.0\"\r\n    };\r\n\r\n    // Add HMAC signature if secret is provided\r\n    if (secret) {\r\n        const signature = crypto\r\n            .createHmac(\"sha256\", secret)\r\n            .update(body)\r\n            .digest(\"hex\");\r\n        headers[\"X-Webhook-Signature\"] = `sha256=${signature}`;\r\n    }\r\n\r\n    const response = await fetch(url, {\r\n        method: \"POST\",\r\n        headers,\r\n        body,\r\n        signal: AbortSignal.timeout(10000) // 10 second timeout\r\n    });\r\n\r\n    if (!response.ok) {\r\n        throw new Error(`Webhook returned ${response.status}: ${response.statusText}`);\r\n    }\r\n\r\n    return response;\r\n}\r\n\r\n/**\r\n * Helper to download and save media\r\n */\r\nexport async function downloadAndSaveMedia(message: WAMessage, sessionId: string): Promise<string | null> {\r\n    try {\r\n        const messageContent = normalizeMessageContent(message.message);\r\n        if (!messageContent) {\r\n            console.log(\"MediaDownload: No content normalized\");\r\n            return null;\r\n        }\r\n\r\n        const messageType = Object.keys(messageContent)[0];\r\n        console.log(`MediaDownload: Types checking... Found: ${messageType}`);\r\n\r\n        if (!['imageMessage', 'videoMessage', 'audioMessage', 'documentMessage', 'stickerMessage'].includes(messageType)) {\r\n             console.log(`MediaDownload: Message type ${messageType} is not a downloadable media.`);\r\n            return null;\r\n        }\r\n        \r\n        console.log(`MediaDownload: Attempting to download ${messageType}...`);\r\n\r\n        const buffer = await downloadMediaMessage(\r\n            message,\r\n            \"buffer\",\r\n            {}\r\n        ) as Buffer;\r\n\r\n        if (!buffer) {\r\n             console.log(\"MediaDownload: Buffer is empty/null\");\r\n             return null;\r\n        }\r\n        \r\n        console.log(`MediaDownload: Downloaded ${buffer.length} bytes.`);\r\n\r\n        // Generate filename\r\n        const extMap: Record<string, string> = {\r\n            imageMessage: 'jpg',\r\n            videoMessage: 'mp4',\r\n            audioMessage: 'mp3',\r\n            documentMessage: 'bin',\r\n            stickerMessage: 'webp'\r\n        };\r\n        \r\n        let ext = extMap[messageType] || 'bin';\r\n        \r\n        // Try to get extension from mimetype if available\r\n        const mime = (messageContent as any)[messageType]?.mimetype;\r\n        if (mime) {\r\n            const mimeExt = mime.split('/')[1]?.split(';')[0];\r\n            if (mimeExt) ext = mimeExt;\r\n        }\r\n\r\n        const filename = `${sessionId}-${message.key.id}.${ext}`;\r\n        const filePath = path.join(process.cwd(), \"public\", \"media\", filename);\r\n\r\n        console.log(`MediaDownload: Saving to ${filePath}`);\r\n\r\n        // Ensure directory exists (redundant if handled by OS, but safe)\r\n        await mkdir(path.dirname(filePath), { recursive: true });\r\n        \r\n        await writeFile(filePath, buffer);\r\n        \r\n        // Return URL path using API route for reliable serving\r\n        const fileUrl = `/api/media/${filename}`;\r\n        console.log(`MediaDownload: Success. URL: ${fileUrl}`);\r\n        return fileUrl;\r\n\r\n    } catch (e) {\r\n        console.error(\"Failed to download media:\", e);\r\n        return null;\r\n    }\r\n}\r\n\r\n/**\r\n * Helper to dispatch message received event\r\n * Normalizes message content to match API structure\r\n */\r\nexport async function onMessageReceived(sessionId: string, message: any, existingFileUrl?: string | null) {\r\n    // Re-calculate fields to match store logic EXACTLY\r\n    const remoteJid = message.key?.remoteJid || \"\";\r\n    const fromMe = message.key?.fromMe || false;\r\n    const isGroup = remoteJid.endsWith(\"@g.us\");\r\n    const participant = isGroup ? (message.key?.participant || message.participant) : undefined;\r\n    \r\n    // Extract Alt JID (e.g. Phone Number JID when remoteJid is LID)\r\n    // Note: Baileys puts this in key sometimes\r\n    const remoteJidAlt = message.key?.remoteJidAlt || null;\r\n\r\n    // \"from\" is usually the chat JID (remoteJid)\r\n    // \"sender\" is who sent it. In DM: remoteJid. In Group: participant.\r\n    // If DM and remoteJidAlt exists (Phone JID), user prefers that as sender.\r\n    let sender: any = isGroup ? participant : remoteJid;\r\n    if (!isGroup && remoteJidAlt) {\r\n        sender = remoteJidAlt;\r\n    }\r\n    \r\n    // Enrich Participant Data if Group\r\n    let participantDetail: any = participant;\r\n    \r\n    if (isGroup && typeof sender === 'string') {\r\n        try {\r\n            // Need dbSessionId\r\n            const session = await prisma.session.findUnique({ \r\n                where: { sessionId },\r\n                select: { id: true }\r\n            });\r\n            \r\n            if (session) {\r\n                const group = await prisma.group.findUnique({\r\n                    where: { \r\n                        sessionId_jid: { \r\n                            sessionId: session.id, \r\n                            jid: remoteJid \r\n                        } \r\n                    },\r\n                    select: { participants: true }\r\n                });\r\n                \r\n                if (group && group.participants) {\r\n                    const parts = group.participants as any[];\r\n                    // Try to match sender or participant JID\r\n                    const found = parts.find(p => p.id === sender || p.id === participant);\r\n                    if (found) {\r\n                        sender = found;\r\n                        participantDetail = found;\r\n                    }\r\n                }\r\n            }\r\n        } catch (e) {\r\n            console.error(\"Failed to enrich participant\", e);\r\n        }\r\n    }\r\n\r\n    // Download media if available (or use existing)\r\n    let fileUrl: string | null = existingFileUrl || null;\r\n    if (!fileUrl) {\r\n        try {\r\n            fileUrl = await downloadAndSaveMedia(message, sessionId);\r\n        } catch (e) {\r\n             console.error(\"Error handling media download\", e);\r\n        }\r\n    }\r\n\r\n    const normalized = extractMessageContent(message);\r\n    const quoted = await extractQuotedMessageAsync(message, sessionId); // Extract quoted message (async now)\r\n    \r\n    dispatchWebhook(sessionId, \"message.received\", {\r\n        key: {\r\n            id: message.key?.id,\r\n            remoteJid: remoteJid,\r\n            fromMe: fromMe,\r\n            participant: participantDetail\r\n        },\r\n        pushName: message.pushName,\r\n        messageTimestamp: message.messageTimestamp,\r\n        \r\n        // Simplified Fields\r\n        from: remoteJid,            // Chat ID\r\n        sender: sender,             // Who Sent It (Preferred JID or Object)\r\n        remoteJidAlt: remoteJidAlt, // Explicit Alt Field\r\n        isGroup: isGroup,           // Boolean\r\n        \r\n        // Message Content\r\n        type: normalized.type,\r\n        content: normalized.content,\r\n        fileUrl: fileUrl,           // Link to file if media\r\n        caption: normalized.caption, // Separate caption\r\n        quoted: quoted,             // Quoted Message Details\r\n        \r\n        // Raw Data (Requested by User)\r\n        raw: message\r\n    });\r\n}\r\n\r\n/**\r\n * Helper to dispatch message sent event\r\n */\r\nexport async function onMessageSent(sessionId: string, message: any, existingFileUrl?: string | null) {\r\n    const normalized = extractMessageContent(message);\r\n    const quoted = await extractQuotedMessageAsync(message, sessionId); // Extract quoted message\r\n    const remoteJid = message.key?.remoteJid || \"\";\r\n    \r\n    // Download media for sent messages too (optional but good)\r\n    let fileUrl: string | null = existingFileUrl || null;\r\n    if (!fileUrl) {\r\n        try {\r\n            fileUrl = await downloadAndSaveMedia(message, sessionId);\r\n        } catch (e) { /* ignore */ }\r\n    }\r\n    \r\n    // For sent messages, sender is always ME (or represented by the bot)\r\n    // If it's a group, the participant might be undefined in the key if sent by us, \r\n    // but typically we are the sender.\r\n    const sender = message.key?.participant || (message.key?.fromMe ? \"ME\" : remoteJid);\r\n    const remoteJidAlt = message.key?.remoteJidAlt || null;\r\n\r\n    dispatchWebhook(sessionId, \"message.sent\", {\r\n        key: message.key,\r\n        \r\n        from: remoteJid,\r\n        sender: sender,\r\n        remoteJidAlt: remoteJidAlt, \r\n        isGroup: remoteJid.endsWith(\"@g.us\"),\r\n        \r\n        type: normalized.type,\r\n        content: normalized.content,\r\n        fileUrl: fileUrl,\r\n        caption: normalized.caption,\r\n        quoted: quoted,\r\n        \r\n        timestamp: Date.now(),\r\n        raw: message\r\n    });\r\n}\r\n\r\n/**\r\n * Determine chat type from JID\r\n */\r\nfunction getChatType(jid: string): \"PERSONAL\" | \"GROUP\" | \"STATUS\" | \"NEWSLETTER\" | \"UNKNOWN\" {\r\n    if (!jid) return \"UNKNOWN\";\r\n    if (jid.endsWith(\"@g.us\")) return \"GROUP\";\r\n    if (jid.endsWith(\"@s.whatsapp.net\")) return \"PERSONAL\";\r\n    if (jid === \"status@broadcast\") return \"STATUS\";\r\n    if (jid.endsWith(\"@newsletter\")) return \"NEWSLETTER\";\r\n    return \"UNKNOWN\";\r\n}\r\n\r\n/**\r\n * Helper to dispatch connection update event\r\n */\r\nexport function onConnectionUpdate(sessionId: string, status: string, qr?: string) {\r\n    dispatchWebhook(sessionId, \"connection.update\", {\r\n        status,\r\n        qr: qr || null\r\n    });\r\n}\r\n\r\n/**\r\n * Extract content and type from Baileys message\r\n */\r\nfunction extractMessageContent(msg: any): { type: string, content: string, caption?: string } {\r\n    const messageContent = normalizeMessageContent(msg.message);\r\n    let text = \"\";\r\n    let caption = undefined;\r\n    let messageType = \"TEXT\";\r\n\r\n    if (!messageContent) return { type: \"UNKNOWN\", content: \"\" };\r\n\r\n    if (messageContent.conversation) {\r\n        text = messageContent.conversation;\r\n    } else if (messageContent.extendedTextMessage?.text) {\r\n        text = messageContent.extendedTextMessage.text;\r\n    } else if (messageContent.imageMessage) {\r\n        messageType = \"IMAGE\";\r\n        caption = messageContent.imageMessage.caption || \"\";\r\n        text = caption; // Content often used as text display\r\n    } else if (messageContent.videoMessage) {\r\n        messageType = \"VIDEO\";\r\n        caption = messageContent.videoMessage.caption || \"\";\r\n        text = caption;\r\n    } else if (messageContent.audioMessage) {\r\n        messageType = \"AUDIO\";\r\n    } else if (messageContent.documentMessage) {\r\n        messageType = \"DOCUMENT\";\r\n        text = messageContent.documentMessage.fileName || \"\";\r\n        caption = messageContent.documentMessage.caption || \"\";\r\n    } else if (messageContent.stickerMessage) {\r\n        messageType = \"STICKER\";\r\n    } else if (messageContent.locationMessage) {\r\n        messageType = \"LOCATION\";\r\n        text = `${messageContent.locationMessage.degreesLatitude},${messageContent.locationMessage.degreesLongitude}`;\r\n    } else if (messageContent.contactMessage) {\r\n        messageType = \"CONTACT\";\r\n        text = messageContent.contactMessage.displayName || \"\";\r\n    }\r\n\r\n    return { type: messageType, content: text, caption };\r\n}\r\n\r\n\r\n\r\n/**\r\n * Extract Quoted Message recursively (Async to Lookup DB)\r\n */\r\nasync function extractQuotedMessageAsync(msg: any, sessionId: string): Promise<any> {\r\n    const messageContent = normalizeMessageContent(msg.message);\r\n    if (!messageContent) return null;\r\n    \r\n    // Check for contextInfo in common message types\r\n    let contextInfo: any = null;\r\n    \r\n    if (messageContent.extendedTextMessage) {\r\n        contextInfo = messageContent.extendedTextMessage.contextInfo;\r\n    } else if (messageContent.imageMessage) {\r\n        contextInfo = messageContent.imageMessage.contextInfo;\r\n    } else if (messageContent.videoMessage) {\r\n        contextInfo = messageContent.videoMessage.contextInfo;\r\n    } else if (messageContent.audioMessage) {\r\n        contextInfo = messageContent.audioMessage.contextInfo;\r\n    } else if (messageContent.stickerMessage) {\r\n        contextInfo = messageContent.stickerMessage.contextInfo;\r\n    } else if (messageContent.documentMessage) {\r\n        contextInfo = messageContent.documentMessage.contextInfo;\r\n    } else if (messageContent.contactMessage) {\r\n         contextInfo = messageContent.contactMessage.contextInfo;\r\n    } else if (messageContent.locationMessage) {\r\n         contextInfo = messageContent.locationMessage.contextInfo;\r\n    }\r\n\r\n    if (contextInfo && contextInfo.quotedMessage) {\r\n        const quotedMsg = contextInfo.quotedMessage;\r\n        const normalized = extractMessageContent({ message: quotedMsg });\r\n        \r\n        let fileUrl = null;\r\n        \r\n        // Lookup Media URL in DB if possible\r\n        if (contextInfo.stanzaId) {\r\n            try {\r\n                // We need the dbSessionId... this is tricky without fetching session again.\r\n                // But we can try to look up by sessionId (baileys ID) and keyId\r\n                // Message table has @@unique([sessionId, keyId]). BUT sessionId there is the CUID, not the string.\r\n                \r\n                // Fetch CUID First\r\n                 const session = await prisma.session.findUnique({\r\n                    where: { sessionId },\r\n                    select: { id: true }\r\n                });\r\n                \r\n                if (session) {\r\n                    const savedMsg = await prisma.message.findUnique({\r\n                        where: {\r\n                            sessionId_keyId: {\r\n                                sessionId: session.id,\r\n                                keyId: contextInfo.stanzaId\r\n                            }\r\n                        },\r\n                        select: { mediaUrl: true }\r\n                    });\r\n                    \r\n                    if (savedMsg?.mediaUrl) {\r\n                        fileUrl = savedMsg.mediaUrl;\r\n                    }\r\n                }\r\n            } catch (e) {\r\n                console.error(\"Failed to lookup quoted media url\", e);\r\n            }\r\n        }\r\n        \r\n        return {\r\n            key: {\r\n                remoteJid: contextInfo.remoteJid || null, // Group JID\r\n                participant: contextInfo.participant || null, // Sender JID\r\n                fromMe: contextInfo.participant === undefined, // Not reliable, better check participant\r\n                id: contextInfo.stanzaId || null\r\n            },\r\n            type: normalized.type,\r\n            content: normalized.content, // Text or Caption\r\n            caption: normalized.caption,\r\n            fileUrl: fileUrl, // <--- Added!\r\n            // We don't download quoted media automatically unless it was already saved\r\n            // raw: quotedMsg \r\n        };\r\n    }\r\n    \r\n    return null;\r\n}\r\n\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\middleware.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\modules\\whatsapp\\auth\\usePrismaAuthState.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":24,"column":62,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":24,"endColumn":65,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1017,1020],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1017,1020],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'error' is defined but never used.","line":45,"column":18,"nodeType":"Identifier","messageId":"unusedVar","endLine":45,"endColumn":23}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { prisma } from \"@/lib/prisma\";\r\nimport { AuthenticationCreds, AuthenticationState, BufferJSON, initAuthCreds, SignalDataTypeMap } from \"@whiskeysockets/baileys\";\r\n\r\nexport const usePrismaAuthState = async (sessionId: string): Promise<{ state: AuthenticationState, saveCreds: () => Promise<void> }> => {\r\n    \r\n    // Helper to read JSON with Buffer handling\r\n    const readData = async (type: string, id: string) => {\r\n        try {\r\n            const key = `${type}-${id}`;\r\n            const data = await prisma.authState.findUnique({\r\n                where: { sessionId_key: { sessionId, key } }\r\n            });\r\n            if (data && data.value) {\r\n                return JSON.parse(JSON.stringify(data.value), BufferJSON.reviver);\r\n            }\r\n            return null;\r\n        } catch (error) {\r\n            console.error('Error reading auth state:', error);\r\n            return null;\r\n        }\r\n    };\r\n\r\n    // Helper to write data\r\n    const writeData = async (type: string, id: string, data: any) => {\r\n        try {\r\n            const key = `${type}-${id}`;\r\n            const value = JSON.parse(JSON.stringify(data, BufferJSON.replacer));\r\n            \r\n            await prisma.authState.upsert({\r\n                where: { sessionId_key: { sessionId, key } },\r\n                create: { sessionId, key, value },\r\n                update: { value }\r\n            });\r\n        } catch (error) {\r\n             console.error('Error writing auth state:', error);\r\n        }\r\n    };\r\n\r\n    const removeData = async (type: string, id: string) => {\r\n        try {\r\n            const key = `${type}-${id}`;\r\n             await prisma.authState.deleteMany({\r\n                where: { sessionId, key }\r\n            });\r\n        } catch (error) {\r\n            // ignore\r\n        }\r\n    }\r\n\r\n\r\n    const creds: AuthenticationCreds = (await readData('creds', 'me')) || initAuthCreds();\r\n\r\n    return {\r\n        state: {\r\n            creds,\r\n            keys: {\r\n                get: async (type, ids) => {\r\n                    const data: { [key: string]: SignalDataTypeMap[typeof type] } = {};\r\n                    await Promise.all(ids.map(async id => {\r\n                        let value = await readData(type, id);\r\n                        if (type === 'app-state-sync-key' && value) {\r\n                            value = BufferJSON.reviver(null, value);\r\n                        }\r\n                        if (value) {\r\n                            data[id] = value;\r\n                        }\r\n                    }));\r\n                    return data;\r\n                },\r\n                set: async (data) => {\r\n                     const tasks: Promise<void>[] = [];\r\n                    for (const category in data) {\r\n                        const categoryData = data[category as keyof typeof data];\r\n                        if (!categoryData) continue;\r\n                        \r\n                        for (const id in categoryData) {\r\n                            const value = categoryData[id];\r\n                             if (value) {\r\n                                tasks.push(writeData(category, id, value));\r\n                            } else {\r\n                                tasks.push(removeData(category, id));\r\n                            }\r\n                        }\r\n                    }\r\n                    await Promise.all(tasks);\r\n                }\r\n            }\r\n        },\r\n        saveCreds: async () => {\r\n            await writeData('creds', 'me', creds);\r\n        }\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\modules\\whatsapp\\bot\\command-handler.ts","messages":[{"ruleId":"@typescript-eslint/ban-ts-comment","severity":2,"message":"Use \"@ts-expect-error\" instead of \"@ts-ignore\", as \"@ts-ignore\" will do nothing if the following line is error-free.","line":75,"column":5,"nodeType":"Line","messageId":"tsIgnoreInsteadOfExpectError","endLine":75,"endColumn":57,"suggestions":[{"messageId":"replaceTsIgnoreWithTsExpectError","fix":{"range":[2177,2229],"text":"// @ts-expect-error - Prisma Client types might lag in IDE"},"desc":"Replace \"@ts-ignore\" with \"@ts-expect-error\"."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":76,"column":40,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":76,"endColumn":43,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2270,2273],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2270,2273],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":85,"column":32,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":85,"endColumn":35,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2504,2507],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2504,2507],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":96,"column":44,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":96,"endColumn":47,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2859,2862],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2859,2862],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":110,"column":44,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":110,"endColumn":47,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3535,3538],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3535,3538],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":199,"column":37,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":199,"endColumn":40,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[6993,6996],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[6993,6996],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":205,"column":52,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":205,"endColumn":55,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[7344,7347],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[7344,7347],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":222,"column":48,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":222,"endColumn":51,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[8038,8041],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[8038,8041],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":288,"column":76,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":288,"endColumn":79,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[11738,11741],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[11738,11741],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":292,"column":107,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":292,"endColumn":110,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[12040,12043],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[12040,12043],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":301,"column":42,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":301,"endColumn":45,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[12549,12552],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[12549,12552],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":302,"column":53,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":302,"endColumn":56,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[12632,12635],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[12632,12635],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":315,"column":109,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":315,"endColumn":112,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[13333,13336],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[13333,13336],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":322,"column":44,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":322,"endColumn":47,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[13525,13528],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[13525,13528],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":328,"column":57,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":328,"endColumn":60,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[13740,13743],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[13740,13743],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":15,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { prisma } from \"@/lib/prisma\";\r\nimport type { WASocket, WAMessage } from \"@whiskeysockets/baileys\";\r\nimport { downloadMediaMessage } from \"@whiskeysockets/baileys\";\r\nimport Sticker from \"wa-sticker-formatter\";\r\nimport sharp from \"sharp\";\r\nimport fs from \"fs/promises\";\r\nimport path from \"path\";\r\nimport os from \"os\";\r\nimport { exec } from \"child_process\";\r\nimport { promisify } from \"util\";\r\n\r\nconst execAsync = promisify(exec);\r\n\r\n// Map to track start times for uptime\r\nconst startTimes = new Map<string, number>();\r\n\r\n// Default bot config\r\n// Default bot config\r\nconst DEFAULT_CONFIG = {\r\n    enabled: true,\r\n    botMode: 'OWNER',\r\n    botAllowedJids: [] as string[],\r\n    autoReplyMode: 'ALL',\r\n    autoReplyAllowedJids: [] as string[],\r\n    enableSticker: true,\r\n    enableVideoSticker: true,\r\n    maxStickerDuration: 10,\r\n    enablePing: true,\r\n    enableUptime: true,\r\n    botName: \"WA-AKG Bot\",\r\n    removeBgApiKey: null as string | null\r\n};\r\n\r\nexport function setSessionStartTime(sessionId: string) {\r\n    if (!startTimes.has(sessionId)) {\r\n        startTimes.set(sessionId, Date.now());\r\n    }\r\n}\r\n\r\nexport async function handleBotCommand(\r\n    sock: WASocket | undefined,\r\n    sessionId: string,\r\n    msg: WAMessage\r\n) {\r\n    if (!sock || !msg.message || !msg.key.remoteJid) return;\r\n\r\n    const remoteJid = msg.key.remoteJid;\r\n    const fromMe = msg.key.fromMe || false;\r\n\r\n    // Get text content\r\n    let text = \"\";\r\n    const messageContent = msg.message;\r\n\r\n    if (messageContent.conversation) {\r\n        text = messageContent.conversation;\r\n    } else if (messageContent.extendedTextMessage?.text) {\r\n        text = messageContent.extendedTextMessage.text;\r\n    } else if (messageContent.imageMessage?.caption) {\r\n        text = messageContent.imageMessage.caption;\r\n    } else if (messageContent.videoMessage?.caption) {\r\n        text = messageContent.videoMessage.caption;\r\n    }\r\n\r\n    if (!text.startsWith(\"#\")) return;\r\n\r\n    // Fetch session first\r\n    const session = await prisma.session.findUnique({\r\n        where: { sessionId },\r\n        select: { id: true }\r\n    });\r\n\r\n    if (!session) return;\r\n\r\n    // Fetch BotConfig separately\r\n    // @ts-ignore - Prisma Client types might lag in IDE\r\n    const botConfig = await (prisma as any).botConfig.findUnique({\r\n        where: { sessionId: session.id }\r\n    });\r\n\r\n    const config = botConfig || DEFAULT_CONFIG;\r\n\r\n    if (!config.enabled) return;\r\n\r\n    // Verify Access Permissions\r\n    const botMode = (config as any).botMode || 'OWNER'; // Default to OWNER if missing\r\n\r\n    // Check Permission\r\n    let canExecute = false;\r\n\r\n    if (fromMe) {\r\n        canExecute = true; // Owner always allowed\r\n    } else {\r\n        if (botMode === 'ALL') {\r\n            canExecute = true;\r\n        } else if (botMode === 'SPECIFIC') {\r\n            const allowedJids = (config as any).botAllowedJids || [];\r\n            // Standardized Sender Logic (matches webhook & store)\r\n            const isGroup = msg.key.remoteJid?.endsWith(\"@g.us\") || false;\r\n            const remoteJidAlt = msg.key.remoteJidAlt;\r\n            let senderJid = (isGroup ? (msg.key.participant || msg.participant) : msg.key.remoteJid) || \"\";\r\n\r\n            if (!isGroup && remoteJidAlt) {\r\n                senderJid = remoteJidAlt;\r\n            }\r\n\r\n            if (Array.isArray(allowedJids)) {\r\n                canExecute = allowedJids.some(jid => senderJid.includes(jid));\r\n            }\r\n        } else if (botMode === 'BLACKLIST') {\r\n            const blockedJids = (config as any).botBlockedJids || [];\r\n            const isGroup = msg.key.remoteJid?.endsWith(\"@g.us\") || false;\r\n            const remoteJidAlt = msg.key.remoteJidAlt;\r\n            let senderJid = (isGroup ? (msg.key.participant || msg.participant) : msg.key.remoteJid) || \"\";\r\n\r\n            if (!isGroup && remoteJidAlt) {\r\n                senderJid = remoteJidAlt;\r\n            }\r\n\r\n            // If blacklist, allowed by default UNLESS in blocked list\r\n            canExecute = true;\r\n            if (Array.isArray(blockedJids)) {\r\n                const isBlocked = blockedJids.some(jid => senderJid.includes(jid));\r\n                if (isBlocked) canExecute = false;\r\n            }\r\n        }\r\n    }\r\n\r\n    if (!canExecute) return;\r\n\r\n    const [command, ...args] = text.trim().split(\" \");\r\n    const cmd = command.toLowerCase().slice(1); // remove #\r\n\r\n    try {\r\n        switch (cmd) {\r\n            case \"ping\": {\r\n                if (!config.enablePing) return;\r\n                await sock.sendMessage(remoteJid, { text: \"Pong! ≡ƒÅô\" }, { quoted: msg });\r\n                break;\r\n            }\r\n\r\n            case \"id\": {\r\n                await sock.sendMessage(remoteJid, {\r\n                    text: `*Chat ID:* \\`${remoteJid}\\``\r\n                }, { quoted: msg });\r\n                break;\r\n            }\r\n\r\n            case \"uptime\": {\r\n                if (!config.enableUptime) return;\r\n\r\n                const start = startTimes.get(sessionId) || Date.now();\r\n                const uptimeMs = Date.now() - start;\r\n                const hours = Math.floor(uptimeMs / 3600000);\r\n                const minutes = Math.floor((uptimeMs % 3600000) / 60000);\r\n                const seconds = Math.floor((uptimeMs % 60000) / 1000);\r\n\r\n                await sock.sendMessage(remoteJid, {\r\n                    text: `*Session Uptime:* ${hours}h ${minutes}m ${seconds}s`\r\n                }, { quoted: msg });\r\n                break;\r\n            }\r\n\r\n            case \"sticker\":\r\n            case \"s\":\r\n            case \"stiker\": {\r\n                if (!config.enableSticker) return;\r\n\r\n                // Check if message has image or video\r\n                let mediaMsg: WAMessage | null = msg;\r\n\r\n                // If quoted, check quoted\r\n                const quoted = messageContent.extendedTextMessage?.contextInfo?.quotedMessage;\r\n                if (quoted) {\r\n                    mediaMsg = {\r\n                        key: {\r\n                            remoteJid,\r\n                            id: messageContent.extendedTextMessage?.contextInfo?.stanzaId,\r\n                        },\r\n                        message: quoted\r\n                    } as WAMessage;\r\n                }\r\n\r\n                const msgContent = mediaMsg.message;\r\n                const isImage = !!msgContent?.imageMessage;\r\n                const isVideo = !!msgContent?.videoMessage;\r\n\r\n                if (!isImage && !isVideo) {\r\n                    await sock.sendMessage(remoteJid, { text: \"Γ¥î Please reply to an image/video or send media with caption #sticker\" }, { quoted: msg });\r\n                    return;\r\n                }\r\n\r\n                if (msgContent?.extendedTextMessage) {\r\n                    await sock.sendMessage(remoteJid, { text: \"Γ¥î Cannot convert text message to sticker.\" }, { quoted: msg });\r\n                    return;\r\n                }\r\n\r\n                // Handle Video Limits\r\n                if (isVideo) {\r\n                    if (!(config as any).enableVideoSticker) {\r\n                        await sock.sendMessage(remoteJid, { text: \"Γ¥î Video stickers are disabled in bot settings.\" }, { quoted: msg });\r\n                        return;\r\n                    }\r\n\r\n                    const seconds = msgContent?.videoMessage?.seconds || 0;\r\n                    const maxDuration = (config as any).maxStickerDuration || 10;\r\n\r\n                    if (seconds > maxDuration) {\r\n                        await sock.sendMessage(remoteJid, { text: `Γ¥î Video too long! Max duration is ${maxDuration} seconds.` }, { quoted: msg });\r\n                        return;\r\n                    }\r\n                }\r\n\r\n                await sock.sendMessage(remoteJid, { react: { text: \"ΓÅ│\", key: msg.key } });\r\n\r\n                try {\r\n                    // Download\r\n                    let buffer = await downloadMediaMessage(\r\n                        mediaMsg,\r\n                        \"buffer\",\r\n                        {},\r\n                        {\r\n                            logger: console as any,\r\n                            reuploadRequest: sock.updateMediaMessage\r\n                        }\r\n                    ) as Buffer;\r\n\r\n                    // Resize/Compress Logic\r\n                    if (isImage) {\r\n                        try {\r\n                            // Use limitInputPixels: false to handle large images\r\n                            buffer = await sharp(buffer, { limitInputPixels: false })\r\n                                .resize(512, 512, { // Resize to standard 512x512 sticker size directly\r\n                                    fit: 'inside',\r\n                                    withoutEnlargement: true\r\n                                })\r\n                                .toBuffer();\r\n                        } catch (resizeErr) {\r\n                            console.error(\"Image Resize failed\", resizeErr);\r\n                        }\r\n                    } else if (isVideo) {\r\n                        try {\r\n                            const tempInput = path.join(os.tmpdir(), `input_${Date.now()}.mp4`);\r\n                            const tempOutput = path.join(os.tmpdir(), `output_${Date.now()}.mp4`);\r\n\r\n                            await fs.writeFile(tempInput, buffer);\r\n\r\n                            // Compress Video using ffmpeg\r\n                            // Extreme Compression: 8fps, CRF 40, 300k bitrate, ultrafast\r\n                            await execAsync(`ffmpeg -y -i \"${tempInput}\" -vf \"scale=512:512:force_original_aspect_ratio=decrease,fps=10\" -c:v libx264 -preset ultrafast -crf 40 -b:v 300k -maxrate 300k -bufsize 600k -an \"${tempOutput}\"`);\r\n\r\n                            buffer = await fs.readFile(tempOutput);\r\n\r\n                            // Cleanup\r\n                            await fs.unlink(tempInput).catch(() => { });\r\n                            await fs.unlink(tempOutput).catch(() => { });\r\n                        } catch (videoErr) {\r\n                            console.error(\"Video Compression failed\", videoErr);\r\n                            // Continue with original buffer if compression fails, or throw? \r\n                            // If it fails, likely original will fail too, but let's try.\r\n                        }\r\n                    }\r\n\r\n                    // Check for background removal (Only for Images)\r\n                    const isRemoveBg = args.includes(\"nobg\") || args.includes(\"removebg\");\r\n                    if (isImage && isRemoveBg && config.removeBgApiKey) {\r\n                        try {\r\n                            // Convert Buffer to Uint8Array for Blob compatibility\r\n                            const uint8Array = new Uint8Array(buffer);\r\n                            const blob = new Blob([uint8Array], { type: 'image/png' });\r\n\r\n                            const formData = new FormData();\r\n                            formData.append('image_file', blob, 'image.png');\r\n                            formData.append('size', 'auto');\r\n\r\n                            const res = await fetch('https://api.remove.bg/v1.0/removebg', {\r\n                                method: 'POST',\r\n                                headers: {\r\n                                    'X-Api-Key': config.removeBgApiKey\r\n                                },\r\n                                body: formData\r\n                            });\r\n\r\n                            if (res.ok) {\r\n                                const arrayBuffer = await res.arrayBuffer();\r\n                                buffer = Buffer.from(arrayBuffer);\r\n                            } else {\r\n                                const err = await res.json();\r\n                                throw new Error(`RemoveBG Error: ${(err as any).errors?.[0]?.title || res.statusText}`);\r\n                            }\r\n                        } catch (bgError) {\r\n                            console.error(\"RemoveBG Failed:\", bgError);\r\n                            await sock.sendMessage(remoteJid, { text: `ΓÜá∩╕Å Remove BG failed: ${(bgError as any).message}. Sending normal sticker...` }, { quoted: msg });\r\n                        }\r\n                    } else if (isImage && isRemoveBg && !config.removeBgApiKey) {\r\n                        await sock.sendMessage(remoteJid, { text: `ΓÜá∩╕Å Remove BG API Key not configured in dashboard. Sending normal sticker...` }, { quoted: msg });\r\n                    }\r\n\r\n\r\n                    // Convert\r\n                    const sticker = new Sticker(buffer as Buffer, {\r\n                        pack: (config as any).botName || \"WA-AKG Bot\",\r\n                        author: \"By \" + ((config as any).botName || \"WA-AKG Bot\"),\r\n                        type: \"full\", // full, crop, circle\r\n                        quality: 15 // Extreme quality reduction for size\r\n                    });\r\n\r\n                    const stickerBuffer = await sticker.toBuffer();\r\n\r\n                    // Send\r\n                    await sock.sendMessage(remoteJid, { sticker: stickerBuffer }, { quoted: msg });\r\n                    await sock.sendMessage(remoteJid, { react: { text: \"Γ£à\", key: msg.key } });\r\n\r\n                } catch (e) {\r\n                    console.error(\"Sticker generation failed\", e);\r\n                    await sock.sendMessage(remoteJid, { text: \"Γ¥î Failed to create sticker. Error: \" + (e as any).message }, { quoted: msg });\r\n                }\r\n                break;\r\n            }\r\n\r\n            case \"menu\":\r\n            case \"help\": {\r\n                const botName = (config as any).botName || \"WA-AKG Bot\";\r\n                const menu = `\r\n≡ƒñû *${botName} Menu* ≡ƒñû\r\n\r\n≡ƒôî *Commands:*\r\nΓÇó *#sticker* / *#s*: Convert Image/Video to Sticker\r\n  - Supports Images, GIFs, and Videos (max ${(config as any).maxStickerDuration || 10}s)\r\n  - Use *#sticker nobg* to remove background (Images only)\r\nΓÇó *#ping*: Check Bot Status\r\nΓÇó *#uptime*: Check Session Uptime\r\nΓÇó *#id*: Get Chat ID\r\n\r\n_Made with Γ¥ñ∩╕Å_\r\n`;\r\n                await sock.sendMessage(remoteJid, { text: menu }, { quoted: msg });\r\n                break;\r\n            }\r\n\r\n            default:\r\n                // Ignore unknown commands\r\n                break;\r\n        }\r\n    } catch (e) {\r\n        console.error(\"Bot command error\", e);\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\modules\\whatsapp\\instance.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":26,"column":13,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":26,"endColumn":16,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[842,845],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[842,845],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"react-hooks/rules-of-hooks","severity":2,"message":"React Hook \"usePrismaAuthState\" cannot be called in a class component. React Hooks must be called in a React function component or a custom React Hook function.","line":42,"column":44,"nodeType":"Identifier","endLine":42,"endColumn":62},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":47,"column":82,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":47,"endColumn":85,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1623,1626],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1623,1626],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":51,"column":124,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":51,"endColumn":127,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1849,1852],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1849,1852],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":91,"column":56,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":91,"endColumn":59,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3384,3387],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3384,3387],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'e' is defined but never used.","line":114,"column":26,"nodeType":"Identifier","messageId":"unusedVar","endLine":114,"endColumn":27},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'e' is defined but never used.","line":134,"column":30,"nodeType":"Identifier","messageId":"unusedVar","endLine":134,"endColumn":31},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":173,"column":25,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":173,"endColumn":28,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[7137,7140],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[7137,7140],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":6,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import makeWASocket, {\r\n    DisconnectReason,\r\n    fetchLatestBaileysVersion,\r\n    makeCacheableSignalKeyStore,\r\n    WASocket,\r\n    ConnectionState\r\n} from \"@whiskeysockets/baileys\";\r\nimport { prisma } from \"@/lib/prisma\";\r\nimport { usePrismaAuthState } from \"./auth/usePrismaAuthState\";\r\nimport { Server } from \"socket.io\";\r\nimport pino from \"pino\";\r\nimport { bindSessionStore } from \"./store\";\r\nimport { syncGroups } from \"./store/groups\";\r\nimport { bindContactSync } from \"./store/contacts\";\r\nimport { bindAutoReply } from \"./store/autoreply\";\r\nimport { bindPpGuard } from \"./store/ppguard\";\r\n\r\nexport class WhatsAppInstance {\r\n    socket: WASocket | null = null;\r\n    qr: string | null = null;\r\n    rq: string | null = null;\r\n    status: string = \"DISCONNECTED\";\r\n    sessionId: string;\r\n    userId: string;\r\n    io: Server;\r\n    config: any = {};\r\n    startTime: Date | null = null;\r\n\r\n    isStopped: boolean = false;\r\n\r\n    constructor(sessionId: string, userId: string, io: Server) {\r\n        this.sessionId = sessionId;\r\n        this.userId = userId;\r\n        this.io = io;\r\n    }\r\n\r\n    async init() {\r\n        this.isStopped = false; // Reset stop flag on init\r\n        const sessionData = await prisma.session.findUnique({ where: { sessionId: this.sessionId } });\r\n        this.config = sessionData?.config || {};\r\n        \r\n        const { state, saveCreds } = await usePrismaAuthState(this.sessionId);\r\n        const { version } = await fetchLatestBaileysVersion();\r\n\r\n        this.socket = makeWASocket({\r\n            version,\r\n            logger: pino({ level: process.env.BAILEYS_LOG_LEVEL || \"error\" }) as any,\r\n            printQRInTerminal: false,\r\n            auth: {\r\n                creds: state.creds,\r\n                keys: makeCacheableSignalKeyStore(state.keys, pino({ level: process.env.BAILEYS_LOG_LEVEL || \"error\" }) as any),\r\n            },\r\n            browser: [\"WA-AKG\", \"Chrome\", \"1.0.0\"],\r\n            markOnlineOnConnect: true,\r\n            syncFullHistory: true, // Enable history sync to get contacts\r\n        });\r\n        \r\n        // Bind Store for DB Sync (handles incoming messages)\r\n        bindSessionStore(this.socket, this.sessionId, this.io);\r\n        \r\n        // Bind Contact Sync (handles contacts.update and messaging-history.set events)\r\n        bindContactSync(this.socket, this.sessionId);\r\n\r\n        this.socket.ev.on(\"creds.update\", saveCreds);\r\n\r\n        this.socket.ev.on(\"connection.update\", async (update) => {\r\n             await this.handleConnectionUpdate(update);\r\n        });\r\n    }\r\n\r\n    async handleConnectionUpdate(update: Partial<ConnectionState>) {\r\n        const { connection, lastDisconnect, qr } = update;\r\n\r\n        try {\r\n            if (qr) {\r\n                if (this.isStopped) return; // Don't emit QR if stopped\r\n                this.qr = qr;\r\n                this.status = \"SCAN_QR\";\r\n                \r\n                // Emit QR to Socket Room\r\n                this.io?.to(this.sessionId).emit(\"connection.update\", { status: this.status, qr });\r\n                \r\n                // Update DB\r\n                await prisma.session.update({\r\n                    where: { sessionId: this.sessionId },\r\n                    data: { qr, status: \"SCAN_QR\" }\r\n                });\r\n            }\r\n            \r\n            if (connection === \"close\") {\r\n                const code = (lastDisconnect?.error as any)?.output?.statusCode;\r\n                const isLoggedOut = code === DisconnectReason.loggedOut;\r\n                \r\n                // Only reconnect if NOT logged out AND NOT explicitly stopped\r\n                const shouldReconnect = !isLoggedOut && !this.isStopped;\r\n                \r\n                // Determine status based on reason\r\n                if (isLoggedOut) {\r\n                    this.status = \"LOGGED_OUT\";\r\n                } else if (this.isStopped) {\r\n                    this.status = \"STOPPED\";\r\n                } else {\r\n                    this.status = \"DISCONNECTED\";\r\n                }\r\n                \r\n                this.io?.to(this.sessionId).emit(\"connection.update\", { status: this.status, qr: null });\r\n                 \r\n                // Use try-catch specifically for update as session might be deleted\r\n                try {\r\n                    await prisma.session.update({\r\n                        where: { sessionId: this.sessionId },\r\n                        data: { status: this.status, qr: null }\r\n                    });\r\n                } catch (e) {\r\n                    // Ignore if session not found (deleted)\r\n                }\r\n\r\n                if (shouldReconnect) {\r\n                    // Connection lost unexpectedly, reconnect\r\n                    this.init();\r\n                } else if (isLoggedOut) {\r\n                    // Explicit logout: delete credentials\r\n                    console.log(`Session ${this.sessionId} logged out. Deleting credentials...`);\r\n                    try {\r\n                        await prisma.$transaction([\r\n                            prisma.session.update({\r\n                                where: { sessionId: this.sessionId },\r\n                                data: { status: \"LOGGED_OUT\", qr: null }\r\n                            }),\r\n                            prisma.authState.deleteMany({\r\n                                where: { sessionId: this.sessionId }\r\n                            })\r\n                        ]);\r\n                    } catch (e) { /* ignore */ }\r\n                    this.socket = null;\r\n                    this.config = {}; // Clear config cache\r\n                    console.log(`Session ${this.sessionId} credentials deleted.`);\r\n                } else if (this.isStopped) {\r\n                    // Stopped: preserve credentials for future restart\r\n                    console.log(`Session ${this.sessionId} stopped. Credentials preserved for auto-login.`);\r\n                    this.socket = null;\r\n                }\r\n            }\r\n\r\n\r\n            if (connection === \"open\") {\r\n                this.status = \"CONNECTED\";\r\n                this.qr = null;\r\n                this.startTime = new Date();\r\n                \r\n                this.io?.to(this.sessionId).emit(\"connection.update\", { status: this.status, qr: null });\r\n                \r\n                // Sync Groups from WhatsApp (with error handling)\r\n                try {\r\n                    await syncGroups(this.socket as WASocket, this.sessionId);\r\n                } catch (e) {\r\n                    console.error(\"Group sync failed:\", e);\r\n                }\r\n                \r\n                // Bind Auto Reply\r\n                bindAutoReply(this.socket as WASocket, this.sessionId);\r\n                \r\n                // Bind PP Guard\r\n                bindPpGuard(this.socket as WASocket, this.sessionId);\r\n\r\n                await prisma.session.update({\r\n                    where: { sessionId: this.sessionId },\r\n                    data: { status: \"CONNECTED\", qr: null }\r\n                });\r\n                \r\n                console.log(`Session ${this.sessionId} connected and synced successfully`);\r\n            }\r\n        } catch (error: any) {\r\n            // Catch global errors in handler (like Record Not Found if session deleted mid-process)\r\n            if (error.code === 'P2025') {\r\n                console.warn(`Session ${this.sessionId} record not found during update. Stopping instance.`);\r\n                this.socket?.end(undefined);\r\n                this.socket = null;\r\n            } else {\r\n                console.error(\"Error in handleConnectionUpdate:\", error);\r\n            }\r\n        }\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\modules\\whatsapp\\manager.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":42,"column":36,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":42,"endColumn":39,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1463,1466],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1463,1466],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":43,"column":34,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":43,"endColumn":37,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1508,1511],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1508,1511],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { prisma } from \"@/lib/prisma\";\r\nimport { WhatsAppInstance } from \"./instance\";\r\nimport { Server } from \"socket.io\";\r\nimport { initScheduler } from \"@/lib/cron\";\r\n\r\nexport class WhatsAppManager {\r\n    private static instance: WhatsAppManager;\r\n    private sessions: Map<string, WhatsAppInstance> = new Map();\r\n    public io: Server | null = null;\r\n    \r\n    private constructor() {\r\n        initScheduler();\r\n    }\r\n\r\n    public static getInstance(): WhatsAppManager {\r\n        if (!WhatsAppManager.instance) {\r\n            WhatsAppManager.instance = new WhatsAppManager();\r\n        }\r\n        return WhatsAppManager.instance;\r\n    }\r\n\r\n    setup(io: Server) {\r\n        this.io = io;\r\n    }\r\n\r\n    async loadSessions() {\r\n        if (!this.io) throw new Error(\"Socket.IO not initialized in WhatsAppManager\");\r\n        const sessions = await prisma.session.findMany({\r\n            where: { status: { not: \"LOGGED_OUT\" } }\r\n        });\r\n\r\n        for (const session of sessions) {\r\n            const instance = new WhatsAppInstance(session.sessionId, session.userId, this.io);\r\n            this.sessions.set(session.sessionId, instance);\r\n            await instance.init();\r\n        }\r\n        console.log(`Loaded ${sessions.length} sessions.`);\r\n    }\r\n\r\n    async createSession(userId: string, name: string, customSessionId?: string) {\r\n        // Fallback to global IO if instance IO is missing (Next.js Context Issue)\r\n        if (!this.io && (global as any).io) {\r\n            this.io = (global as any).io;\r\n        }\r\n\r\n        if (!this.io) {\r\n             console.error(\"Socket.IO not initialized in WhatsAppManager, and global fallback failed.\");\r\n             throw new Error(\"Socket.IO not initialized\");\r\n        }\r\n        \r\n        // Use custom ID if provided, otherwise generate random\r\n        const sessionId = customSessionId || Math.random().toString(36).substring(7);\r\n\r\n        const session = await prisma.session.create({\r\n            data: {\r\n                userId,\r\n                name,\r\n                sessionId,\r\n                status: \"DISCONNECTED\",\r\n                botConfig: {\r\n                    create: {\r\n                        enabled: true,\r\n                        botMode: \"OWNER\",\r\n                        autoReplyMode: \"ALL\"\r\n                    }\r\n                }\r\n            }\r\n        });\r\n\r\n        const instance = new WhatsAppInstance(sessionId, userId, this.io);\r\n        this.sessions.set(sessionId, instance);\r\n        await instance.init();\r\n\r\n        return session;\r\n    }\r\n\r\n    public getInstance(sessionId: string) {\r\n        return this.sessions.get(sessionId);\r\n    }\r\n    \r\n    async deleteSession(sessionId: string) {\r\n        const instance = this.sessions.get(sessionId);\r\n        if (instance) {\r\n             // Logout/Close socket\r\n             instance.socket?.end(undefined);\r\n             this.sessions.delete(sessionId);\r\n        }\r\n        await prisma.session.delete({ where: { sessionId } });\r\n    }\r\n\r\n    async stopSession(sessionId: string) {\r\n        const instance = this.sessions.get(sessionId);\r\n        if (instance) {\r\n            instance.isStopped = true; // Prevent auto-reconnect\r\n            instance.socket?.end(undefined);\r\n            instance.status = \"STOPPED\";\r\n            this.io?.to(sessionId).emit(\"connection.update\", { status: \"STOPPED\", qr: null });\r\n            await prisma.session.update({\r\n                where: { sessionId },\r\n                data: { status: \"STOPPED\" }\r\n            });\r\n        }\r\n    }\r\n\r\n    async startSession(sessionId: string) {\r\n        // If already running, do nothing\r\n        const existingInstance = this.sessions.get(sessionId);\r\n        if (existingInstance && existingInstance.status === \"CONNECTED\") {\r\n            return;\r\n        }\r\n\r\n        const session = await prisma.session.findUnique({ where: { sessionId } });\r\n        if (!session) throw new Error(\"Session not found\");\r\n\r\n        // Re-initialize\r\n        let instance = this.sessions.get(sessionId);\r\n        if (!instance) {\r\n            instance = new WhatsAppInstance(sessionId, session.userId, this.io!);\r\n            this.sessions.set(sessionId, instance);\r\n        }\r\n        \r\n        await instance.init();\r\n    }\r\n\r\n    async restartSession(sessionId: string) {\r\n        await this.stopSession(sessionId);\r\n        // Small delay to ensure cleanup\r\n        await new Promise(resolve => setTimeout(resolve, 1000));\r\n        await this.startSession(sessionId);\r\n    }\r\n}\r\n\r\nconst globalForWhatsapp = global as unknown as { waManager: WhatsAppManager };\r\n\r\nexport const waManager = globalForWhatsapp.waManager || WhatsAppManager.getInstance();\r\n\r\n// Always store in global to ensure singleton across Next.js compilations/chunks\r\nglobalForWhatsapp.waManager = waManager;\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\modules\\whatsapp\\scheduler.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":25,"column":34,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":25,"endColumn":37,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[824,827],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[824,827],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { prisma } from \"@/lib/prisma\";\r\nimport { waManager } from \"./manager\";\r\n\r\nconst checkScheduledMessages = async () => {\r\n    try {\r\n        const now = new Date();\r\n        console.log(`[Scheduler] Checking for messages due before ${now.toISOString()}...`);\r\n\r\n        const pendingMessages = await prisma.scheduledMessage.findMany({\r\n            where: {\r\n                status: \"PENDING\",\r\n                sendAt: { lte: now }\r\n            }\r\n        });\r\n\r\n        if (pendingMessages.length > 0) {\r\n            console.log(`[Scheduler] Found ${pendingMessages.length} pending messages.`);\r\n        }\r\n\r\n        for (const msg of pendingMessages) {\r\n            const instance = waManager.getInstance(msg.sessionId);\r\n\r\n            if (instance?.socket) {\r\n                try {\r\n                    let content: any = {};\r\n                    // Simple text support for now, expand for media later\r\n                    if (msg.mediaUrl) {\r\n                        const url = msg.mediaUrl;\r\n                        const type = msg.mediaType || 'image'; // Default to image if null\r\n\r\n                        if (type === 'video') {\r\n                            content = { video: { url }, caption: msg.content };\r\n                        } else if (type === 'document') {\r\n                            content = { document: { url }, caption: msg.content, fileName: 'file', mimetype: 'application/octet-stream' };\r\n                        } else {\r\n                            content = { image: { url }, caption: msg.content };\r\n                        }\r\n                    } else {\r\n                        content = { text: msg.content };\r\n                    }\r\n\r\n                    await instance.socket.sendMessage(msg.jid, content);\r\n\r\n                    await prisma.scheduledMessage.update({\r\n                        where: { id: msg.id },\r\n                        data: { status: \"SENT\" }\r\n                    });\r\n                    console.log(`[Scheduler] Msg ${msg.id} sent to ${msg.jid}`);\r\n\r\n                } catch (err) {\r\n                    console.error(`[Scheduler] Failed to send scheduled msg ${msg.id}`, err);\r\n                    await prisma.scheduledMessage.update({\r\n                        where: { id: msg.id },\r\n                        data: { status: \"FAILED\" }\r\n                    });\r\n                }\r\n            } else {\r\n                console.log(`[Scheduler] Session ${msg.sessionId} not connected for scheduled msg ${msg.id}`);\r\n                // Optionally mark as failed or leave pending\r\n            }\r\n        }\r\n    } catch (e) {\r\n        console.error(\"[Scheduler] Error:\", e);\r\n    }\r\n};\r\n\r\nexport function startScheduler() {\r\n    console.log(\"Starting Message Scheduler...\");\r\n\r\n    // Run immediately on start\r\n    checkScheduledMessages();\r\n\r\n    // Then run every 30 seconds\r\n    setInterval(checkScheduledMessages, 30 * 1000);\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\modules\\whatsapp\\store\\autoreply.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":6,"column":31,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":6,"endColumn":34,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[299,302],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[299,302],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/ban-ts-comment","severity":2,"message":"Use \"@ts-expect-error\" instead of \"@ts-ignore\", as \"@ts-ignore\" will do nothing if the following line is error-free.","line":60,"column":13,"nodeType":"Line","messageId":"tsIgnoreInsteadOfExpectError","endLine":60,"endColumn":26,"suggestions":[{"messageId":"replaceTsIgnoreWithTsExpectError","fix":{"range":[2500,2513],"text":"// @ts-expect-error"},"desc":"Replace \"@ts-ignore\" with \"@ts-expect-error\"."}]},{"ruleId":"@typescript-eslint/ban-ts-comment","severity":2,"message":"Use \"@ts-expect-error\" instead of \"@ts-ignore\", as \"@ts-ignore\" will do nothing if the following line is error-free.","line":66,"column":9,"nodeType":"Line","messageId":"tsIgnoreInsteadOfExpectError","endLine":66,"endColumn":22,"suggestions":[{"messageId":"replaceTsIgnoreWithTsExpectError","fix":{"range":[2613,2626],"text":"// @ts-expect-error"},"desc":"Replace \"@ts-ignore\" with \"@ts-expect-error\"."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":67,"column":34,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":67,"endColumn":37,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2661,2664],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2661,2664],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'e' is defined but never used.","line":134,"column":38,"nodeType":"Identifier","messageId":"unusedVar","endLine":134,"endColumn":39},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":143,"column":54,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":143,"endColumn":57,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[5708,5711],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[5708,5711],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":5,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { prisma } from \"@/lib/prisma\";\r\nimport type { WASocket } from \"@whiskeysockets/baileys\";\r\nimport { normalizeMessageContent } from \"@whiskeysockets/baileys\";\r\n\r\n// Helper for permission check (Deduplicate from command-handler if possible, but keep simple here)\r\nfunction canAutoReply(config: any, fromMe: boolean, senderJid: string): boolean {\r\n    if (!config || !config.enabled) return false;\r\n\r\n    // Auto Reply Specific Mode\r\n    const mode = config.autoReplyMode || 'ALL';\r\n\r\n    if (fromMe) {\r\n        // If mode is OWNER, it triggers for ME? \r\n        // Auto Reply usually replies TO someone. \r\n        // If I send a message, and mode is OWNER, should it reply to me? \r\n        // User requested \"Self Mode\" -> Use case: Snippets.\r\n        // So yes, if fromMe checks out.\r\n\r\n        // However, standard auto-reply logic (replying to incoming) should be blocked if fromMe is true AND mode is ALL?\r\n        // No, typically Auto Reply doesn't trigger on own messages to prevent unexpected loops.\r\n        // But for \"Self Mode\" (Macros), it MUST trigger on own messages.\r\n\r\n        if (mode === 'OWNER') return true;\r\n        if (mode === 'ALL') return false; // Standard auto-reply ignores self\r\n\r\n        // Specific? \r\n        return false;\r\n    } else {\r\n        // Incoming message from others\r\n        if (mode === 'OWNER') return false; // Owner only acts on Owner messages\r\n        if (mode === 'ALL') return true;\r\n\r\n        if (mode === 'SPECIFIC') {\r\n            const allowedJids = config.autoReplyAllowedJids || [];\r\n            if (Array.isArray(allowedJids)) {\r\n                return allowedJids.some((jid: string) => senderJid.includes(jid));\r\n            }\r\n        }\r\n\r\n        if (mode === 'BLACKLIST') {\r\n            const blockedJids = config.autoReplyBlockedJids || [];\r\n            if (Array.isArray(blockedJids)) {\r\n                const isBlocked = blockedJids.some((jid: string) => senderJid.includes(jid));\r\n                return !isBlocked; // Return true if NOT blocked\r\n            }\r\n            return true; // If blacklist empty, allow all\r\n        }\r\n    }\r\n\r\n    return false;\r\n}\r\n\r\nexport async function bindAutoReply(sock: WASocket, sessionId: string) {\r\n    sock.ev.on('messages.upsert', async ({ messages, type }) => {\r\n        if (type !== 'notify') return;\r\n\r\n        // Fetch session ID and Bot Config once per batch (optimization)\r\n        const session = await prisma.session.findUnique({\r\n            where: { sessionId },\r\n            // @ts-ignore\r\n            include: { botConfig: true }\r\n        });\r\n\r\n        if (!session) return;\r\n\r\n        // @ts-ignore\r\n        let config = (session as any).botConfig;\r\n\r\n        if (!config) {\r\n            console.log(\"AutoReply: No config found, creating default...\");\r\n            config = await prisma.botConfig.create({\r\n                data: {\r\n                    sessionId: session.id,\r\n                    enabled: true,\r\n                    botMode: 'OWNER',\r\n                    autoReplyMode: 'ALL'\r\n                }\r\n            });\r\n        }\r\n\r\n        console.log(`AutoReply: Processing for ${sessionId}. Config:`, config ? \"Found\" : \"Missing\", config?.enabled ? \"Enabled\" : \"Disabled\");\r\n\r\n        if (!config || !config.enabled) return;\r\n\r\n        for (const msg of messages) {\r\n            const fromMe = msg.key.fromMe || false;\r\n            const remoteJid = msg.key.remoteJid;\r\n\r\n            // Standardized Sender Logic\r\n            const isGroup = remoteJid?.endsWith(\"@g.us\") || false;\r\n            const remoteJidAlt = msg.key.remoteJidAlt;\r\n            let senderJid = (isGroup ? (msg.key.participant || msg.participant) : remoteJid);\r\n\r\n            if (!isGroup && remoteJidAlt) {\r\n                senderJid = remoteJidAlt;\r\n            }\r\n\r\n            if (!remoteJid || !senderJid) continue;\r\n\r\n            // Check Permissions\r\n            if (!canAutoReply(config, fromMe, senderJid)) continue;\r\n\r\n            const content = normalizeMessageContent(msg.message);\r\n            const text = content?.conversation || content?.extendedTextMessage?.text || \"\"; // Caption?\r\n\r\n            if (!text) continue;\r\n\r\n            try {\r\n                // Fetch rules for this session\r\n                const rules = await prisma.autoReply.findMany({\r\n                    where: {\r\n                        session: {\r\n                            sessionId: sessionId\r\n                        }\r\n                    }\r\n                });\r\n\r\n                for (const rule of rules) {\r\n                    let match = false;\r\n                    const keyword = rule.keyword.toLowerCase();\r\n                    const incoming = text.toLowerCase();\r\n\r\n                    switch (rule.matchType) {\r\n                        case 'EXACT':\r\n                            match = incoming === keyword;\r\n                            break;\r\n                        case 'CONTAINS':\r\n                            match = incoming.includes(keyword);\r\n                            break;\r\n                        case 'REGEX':\r\n                            try {\r\n                                const regex = new RegExp(rule.keyword, 'i');\r\n                                match = regex.test(text); // Use original case for regex\r\n                            } catch (e) {\r\n                                console.error(\"Invalid regex in auto-reply\", rule.keyword);\r\n                            }\r\n                            break;\r\n                    }\r\n\r\n                    if (match) {\r\n                        // Check trigger context (GROUP, PRIVATE, or ALL)\r\n                        const isGroup = remoteJid.endsWith('@g.us');\r\n                        const triggerType = (rule as any).triggerType || 'ALL'; // Default to ALL if undefined\r\n\r\n                        if (triggerType === 'GROUP' && !isGroup) continue;\r\n                        if (triggerType === 'PRIVATE' && isGroup) continue;\r\n\r\n                        console.log(`Auto-reply match: ${rule.keyword} -> ${remoteJid}`);\r\n\r\n                        if (rule.isMedia && rule.mediaUrl) {\r\n                            const url = rule.mediaUrl;\r\n                            const isVideo = url.endsWith('.mp4') || url.endsWith('.avi') || url.endsWith('.mov');\r\n                            const isDocument = url.endsWith('.pdf') || url.endsWith('.doc') || url.endsWith('.docx') || url.endsWith('.zip');\r\n\r\n                            if (isVideo) {\r\n                                await sock.sendMessage(remoteJid, {\r\n                                    video: { url },\r\n                                    caption: rule.response\r\n                                }, { quoted: msg });\r\n                            } else if (isDocument) {\r\n                                await sock.sendMessage(remoteJid, {\r\n                                    document: { url },\r\n                                    caption: rule.response,\r\n                                    mimetype: 'application/octet-stream', // Default mimetype\r\n                                    fileName: url.split('/').pop() || 'document'\r\n                                }, { quoted: msg });\r\n                            } else {\r\n                                // Default to Image\r\n                                await sock.sendMessage(remoteJid, {\r\n                                    image: { url },\r\n                                    caption: rule.response\r\n                                }, { quoted: msg });\r\n                            }\r\n                        } else {\r\n                            await sock.sendMessage(remoteJid, { text: rule.response }, { quoted: msg });\r\n                        }\r\n\r\n                        break;\r\n                    }\r\n                }\r\n\r\n            } catch (e) {\r\n                console.error(\"Auto-reply error\", e);\r\n            }\r\n        }\r\n    });\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\modules\\whatsapp\\store\\contacts.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'isLatest' is defined but never used.","line":61,"column":77,"nodeType":"Identifier","messageId":"unusedVar","endLine":61,"endColumn":85},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":81,"column":42,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":81,"endColumn":45,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3435,3438],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3435,3438],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { prisma } from \"@/lib/prisma\";\r\nimport type { WASocket } from \"@whiskeysockets/baileys\";\r\n\r\n/**\r\n * Sync contacts from WhatsApp to database.\r\n * Uses proper Baileys events for syncing and correct Session.id foreign key.\r\n */\r\nexport function bindContactSync(sock: WASocket, sessionId: string) {\r\n    // First, get the database Session ID (cuid)\r\n    let dbSessionId: string | null = null;\r\n    \r\n    // Initialize by fetching the session ID\r\n    (async () => {\r\n        const session = await prisma.session.findUnique({\r\n            where: { sessionId },\r\n            select: { id: true }\r\n        });\r\n        if (session) {\r\n            dbSessionId = session.id;\r\n            console.log(`Contact sync initialized for session ${sessionId} (db: ${dbSessionId})`);\r\n        } else {\r\n            console.error(`Session ${sessionId} not found for contact sync`);\r\n        }\r\n    })();\r\n\r\n    // Handle contacts.update event (fires when contacts are updated)\r\n    sock.ev.on('contacts.update', async (updates) => {\r\n        if (!dbSessionId) {\r\n            const session = await prisma.session.findUnique({ where: { sessionId }, select: { id: true } });\r\n            if (!session) return;\r\n            dbSessionId = session.id;\r\n        }\r\n        \r\n        console.log(`Received ${updates.length} contact updates for session ${sessionId}`);\r\n        for (const update of updates) {\r\n            try {\r\n                if (!update.id) continue;\r\n                \r\n                await prisma.contact.upsert({\r\n                    where: { sessionId_jid: { sessionId: dbSessionId, jid: update.id } },\r\n                    create: {\r\n                        sessionId: dbSessionId,\r\n                        jid: update.id,\r\n                        name: update.name || update.notify,\r\n                        notify: update.notify,\r\n                        profilePic: update.imgUrl\r\n                    },\r\n                    update: {\r\n                        name: update.name || undefined,\r\n                        notify: update.notify || undefined,\r\n                        profilePic: update.imgUrl || undefined\r\n                    }\r\n                });\r\n            } catch (e) {\r\n                console.error(`Failed to sync contact ${update.id}`, e);\r\n            }\r\n        }\r\n    });\r\n\r\n    // Also listen for messaging events to auto-create contacts\r\n    sock.ev.on('messaging-history.set', async ({ chats, contacts, messages, isLatest }) => {\r\n        if (!dbSessionId) {\r\n            const session = await prisma.session.findUnique({ where: { sessionId }, select: { id: true } });\r\n            if (!session) return;\r\n            dbSessionId = session.id;\r\n        }\r\n        \r\n        console.log(`Received messaging history: ${chats.length} chats, ${contacts?.length || 0} contacts, ${messages.length} messages`);\r\n        \r\n        // Sync chats as contacts (for personal chats)\r\n        for (const chat of chats) {\r\n            try {\r\n                if (!chat.id || chat.id.includes('@g.us') || chat.id.includes('@broadcast')) continue;\r\n                \r\n                await prisma.contact.upsert({\r\n                    where: { sessionId_jid: { sessionId: dbSessionId, jid: chat.id } },\r\n                    create: {\r\n                        sessionId: dbSessionId,\r\n                        jid: chat.id,\r\n                        name: chat.name || undefined,\r\n                        notify: (chat as any).notify || undefined\r\n                    },\r\n                    update: {\r\n                        name: chat.name || undefined\r\n                    }\r\n                });\r\n            } catch (e) {\r\n                console.error(`Failed to sync chat contact ${chat.id}`, e);\r\n            }\r\n        }\r\n        \r\n        // Sync explicit contacts\r\n        if (contacts) {\r\n            for (const contact of contacts) {\r\n                try {\r\n                    if (!contact.id) continue;\r\n                    \r\n                    await prisma.contact.upsert({\r\n                        where: { sessionId_jid: { sessionId: dbSessionId, jid: contact.id } },\r\n                        create: {\r\n                            sessionId: dbSessionId,\r\n                            jid: contact.id,\r\n                            name: contact.name || contact.notify,\r\n                            notify: contact.notify\r\n                        },\r\n                        update: {\r\n                            name: contact.name || undefined,\r\n                            notify: contact.notify || undefined\r\n                        }\r\n                    });\r\n                } catch (e) {\r\n                    console.error(`Failed to sync contact ${contact.id}`, e);\r\n                }\r\n            }\r\n        }\r\n        \r\n        console.log(`Synced contacts from messaging history for session ${sessionId}`);\r\n    });\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\modules\\whatsapp\\store\\groups.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'GroupMetadata' is defined but never used.","line":2,"column":25,"nodeType":"Identifier","messageId":"unusedVar","endLine":2,"endColumn":38,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"GroupMetadata"},"fix":{"range":[62,77],"text":""},"desc":"Remove unused variable \"GroupMetadata\"."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":38,"column":58,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":38,"endColumn":61,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1567,1570],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1567,1570],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":39,"column":41,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":39,"endColumn":44,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1613,1616],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1613,1616],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":47,"column":58,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":47,"endColumn":61,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1966,1969],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1966,1969],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":48,"column":41,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":48,"endColumn":44,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2012,2015],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2012,2015],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":4,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { prisma } from \"@/lib/prisma\";\r\nimport type { WASocket, GroupMetadata } from \"@whiskeysockets/baileys\";\r\n\r\nexport async function syncGroups(sock: WASocket, sessionId: string) {\r\n    try {\r\n        // Verify session exists and get the actual database ID\r\n        const session = await prisma.session.findUnique({\r\n            where: { sessionId },\r\n            select: { id: true }\r\n        });\r\n        \r\n        if (!session) {\r\n            console.error(`Session ${sessionId} does not exist, cannot sync groups`);\r\n            return;\r\n        }\r\n\r\n        // Use session.id (cuid) for foreign key, not sessionId string\r\n        const dbSessionId = session.id;\r\n\r\n        const groups = await sock.groupFetchAllParticipating();\r\n        const groupList = Object.values(groups);\r\n\r\n        console.log(`Found ${groupList.length} groups for session ${sessionId}`);\r\n\r\n        for (const g of groupList) {\r\n             try {\r\n                 await prisma.group.upsert({\r\n                     where: { sessionId_jid: { sessionId: dbSessionId, jid: g.id } },\r\n                     create: {\r\n                         sessionId: dbSessionId,\r\n                         jid: g.id,\r\n                         subject: g.subject,\r\n                         description: g.desc,\r\n                         ownerJid: g.owner,\r\n                         creation: g.creation ? new Date(g.creation * 1000) : undefined,\r\n                         restrict: g.restrict,\r\n                         announce: g.announce,\r\n                         participants: g.participants as any,\r\n                         metadata: g as any\r\n                     },\r\n                     update: {\r\n                         subject: g.subject,\r\n                         description: g.desc,\r\n                         ownerJid: g.owner,\r\n                         restrict: g.restrict,\r\n                         announce: g.announce,\r\n                         participants: g.participants as any,\r\n                         metadata: g as any\r\n                     }\r\n                 });\r\n             } catch (e) {\r\n                 console.error(`Failed to sync group ${g.id}`, e);\r\n             }\r\n        }\r\n        console.log(`Synced ${groupList.length} groups for session ${sessionId}`);\r\n    } catch (e) {\r\n        console.error(\"Failed to sync groups\", e);\r\n    }\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\modules\\whatsapp\\store\\index.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'Contact' is defined but never used.","line":2,"column":36,"nodeType":"Identifier","messageId":"unusedVar","endLine":2,"endColumn":43,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"Contact"},"fix":{"range":[73,82],"text":""},"desc":"Remove unused variable \"Contact\"."}]},{"ruleId":"@typescript-eslint/ban-ts-comment","severity":2,"message":"Use \"@ts-expect-error\" instead of \"@ts-ignore\", as \"@ts-ignore\" will do nothing if the following line is error-free.","line":122,"column":25,"nodeType":"Line","messageId":"tsIgnoreInsteadOfExpectError","endLine":122,"endColumn":38,"suggestions":[{"messageId":"replaceTsIgnoreWithTsExpectError","fix":{"range":[5260,5273],"text":"// @ts-expect-error"},"desc":"Replace \"@ts-ignore\" with \"@ts-expect-error\"."}]},{"ruleId":"@typescript-eslint/ban-ts-comment","severity":2,"message":"Use \"@ts-expect-error\" instead of \"@ts-ignore\", as \"@ts-ignore\" will do nothing if the following line is error-free.","line":126,"column":25,"nodeType":"Line","messageId":"tsIgnoreInsteadOfExpectError","endLine":126,"endColumn":38,"suggestions":[{"messageId":"replaceTsIgnoreWithTsExpectError","fix":{"range":[5461,5474],"text":"// @ts-expect-error"},"desc":"Replace \"@ts-ignore\" with \"@ts-expect-error\"."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":129,"column":36,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":129,"endColumn":39,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[5626,5629],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[5626,5629],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/ban-ts-comment","severity":2,"message":"Use \"@ts-expect-error\" instead of \"@ts-ignore\", as \"@ts-ignore\" will do nothing if the following line is error-free.","line":132,"column":25,"nodeType":"Line","messageId":"tsIgnoreInsteadOfExpectError","endLine":132,"endColumn":38,"suggestions":[{"messageId":"replaceTsIgnoreWithTsExpectError","fix":{"range":[5710,5723],"text":"// @ts-expect-error"},"desc":"Replace \"@ts-ignore\" with \"@ts-expect-error\"."}]},{"ruleId":"@typescript-eslint/ban-ts-comment","severity":2,"message":"Use \"@ts-expect-error\" instead of \"@ts-ignore\", as \"@ts-ignore\" will do nothing if the following line is error-free.","line":136,"column":25,"nodeType":"Line","messageId":"tsIgnoreInsteadOfExpectError","endLine":136,"endColumn":38,"suggestions":[{"messageId":"replaceTsIgnoreWithTsExpectError","fix":{"range":[5907,5920],"text":"// @ts-expect-error"},"desc":"Replace \"@ts-ignore\" with \"@ts-expect-error\"."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":139,"column":36,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":139,"endColumn":39,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[6085,6088],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[6085,6088],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":172,"column":47,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":172,"endColumn":50,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[7238,7241],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[7238,7241],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":299,"column":34,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":299,"endColumn":37,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[12271,12274],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[12271,12274],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":309,"column":29,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":309,"endColumn":32,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[12622,12625],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[12622,12625],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/ban-ts-comment","severity":2,"message":"Use \"@ts-expect-error\" instead of \"@ts-ignore\", as \"@ts-ignore\" will do nothing if the following line is error-free.","line":327,"column":17,"nodeType":"Line","messageId":"tsIgnoreInsteadOfExpectError","endLine":327,"endColumn":30,"suggestions":[{"messageId":"replaceTsIgnoreWithTsExpectError","fix":{"range":[13298,13311],"text":"// @ts-expect-error"},"desc":"Replace \"@ts-ignore\" with \"@ts-expect-error\"."}]},{"ruleId":"@typescript-eslint/ban-ts-comment","severity":2,"message":"Use \"@ts-expect-error\" instead of \"@ts-ignore\", as \"@ts-ignore\" will do nothing if the following line is error-free.","line":334,"column":17,"nodeType":"Line","messageId":"tsIgnoreInsteadOfExpectError","endLine":334,"endColumn":30,"suggestions":[{"messageId":"replaceTsIgnoreWithTsExpectError","fix":{"range":[13630,13643],"text":"// @ts-expect-error"},"desc":"Replace \"@ts-ignore\" with \"@ts-expect-error\"."}]}],"suppressedMessages":[],"errorCount":11,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { prisma } from \"@/lib/prisma\";\r\nimport type { WASocket, WAMessage, Contact } from \"@whiskeysockets/baileys\";\r\nimport { normalizeMessageContent } from \"@whiskeysockets/baileys\";\r\nimport { onMessageReceived, onMessageSent, dispatchWebhook, downloadAndSaveMedia } from \"@/lib/webhook\";\r\nimport { handleBotCommand, setSessionStartTime } from \"../bot/command-handler\";\r\n\r\nimport { Server } from \"socket.io\";\r\n\r\nexport const bindSessionStore = (sock: WASocket, sessionId: string, io: Server | null) => {\r\n    // Set start time for uptime command\r\n    setSessionStartTime(sessionId);\r\n\r\n    // First, get the database Session ID (cuid)\r\n    let dbSessionId: string | null = null;\r\n    \r\n    // Initialize by fetching the session ID\r\n    (async () => {\r\n        const session = await prisma.session.findUnique({\r\n            where: { sessionId },\r\n            select: { id: true }\r\n        });\r\n        if (session) {\r\n            dbSessionId = session.id;\r\n            console.log(`Message store initialized for session ${sessionId} (db: ${dbSessionId})`);\r\n        } else {\r\n            console.error(`Session ${sessionId} not found for message store`);\r\n        }\r\n    })();\r\n    \r\n    // Handle Messages\r\n    sock.ev.on('messages.upsert', async ({ messages, type }) => {\r\n        // Process all message types: notify, append, and history sync\r\n        if (type !== 'notify' && type !== 'append') {\r\n            // For history sync, we still want to save messages\r\n            console.log(`Received ${messages.length} messages of type: ${type}`);\r\n        }\r\n\r\n        // Emit to socket room for real-time frontend updates\r\n        if (type === 'notify' || type === 'append') {\r\n            io?.to(sessionId).emit('message.upsert', { messages, type });\r\n        }\r\n\r\n        // Ensure we have the database session ID\r\n        if (!dbSessionId) {\r\n            const session = await prisma.session.findUnique({ where: { sessionId }, select: { id: true } });\r\n            if (!session) return;\r\n            dbSessionId = session.id;\r\n        }\r\n\r\n        const processedMessages = [];\r\n\r\n        for (const msg of messages) {\r\n            try {\r\n                const savedMessage = await processAndSaveMessage(msg, dbSessionId, sessionId, type === 'notify');\r\n                if (savedMessage) {\r\n                    processedMessages.push(savedMessage);\r\n                }\r\n                \r\n                // Execute Bot Commands (Only for Notify / New Messages)\r\n                if (type === 'notify' && savedMessage) {\r\n                   // Run in background, don't await strictly to not block saving\r\n                   handleBotCommand(sock, sessionId, msg).catch(e => console.error(\"Bot Handler Error\", e));\r\n                }\r\n            } catch (error) {\r\n                console.error(\"Error saving message\", error);\r\n            }\r\n        }\r\n\r\n        // Emit to socket room for real-time frontend updates\r\n        if (processedMessages.length > 0) {\r\n            io?.to(sessionId).emit('message.update', processedMessages);\r\n        }\r\n    });\r\n\r\n    // Handle Message History Sync (when connecting for the first time or syncing)\r\n    sock.ev.on('messaging-history.set', async ({ messages, chats, contacts, isLatest }) => {\r\n        console.log(`History sync: ${messages?.length || 0} messages, ${chats?.length || 0} chats, ${contacts?.length || 0} contacts, latest: ${isLatest}`);\r\n        \r\n        // Ensure we have the database session ID\r\n        if (!dbSessionId) {\r\n            const session = await prisma.session.findUnique({ where: { sessionId }, select: { id: true } });\r\n            if (!session) return;\r\n            dbSessionId = session.id;\r\n        }\r\n\r\n        // Save all historical messages\r\n        if (messages && messages.length > 0) {\r\n            console.log(`Syncing ${messages.length} historical messages...`);\r\n            for (const msg of messages) {\r\n                try {\r\n                    await processAndSaveMessage(msg, dbSessionId, sessionId, false);\r\n                } catch (error) {\r\n                    console.error(\"Error saving historical message\", error);\r\n                }\r\n            }\r\n            console.log(`Finished syncing ${messages.length} historical messages`);\r\n        }\r\n\r\n\r\n        // Note: Contacts and Chats are synced by src/modules/whatsapp/store/contacts.ts\r\n        // We only handle messages here to avoid P2002 Unique Constraint Race Conditions.\r\n        console.log(`Finished syncing ${messages.length} historical messages`);\r\n    });\r\n\r\n    // Handle Contacts Upsert\r\n    sock.ev.on('contacts.upsert', async (contacts) => {\r\n        // Ensure we have the database session ID\r\n        if (!dbSessionId) {\r\n            const session = await prisma.session.findUnique({ where: { sessionId }, select: { id: true } });\r\n            if (!session) return;\r\n            dbSessionId = session.id;\r\n        }\r\n\r\n        for (const c of contacts) {\r\n             try {\r\n                if (!c.id) continue;\r\n                await prisma.contact.upsert({\r\n                    where: { sessionId_jid: { sessionId: dbSessionId, jid: c.id } },\r\n                    create: {\r\n                        sessionId: dbSessionId,\r\n                        jid: c.id,\r\n                        // @ts-ignore\r\n                        lid: c.lid || undefined,\r\n                        name: c.name || c.notify || c.verifiedName,\r\n                        notify: c.notify,\r\n                        // @ts-ignore\r\n                        verifiedName: c.verifiedName,\r\n                        profilePic: c.imgUrl || undefined,\r\n                        data: c as any\r\n                    },\r\n                    update: {\r\n                        // @ts-ignore\r\n                        lid: c.lid || undefined,\r\n                        name: c.name || undefined,\r\n                        notify: c.notify || undefined,\r\n                        // @ts-ignore\r\n                        verifiedName: c.verifiedName || undefined,\r\n                        profilePic: c.imgUrl || undefined,\r\n                        data: c as any\r\n                    }\r\n                });\r\n                \r\n                // Dispatch webhook for contact update\r\n                dispatchWebhook(sessionId, \"contact.update\", { jid: c.id, name: c.name, notify: c.notify });\r\n             } catch (e) {\r\n                 console.error(\"Error saving contact\", e);\r\n             }\r\n        }\r\n    });\r\n\r\n    // Handle Message Status Updates\r\n    sock.ev.on('messages.update', async (updates) => {\r\n        if (!dbSessionId) return;\r\n        \r\n        for (const update of updates) {\r\n            try {\r\n                const keyId = update.key?.id;\r\n                if (!keyId) continue;\r\n\r\n                const statusMap: Record<number, string> = {\r\n                    0: 'PENDING',\r\n                    1: 'SENT',\r\n                    2: 'DELIVERED',\r\n                    3: 'READ',\r\n                    4: 'READ', // Played\r\n                };\r\n\r\n                const status = statusMap[update.update?.status || 0] || 'PENDING';\r\n\r\n                await prisma.message.updateMany({\r\n                    where: { sessionId: dbSessionId, keyId },\r\n                    data: { status: status as any }\r\n                });\r\n\r\n                // Dispatch webhook for message status update\r\n                dispatchWebhook(sessionId, \"message.status\", {\r\n                    keyId,\r\n                    remoteJid: update.key?.remoteJid,\r\n                    status\r\n                });\r\n            } catch (e) {\r\n                console.error(\"Error updating message status\", e);\r\n            }\r\n        }\r\n    });\r\n};\r\n\r\nasync function processAndSaveMessage(msg: WAMessage, dbSessionId: string, sessionId: string, triggerWebhook: boolean) {\r\n    const keyId = msg.key.id;\r\n    const remoteJid = msg.key.remoteJid;\r\n    const fromMe = msg.key.fromMe;\r\n    const pushName = msg.pushName;\r\n    const timestamp = msg.messageTimestamp \r\n        ? new Date((typeof msg.messageTimestamp === 'number' ? msg.messageTimestamp : Number(msg.messageTimestamp)) * 1000)\r\n        : new Date();\r\n    \r\n    // Filter out Protocol & Empty Messages\r\n    if (!msg.message) return false;\r\n    if (!keyId || !remoteJid) return false;\r\n    \r\n    // Ignore specific technical message types\r\n    const messageKeys = Object.keys(msg.message);\r\n    const ignoredTypes = [\r\n        'protocolMessage', \r\n        'senderKeyDistributionMessage', \r\n        'reactionMessage', // Optional: User might want reactions, but usually \"kosong\" means junk\r\n        'keepInChatMessage' \r\n    ];\r\n    \r\n    // If message only contains ignored types, skip\r\n    if (messageKeys.every(k => ignoredTypes.includes(k))) {\r\n        console.log(`Skipping technical message: ${keyId} (${messageKeys.join(', ')})`);\r\n        return null;\r\n    }\r\n\r\n    // Check if message already exists to avoid duplicates\r\n    // Baileys 'notify' event can sometimes trigger multiple times or for history\r\n    // Baileys 'notify' event can sometimes trigger multiple times or for history\r\n    const existingMessage = await prisma.message.findUnique({\r\n        where: { sessionId_keyId: { sessionId: dbSessionId, keyId: keyId! } },\r\n        select: { id: true, status: true }\r\n    });\r\n\r\n    if (existingMessage) {\r\n        // Message exists! Update status if changed, but DO NOT re-trigger webhooks/bot\r\n        if (fromMe && existingMessage.status !== 'SENT') {\r\n             await prisma.message.update({\r\n                where: { id: existingMessage.id },\r\n                data: { status: 'SENT' }\r\n            });\r\n        }\r\n        // Return null to indicate \"Not New\"\r\n        return null;\r\n    }\r\n\r\n    // Debug fromMe issue (Keep this for a while)\r\n    if (fromMe === undefined || fromMe === null) {\r\n        console.log(`[DEBUG] Message ${keyId} has fromMe=${fromMe}. Key:`, JSON.stringify(msg.key));\r\n    }\r\n\r\n    const messageContent = normalizeMessageContent(msg.message);\r\n    let text = \"\";\r\n    let messageType = \"TEXT\";\r\n\r\n    // Extract content based on message type\r\n    if (messageContent?.conversation) {\r\n        text = messageContent.conversation;\r\n    } else if (messageContent?.extendedTextMessage?.text) {\r\n        text = messageContent.extendedTextMessage.text;\r\n    } else if (messageContent?.imageMessage) {\r\n        messageType = \"IMAGE\";\r\n        text = messageContent.imageMessage.caption || \"\";\r\n    } else if (messageContent?.videoMessage) {\r\n        messageType = \"VIDEO\";\r\n        text = messageContent.videoMessage.caption || \"\";\r\n    } else if (messageContent?.audioMessage) {\r\n        messageType = \"AUDIO\";\r\n    } else if (messageContent?.documentMessage) {\r\n        messageType = \"DOCUMENT\";\r\n        text = messageContent.documentMessage.fileName || \"\";\r\n    } else if (messageContent?.stickerMessage) {\r\n        messageType = \"STICKER\";\r\n    } else if (messageContent?.locationMessage) {\r\n        messageType = \"LOCATION\";\r\n        text = `${messageContent.locationMessage.degreesLatitude},${messageContent.locationMessage.degreesLongitude}`;\r\n    } else if (messageContent?.contactMessage) {\r\n        messageType = \"CONTACT\";\r\n        text = messageContent.contactMessage.displayName || \"\";\r\n    }\r\n\r\n    // Determine effective participant for groups\r\n    // Determine effective participant for groups with standard logic\r\n    const isGroup = remoteJid.endsWith(\"@g.us\");\r\n    const remoteJidAlt = msg.key.remoteJidAlt; // LID/Phone JID handling\r\n    let senderJid = fromMe ? undefined : (isGroup ? (msg.key.participant || msg.participant) : remoteJid);\r\n    \r\n    // Prefer remoteJidAlt for DMs if available (matches webhook logic)\r\n    if (!fromMe && !isGroup && remoteJidAlt) {\r\n        senderJid = remoteJidAlt;\r\n    }\r\n\r\n\r\n    // Download Media First (to save URL to DB)\r\n    let fileUrl: string | null = null;\r\n    try {\r\n        fileUrl = await downloadAndSaveMedia(msg, sessionId);\r\n    } catch (e) {\r\n        console.error(\"Error downloading media in store\", e);\r\n    }\r\n\r\n    const newMessage = await prisma.message.create({\r\n        data: {\r\n            sessionId: dbSessionId,\r\n            remoteJid,\r\n            senderJid,\r\n            fromMe: fromMe || false,\r\n            keyId,\r\n            pushName,\r\n            type: messageType as any,\r\n            content: text,\r\n            mediaUrl: fileUrl, // Save Media URL\r\n            status: fromMe ? \"SENT\" : \"PENDING\",\r\n            timestamp\r\n        }\r\n    });\r\n\r\n    // Ensure contact exists (Upsert Contact)\r\n    if (remoteJid && !remoteJid.includes('@g.us') && !remoteJid.includes('status@broadcast')) {\r\n         const contactData: any = {\r\n             sessionId: dbSessionId,\r\n             jid: remoteJid\r\n         };\r\n\r\n         // Only update name/notify if message is FROM the contact (not from me)\r\n         if (!fromMe) {\r\n             if (pushName) contactData.notify = pushName;\r\n             if (pushName) contactData.name = pushName;\r\n         }\r\n\r\n         await prisma.contact.upsert({\r\n            where: { sessionId_jid: { sessionId: dbSessionId, jid: remoteJid } },\r\n            create: {\r\n                sessionId: dbSessionId,\r\n                jid: remoteJid,\r\n                notify: !fromMe ? pushName : undefined,\r\n                name: !fromMe ? pushName : undefined,\r\n                // @ts-ignore\r\n                remoteJidAlt: remoteJidAlt || undefined\r\n            },\r\n            update: !fromMe ? {\r\n                notify: pushName,\r\n                // Only update name if it was null? Or always? Let's just update notify usually.\r\n                // But Baileys often sends name in pushName.\r\n                // @ts-ignore\r\n                remoteJidAlt: remoteJidAlt || undefined // Update Alt JID if we see it\r\n            } : {}\r\n        });\r\n    }\r\n\r\n    // Trigger webhook for new messages only (not history sync)\r\n    // AND filter duplicates is implicitly done because we return 'false' above if existing\r\n    if (triggerWebhook) {\r\n        if (fromMe) {\r\n            onMessageSent(sessionId, msg, fileUrl).catch(e => console.error(\"Error in onMessageSent\", e));\r\n        } else {\r\n            // Pass the fileUrl we just downloaded\r\n            onMessageReceived(sessionId, msg, fileUrl).catch(e => console.error(\"Error in onMessageReceived\", e));\r\n        }\r\n    }\r\n\r\n    return newMessage; // Is New Message = True (Return Object)\r\n}\r\n// Placeholder - verified that I need to find the logic first\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\modules\\whatsapp\\store\\ppguard.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'sessionId' is defined but never used.","line":3,"column":51,"nodeType":"Identifier","messageId":"unusedVar","endLine":3,"endColumn":60}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import type { WASocket } from \"@whiskeysockets/baileys\";\r\n\r\nexport async function bindPpGuard(sock: WASocket, sessionId: string) {\r\n    sock.ev.on('contacts.update', async (updates) => {\r\n        for (const update of updates) {\r\n            if (update.imgUrl) {\r\n                console.log(`Contact ${update.id} changed profile pic to ${update.imgUrl}`);\r\n                // Verify logic: Fetch old imgUrl from DB and compare?\r\n                // For now, simpler: Just notify self if it's a specific target?\r\n                // Or just log it.\r\n                // To properly implement Guard, we need to store 'lastProfilePic' in Contact table.\r\n                \r\n                // For \"Fun\" feature, let's just send a message to self\r\n                // const me = sock.user?.id;\r\n                // if (me) {\r\n                //    await sock.sendMessage(me, { text: `Contact ${update.id} changed PP!` });\r\n                // }\r\n            }\r\n        }\r\n    });\r\n}\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\server\\index.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":39,"column":14,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":39,"endColumn":17,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1135,1138],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1135,1138],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { createServer } from \"http\";\r\nimport { parse } from \"url\";\r\nimport next from \"next\";\r\nimport { Server } from \"socket.io\";\r\nimport { setupSocket } from \"./socket\";\r\nimport { waManager } from \"../modules/whatsapp/manager\";\r\n\r\nconst dev = process.env.NODE_ENV !== \"production\";\r\nconst hostname = process.env.HOSTNAME || \"localhost\";\r\nconst port = parseInt(process.env.PORT || \"3030\", 10);\r\n\r\nconst app = next({ dev, hostname, port });\r\nconst handle = app.getRequestHandler();\r\n\r\napp.prepare().then(() => {\r\n  const server = createServer(async (req, res) => {\r\n    try {\r\n      if (!req.url) return;\r\n      const parsedUrl = parse(req.url, true);\r\n      await handle(req, res, parsedUrl);\r\n    } catch (err) {\r\n      console.error(\"Error occurred handling\", req.url, err);\r\n      res.statusCode = 500;\r\n      res.end(\"internal server error\");\r\n    }\r\n  });\r\n\r\n  const io = new Server(server, {\r\n    path: \"/api/socket/io\",\r\n    addTrailingSlash: false,\r\n    cors: {\r\n        origin: \"*\",\r\n        methods: [\"GET\", \"POST\"]\r\n    }\r\n  });\r\n\r\n  setupSocket(io);\r\n  // Optional: Global instance for Baileys to emit events\r\n  (global as any).io = io;\r\n\r\n  // Initialize WhatsApp Manager\r\n  waManager.setup(io);\r\n  waManager.loadSessions();\r\n\r\n  // Start Scheduler\r\n  import(\"../modules/whatsapp/scheduler\").then(m => m.startScheduler());\r\n\r\n\r\n  server.listen(port, () => {\r\n    console.log(`> Ready on http://${hostname}:${port}`);\r\n  });\r\n});\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\server\\socket.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\opc\\Downloads\\New folder\\WA-AKG\\src\\types\\next-auth.d.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'NextAuth' is defined but never used.","line":1,"column":8,"nodeType":"Identifier","messageId":"unusedVar","endLine":1,"endColumn":16,"suggestions":[{"messageId":"removeUnusedVar","data":{"varName":"NextAuth"},"fix":{"range":[7,16],"text":""},"desc":"Remove unused variable \"NextAuth\"."}]}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import NextAuth, { DefaultSession } from \"next-auth\"\r\n\r\ndeclare module \"next-auth\" {\r\n  interface Session {\r\n    user: {\r\n      role: string;\r\n      id: string;\r\n    } & DefaultSession[\"user\"]\r\n  }\r\n\r\n  interface User {\r\n      role: string;\r\n      id: string;\r\n  }\r\n}\r\n\r\ndeclare module \"next-auth/jwt\" {\r\n    interface JWT {\r\n        role: string;\r\n        id: string;\r\n    }\r\n}\r\n","usedDeprecatedRules":[]}]
