noapi / app.js
smgc's picture
Update app.js
4364ea6 verified
raw
history blame
No virus
11.7 kB
const express = require('express');
const fetch = require('node-fetch');
const crypto = require('crypto');
const app = express();
const port = 8000;
const NOTDIAMOND_URL = 'https://chat.notdiamond.ai/mini-chat';
const NOTDIAMOND_HEADERS = {
'Content-Type': 'application/json',
'next-action': '8189eb37107121e024940f588629a394a594e6a4'
};
const SUPABASE_URL = 'https://spuckhogycrxcbomznwo.supabase.co';
const SUPABASE_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InNwdWNraG9neWNyeGNib216bndvIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MDcyNDYwMzksImV4cCI6MjAyMjgyMjAzOX0.tvlGT7NZY8bijMjNIu1WhAtPnSKuDeYhtveo4DRt6xg';
const DEFAULT_MODEL = 'gpt-4o';
const MODEL_MAPPING = {
"gpt-4o-mini": {
"provider": "openai",
"mapping": "gpt-4o-mini"
},
"gpt-4o": {
"provider": "openai",
"mapping": "gpt-4o"
},
"gpt-4-turbo": {
"provider": "openai",
"mapping": "gpt-4-turbo-2024-04-09"
},
"gemini-1.5-pro-latest": {
"provider": "google",
"mapping": "gemini-1.5-pro-latest"
},
"gemini-1.5-flash-latest": {
"provider": "google",
"mapping": "gemini-1.5-flash-latest"
},
"llama-3.1-70b-instruct": {
"provider": "meta",
"mapping": "Meta-Llama-3.1-70B-Instruct-Turbo"
},
"llama-3.1-405b-instruct": {
"provider": "meta",
"mapping": "Meta-Llama-3.1-405B-Instruct-Turbo"
},
"claude-3-5-sonnet-20240620": {
"provider": "anthropic",
"mapping": "claude-3-5-sonnet-20240620"
},
"claude-3-haiku-20240307": {
"provider": "anthropic",
"mapping": "claude-3-haiku-20240307"
},
"perplexity": {
"provider": "perplexity",
"mapping": "llama-3.1-sonar-large-128k-online"
},
"mistral-large-2407": {
"provider": "mistral",
"mapping": "mistral.mistral-large-2407-v1:0"
}
};
const authCache = new Map();
async function getAuthCookie(req) {
const authHeader = req.headers['authorization'];
if (authHeader && authHeader.startsWith('Bearer ')) {
const [email, password] = authHeader.slice(7).split('|');
if (!email || !password) {
throw new Error('Invalid authentication format');
}
const cacheKey = `${email}:${password}`;
const cachedAuth = authCache.get(cacheKey);
if (cachedAuth && cachedAuth.expiresAt > Date.now()) {
return {
cookie: cachedAuth.cookie,
cacheHit: true,
expiresAt: cachedAuth.expiresAt
};
}
const response = await fetch(`${SUPABASE_URL}/auth/v1/token?grant_type=password`, {
method: 'POST',
headers: {
'accept': '*/*',
'accept-language': 'zh-CN,zh;q=0.9',
'apikey': SUPABASE_KEY,
'authorization': `Bearer ${SUPABASE_KEY}`,
'content-type': 'application/json;charset=UTF-8',
'origin': 'https://chat.notdiamond.ai',
'referer': 'https://chat.notdiamond.ai/',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36',
'x-client-info': 'supabase-ssr/0.4.0',
'x-supabase-api-version': '2024-01-01'
},
body: JSON.stringify({
email: email,
password: password,
gotrue_meta_security: {}
})
});
if (!response.ok) {
throw new Error('Authentication failed');
}
const responseData = await response.json();
const baseCookie = Buffer.from(JSON.stringify(responseData)).toString('base64');
const cookie = `sb-spuckhogycrxcbomznwo-auth-token=base64-${baseCookie}`;
const expiresAt = Date.now() + (responseData.expires_in * 1000);
authCache.set(cacheKey, {
cookie: cookie,
expiresAt: expiresAt
});
return {
cookie: cookie,
cacheHit: false,
expiresAt: expiresAt
};
}
return null;
}
function createOpenAIChunk(content, model, finishReason = null) {
return {
id: `chatcmpl-${crypto.randomUUID()}`,
object: "chat.completion.chunk",
created: Math.floor(Date.now() / 1000),
model: model,
system_fingerprint: "fp_4e2b2da518",
choices: [
{
index: 0,
delta: content ? { content: content } : {},
logprobs: null,
finish_reason: finishReason
}
],
usage: null
};
}
async function* streamNotdiamondResponse(response, model) {
let buffer = "";
let lastContent = "";
function processDollars(str) {
return str.replace(/\${2,}/, match => match.slice(1));
}
for await (const chunk of response.body) {
buffer += chunk.toString();
let lines = buffer.split('\n');
buffer = lines.pop() || "";
for (const line of lines) {
if (line.trim() === '') continue;
try {
const jsonMatch = line.match(/\{.*\}/);
if (jsonMatch) {
const data = JSON.parse(jsonMatch[0]);
let content = '';
if (data.output?.curr !== undefined) {
content = processDollars(data.output.curr);
lastContent = content;
} else if (data.curr !== undefined) {
content = processDollars(data.curr);
lastContent = content;
} else if (data.diff !== undefined && Array.isArray(data.diff) && data.diff.length > 1) {
const newContent = processDollars(data.diff[1]);
content = lastContent + newContent;
lastContent = content;
} else if (data.diff !== undefined && Array.isArray(data.diff) && data.diff.length === 1) {
content = lastContent; // If diff is empty, use the last content
}
if (content) {
yield createOpenAIChunk(content, model);
}
}
} catch (error) {
console.error('Error processing line:', error, 'Raw line:', line);
}
}
}
if (buffer.trim()) {
try {
const jsonMatch = buffer.match(/\{.*\}/);
if (jsonMatch) {
const data = JSON.parse(jsonMatch[0]);
let content = '';
if (data.output?.curr !== undefined) {
content = processDollars(data.output.curr);
} else if (data.curr !== undefined) {
content = processDollars(data.curr);
} else if (data.diff !== undefined && Array.isArray(data.diff) && data.diff.length > 1) {
const newContent = processDollars(data.diff[1]);
content = lastContent + newContent;
} else if (data.diff !== undefined && Array.isArray(data.diff) && data.diff.length === 1) {
content = lastContent;
}
if (content) {
yield createOpenAIChunk(content, model);
}
}
} catch (error) {
console.error('Error processing final buffer:', error);
}
}
yield createOpenAIChunk('', model, 'stop');
}
app.use(express.json());
app.get('/', (req, res) => {
res.json({
service: "AI Chat Completion Proxy",
usage: {
endpoint: "/ai/v1/chat/completions",
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_AUTH_KEY"
},
body: {
model: "One of: " + Object.keys(MODEL_MAPPING).join(", "),
messages: [
{ role: "system", content: "You are a helpful assistant." },
{ role: "user", content: "Hello, who are you?" }
],
stream: false,
temperature: 0.7
}
},
availableModels: Object.keys(MODEL_MAPPING),
note: "Replace YOUR_AUTH_KEY with your actual authentication key."
});
});
app.get('/ai/v1/models', async (req, res) => {
try {
const authCookie = await getAuthCookie(req);
if (!authCookie) {
return res.status(401).json({ error: 'Unauthorized' });
}
res.json({
object: "list",
data: Object.entries(MODEL_MAPPING).map(([id, info]) => ({
id: id,
object: "model",
created: Math.floor(Date.now() / 1000),
owned_by: info.provider,
permission: [],
root: id,
parent: null,
}))
});
console.log(`${new Date().toISOString()} - ${req.ip || req.connection.remoteAddress} - GET /ai/v1/models - 200`);
} catch (error) {
res.status(401).json({ error: 'Authentication failed', details: error.message });
}
});
app.post('/ai/v1/chat/completions', async (req, res) => {
const startTime = new Date();
const clientIP = req.ip || req.connection.remoteAddress;
let userModel = req.body.model || DEFAULT_MODEL;
let status = 200;
let cookieCacheHit = false;
let cookieExpiresAt = null;
try {
const authResult = await getAuthCookie(req);
if (!authResult) {
status = 401;
throw new Error('Unauthorized');
}
cookieCacheHit = authResult.cacheHit;
cookieExpiresAt = new Date(authResult.expiresAt).toISOString();
let requestData = req.body;
let messages = requestData.messages;
let modelInfo = MODEL_MAPPING[userModel];
if (!modelInfo) {
status = 400;
throw new Error('Invalid model specified');
}
let model = modelInfo.mapping;
const stream = requestData.stream || false;
if (!messages || !Array.isArray(messages)) {
status = 400;
throw new Error('Invalid request body: messages should be an array of message objects');
}
const payload = {
messages: messages,
model: model,
stream: stream,
frequency_penalty: requestData.frequency_penalty || 0,
presence_penalty: requestData.presence_penalty || 0,
temperature: requestData.temperature || 0.6,
top_p: requestData.top_p || 1
};
const headers = {
'Content-Type': 'application/json',
'next-action': '4e63dabc37fef18cae74cbfd41d1bace49acf47e',
'Cookie': authResult.cookie
};
const response = await fetch(NOTDIAMOND_URL, {
method: 'POST',
headers: headers,
body: JSON.stringify([payload])
});
const generator = streamNotdiamondResponse(response, userModel);
if (stream) {
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
});
for await (const chunk of generator) {
res.write(`data: ${JSON.stringify(chunk)}\n\n`);
}
res.write("data: [DONE]\n\n");
res.end();
} else {
let fullContent = "";
for await (const chunk of generator) {
if (chunk.choices[0].delta.content) {
fullContent += chunk.choices[0].delta.content;
}
}
res.json({
id: `chatcmpl-${crypto.randomUUID()}`,
object: "chat.completion",
created: Math.floor(Date.now() / 1000),
model: userModel,
system_fingerprint: "fp_4e2b2da518",
choices: [
{
index: 0,
message: {
role: "assistant",
content: fullContent
},
finish_reason: "stop"
}
],
usage: {
prompt_tokens: Math.floor(fullContent.length / 4),
completion_tokens: Math.floor(fullContent.length / 4),
total_tokens: Math.floor(fullContent.length / 2)
}
});
}
} catch (error) {
status = status === 200 ? 500 : status;
res.status(status).json({
error: 'Error',
details: error.message
});
} finally {
const endTime = new Date();
const duration = endTime - startTime;
console.log(`${endTime.toISOString()} - ${clientIP} - ${userModel} - ${status} - ${duration}ms - CacheHit:${cookieCacheHit} - ExpiresAt:${cookieExpiresAt}`);
}
});
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});