mirror of
https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web.git
synced 2025-10-08 19:16:37 +08:00
Compare commits
No commits in common. "8af4d7a6d9416e56bd2de8527f82a93e1049e55d" and "b07760fbc9f86905d7d02b5c26dd2c5d24412497" have entirely different histories.
8af4d7a6d9
...
b07760fbc9
@ -1,53 +1,21 @@
|
||||
"use client";
|
||||
import { useEffect } from "react";
|
||||
import { useSyncStore } from "./store/sync";
|
||||
import { showToast } from "./components/ui-lib";
|
||||
import { AUTHEN_PAGE } from "./constant";
|
||||
|
||||
export default function SyncOnFirstLoad() {
|
||||
const syncStore = useSyncStore();
|
||||
|
||||
useEffect(() => {
|
||||
// Parse cookies using the cookie library
|
||||
// const cookies = cookie.parse(document.cookie || "");
|
||||
// const authToken = cookies["sb-zzgkylsbdgwoohcbompi-auth-token"] || null;
|
||||
// if (syncStore.lastSyncTime === 0) {
|
||||
// // If this is the first time syncing, call sync()
|
||||
// alert("[SyncOnFirstLoad] Dong bo hoa du lieu lan dau tien");
|
||||
|
||||
console.log("[Auth Check] Checking user authentication status");
|
||||
console.log("[SyncOnFirstLoad] Dong bo hoa du lieu lan dau tien");
|
||||
|
||||
fetch("/api/auth/check")
|
||||
.then((res) => {
|
||||
if (res.status === 401) {
|
||||
console.log("[Auth Check] User is not authenticated");
|
||||
// Handle unauthenticated user - redirect or show login modal
|
||||
console.log("Thoi gian dong bo lan cuoi: ", syncStore.lastSyncTime);
|
||||
|
||||
showToast("Please login first");
|
||||
|
||||
setTimeout(() => {
|
||||
window.location.href = AUTHEN_PAGE;
|
||||
}, 500);
|
||||
return;
|
||||
}
|
||||
|
||||
return res.json();
|
||||
})
|
||||
.then((data) => {
|
||||
if (data) {
|
||||
console.log("[Auth Check] User is authenticated:", data.user);
|
||||
|
||||
// Assuming data.user contains the user information(user email)
|
||||
const email = data.user.email || "";
|
||||
|
||||
// Only update upstash.username, keep other params
|
||||
syncStore.update((config) => (config.upstash.username = email));
|
||||
|
||||
// You can now use the user data as needed
|
||||
// syncStore.sync();
|
||||
// console.log("[Sync] User data synced successfully");
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error("[Auth Check] Error checking authentication:", e);
|
||||
// Handle error appropriately
|
||||
});
|
||||
syncStore.sync();
|
||||
// }
|
||||
}, []);
|
||||
|
||||
return null;
|
||||
|
@ -1,21 +0,0 @@
|
||||
// /app/api/auth/check/route.ts
|
||||
import { NextRequest } from "next/server";
|
||||
import { checkAuth } from "../../supabase";
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
const user = await checkAuth(req);
|
||||
|
||||
console.log("[Auth] user ", user);
|
||||
|
||||
if (!user) {
|
||||
return new Response(JSON.stringify({ authenticated: false }), {
|
||||
status: 401,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
}
|
||||
|
||||
return new Response(JSON.stringify({ authenticated: true, user }), {
|
||||
status: 200,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
}
|
@ -30,17 +30,14 @@ export async function requestOpenai(req: NextRequest) {
|
||||
authHeaderName = "api-key";
|
||||
} else {
|
||||
// Nếu là OpenAI thường, giữ nguyên header Authorization
|
||||
|
||||
authValue = req.headers.get("Authorization") ?? "";
|
||||
authHeaderName = "Authorization";
|
||||
|
||||
console.log("[Auth] ", authValue);
|
||||
}
|
||||
|
||||
// Xử lý lại đường dẫn endpoint cho phù hợp với OpenAI/Azure
|
||||
let path = `${req.nextUrl.pathname}`.replaceAll("/api/openai/", "");
|
||||
|
||||
// console.log("[Proxy] mac dinh ", path);
|
||||
console.log("[Proxy] mac dinh ", path);
|
||||
|
||||
// Lấy baseUrl từ config, ưu tiên Azure nếu là request Azure
|
||||
let baseUrl =
|
||||
|
@ -1,45 +0,0 @@
|
||||
import { createClient } from "@supabase/supabase-js";
|
||||
import { NextRequest } from "next/server";
|
||||
|
||||
const SUPABASE_URL = process.env.SUPABASE_URL!;
|
||||
const SUPABASE_ANON_KEY = process.env.SUPABASE_ANON_KEY!;
|
||||
|
||||
export async function checkAuth(req: NextRequest) {
|
||||
// Use NextRequest.cookies API
|
||||
const authToken = req.cookies.get("sb-zzgkylsbdgwoohcbompi-auth-token")
|
||||
?.value;
|
||||
|
||||
// console.log("[Supabase] authToken", authToken);
|
||||
|
||||
if (!authToken) {
|
||||
// Không tìm thấy token xác thực
|
||||
console.log("[Supabase] No auth token found");
|
||||
return null;
|
||||
}
|
||||
|
||||
const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY, {
|
||||
global: {
|
||||
headers: {
|
||||
Authorization: `Bearer ${authToken}`,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
const { data, error } = await supabase.auth.getUser();
|
||||
|
||||
if (error || !data?.user) {
|
||||
// Lỗi khi lấy thông tin người dùng
|
||||
console.error("[Supabase] Error getting user:", error);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Đã xác thực thành công, trả về thông tin người dùng
|
||||
console.log("[Supabase] Authenticated user:", data.user);
|
||||
return data.user;
|
||||
} catch (err) {
|
||||
// Lỗi khi lấy dữ liệu người dùng
|
||||
console.error("[Supabase] Error fetching user data:", err);
|
||||
return null;
|
||||
}
|
||||
}
|
@ -5,4 +5,3 @@ export const UPSTASH_ENDPOINT = "https://fine-baboon-52580.upstash.io";
|
||||
export const UPSTASH_APIKEY =
|
||||
"Ac1kAAIjcDE2YjM4YmY3OGI4YzA0MTU2YjZhNmQyNzc5Yzc3NzEwYnAxMA";
|
||||
export const STORAGE_KEY = "chebichat-backup";
|
||||
export const AUTHEN_PAGE = "https://chinese.giahungtech.com.vn";
|
||||
|
@ -132,16 +132,10 @@ interface ChatProvider {
|
||||
usage: () => void;
|
||||
}
|
||||
|
||||
// Khởi tạo API client dựa trên nhà cung cấp mô hình được chỉ định
|
||||
export class ClientApi {
|
||||
public llm: LLMApi;
|
||||
|
||||
// Hàm khởi tạo nhận vào một provider (nhà cung cấp mô hình AI)
|
||||
// Mặc định là ModelProvider.GPT nếu không được chỉ định
|
||||
constructor(provider: ModelProvider = ModelProvider.GPT) {
|
||||
console.log("[ClientApi] provider ", provider);
|
||||
|
||||
// Sử dụng switch để khởi tạo instance tương ứng với provider được chọn
|
||||
switch (provider) {
|
||||
case ModelProvider.GeminiPro:
|
||||
this.llm = new GeminiProApi();
|
||||
@ -184,18 +178,13 @@ export class ClientApi {
|
||||
}
|
||||
}
|
||||
|
||||
// Hàm cấu hình (chưa triển khai chi tiết)
|
||||
config() {}
|
||||
|
||||
// Hàm lấy prompts (chưa triển khai chi tiết)
|
||||
prompts() {}
|
||||
|
||||
// Hàm lấy masks (chưa triển khai chi tiết)
|
||||
masks() {}
|
||||
|
||||
// Hàm chia sẻ cuộc trò chuyện
|
||||
async share(messages: ChatMessage[], avatarUrl: string | null = null) {
|
||||
// Chuẩn bị dữ liệu tin nhắn để chia sẻ
|
||||
const msgs = messages
|
||||
.map((m) => ({
|
||||
from: m.role === "user" ? "human" : "gpt",
|
||||
@ -208,20 +197,14 @@ export class ClientApi {
|
||||
"Share from [NextChat]: https://github.com/Yidadaa/ChatGPT-Next-Web",
|
||||
},
|
||||
]);
|
||||
// Lưu ý: Không nên sửa đổi dòng thông báo cuối cùng này vì nó dùng cho việc làm sạch dữ liệu sau này
|
||||
// 敬告二开开发者们,为了开源大模型的发展,请不要修改上述消息,此消息用于后续数据清洗使用
|
||||
// Please do not modify this message
|
||||
|
||||
console.log("[Share]", messages, msgs);
|
||||
|
||||
// Lấy cấu hình client
|
||||
const clientConfig = getClientConfig();
|
||||
|
||||
// Xác định URL để chia sẻ dựa trên môi trường (app hay web)
|
||||
const proxyUrl = "/sharegpt";
|
||||
const rawUrl = "https://sharegpt.com/api/conversations";
|
||||
const shareUrl = clientConfig?.isApp ? rawUrl : proxyUrl;
|
||||
|
||||
// Gửi yêu cầu POST để chia sẻ cuộc trò chuyện
|
||||
const res = await fetch(shareUrl, {
|
||||
body: JSON.stringify({
|
||||
avatarUrl,
|
||||
@ -233,7 +216,6 @@ export class ClientApi {
|
||||
method: "POST",
|
||||
});
|
||||
|
||||
// Xử lý phản hồi và trả về link chia sẻ
|
||||
const resJson = await res.json();
|
||||
console.log("[Share]", resJson);
|
||||
if (resJson.id) {
|
||||
@ -242,7 +224,6 @@ export class ClientApi {
|
||||
}
|
||||
}
|
||||
|
||||
// Hàm tạo token xác thực Bearer
|
||||
export function getBearerToken(
|
||||
apiKey: string,
|
||||
noBearer: boolean = false,
|
||||
@ -252,21 +233,14 @@ export function getBearerToken(
|
||||
: "";
|
||||
}
|
||||
|
||||
// Hàm kiểm tra chuỗi có hợp lệ không (có độ dài > 0)
|
||||
export function validString(x: string): boolean {
|
||||
return x?.length > 0;
|
||||
}
|
||||
|
||||
// Hàm lấy các header cần thiết cho yêu cầu API
|
||||
export function getHeaders(ignoreHeaders: boolean = false) {
|
||||
// Lấy store để truy cập các trạng thái liên quan đến quyền truy cập và chat
|
||||
const accessStore = useAccessStore.getState();
|
||||
const chatStore = useChatStore.getState();
|
||||
|
||||
// Khởi tạo đối tượng headers rỗng
|
||||
let headers: Record<string, string> = {};
|
||||
|
||||
// Nếu không bỏ qua headers thì thêm các header mặc định
|
||||
if (!ignoreHeaders) {
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
@ -274,15 +248,10 @@ export function getHeaders(ignoreHeaders: boolean = false) {
|
||||
};
|
||||
}
|
||||
|
||||
// Lấy cấu hình client
|
||||
const clientConfig = getClientConfig();
|
||||
|
||||
// Hàm getConfig sẽ xác định nhà cung cấp hiện tại và API key tương ứng
|
||||
function getConfig() {
|
||||
// Lấy cấu hình mô hình từ session hiện tại
|
||||
const modelConfig = chatStore.currentSession().mask.modelConfig;
|
||||
|
||||
// Kiểm tra loại nhà cung cấp đang được sử dụng
|
||||
const isGoogle = modelConfig.providerName === ServiceProvider.Google;
|
||||
const isAzure = modelConfig.providerName === ServiceProvider.Azure;
|
||||
const isAnthropic = modelConfig.providerName === ServiceProvider.Anthropic;
|
||||
@ -296,11 +265,7 @@ export function getHeaders(ignoreHeaders: boolean = false) {
|
||||
const isChatGLM = modelConfig.providerName === ServiceProvider.ChatGLM;
|
||||
const isSiliconFlow =
|
||||
modelConfig.providerName === ServiceProvider.SiliconFlow;
|
||||
|
||||
// Kiểm tra xem có bật kiểm soát truy cập không
|
||||
const isEnabledAccessControl = accessStore.enabledAccessControl();
|
||||
|
||||
// Xác định API key dựa trên nhà cung cấp đang được sử dụng
|
||||
const apiKey = isGoogle
|
||||
? accessStore.googleApiKey
|
||||
: isAzure
|
||||
@ -344,7 +309,6 @@ export function getHeaders(ignoreHeaders: boolean = false) {
|
||||
};
|
||||
}
|
||||
|
||||
// Hàm xác định header nào sẽ được sử dụng để xác thực
|
||||
function getAuthHeader(): string {
|
||||
return isAzure
|
||||
? "api-key"
|
||||
@ -355,7 +319,6 @@ export function getHeaders(ignoreHeaders: boolean = false) {
|
||||
: "Authorization";
|
||||
}
|
||||
|
||||
// Lấy các giá trị đã được xác định trong getConfig
|
||||
const {
|
||||
isGoogle,
|
||||
isAzure,
|
||||
@ -372,24 +335,19 @@ export function getHeaders(ignoreHeaders: boolean = false) {
|
||||
apiKey,
|
||||
isEnabledAccessControl,
|
||||
} = getConfig();
|
||||
|
||||
// Khi sử dụng API của Baidu trong ứng dụng, không đặt header xác thực
|
||||
// when using baidu api in app, not set auth header
|
||||
if (isBaidu && clientConfig?.isApp) return headers;
|
||||
|
||||
// Xác định tên header xác thực
|
||||
const authHeader = getAuthHeader();
|
||||
|
||||
// Tạo token xác thực
|
||||
const bearerToken = getBearerToken(
|
||||
apiKey,
|
||||
isAzure || isAnthropic || isGoogle,
|
||||
);
|
||||
|
||||
// Nếu có bearer token thì thêm vào headers
|
||||
if (bearerToken) {
|
||||
headers[authHeader] = bearerToken;
|
||||
} else if (isEnabledAccessControl && validString(accessStore.accessCode)) {
|
||||
// Nếu có mã truy cập thì sử dụng nó để tạo bearer token
|
||||
headers["Authorization"] = getBearerToken(
|
||||
ACCESS_CODE_PREFIX + accessStore.accessCode,
|
||||
);
|
||||
@ -398,7 +356,6 @@ export function getHeaders(ignoreHeaders: boolean = false) {
|
||||
return headers;
|
||||
}
|
||||
|
||||
// Hàm tạo instance của ClientApi dựa trên nhà cung cấp dịch vụ
|
||||
export function getClientApi(provider: ServiceProvider): ClientApi {
|
||||
switch (provider) {
|
||||
case ServiceProvider.Google:
|
||||
|
@ -1813,7 +1813,7 @@ function _Chat() {
|
||||
const shouldShowClearContextDivider =
|
||||
i === clearContextIndex - 1;
|
||||
|
||||
// console.log(message.role);
|
||||
console.log(message.role);
|
||||
|
||||
return (
|
||||
<Fragment key={message.id}>
|
||||
@ -1868,9 +1868,9 @@ function _Chat() {
|
||||
}}
|
||||
></IconButton>
|
||||
</div>
|
||||
|
||||
{/* Neu la user thi khong hien thi avatar */}
|
||||
{isUser ? null : (
|
||||
{isUser ? (
|
||||
<Avatar avatar={config.avatar} />
|
||||
) : (
|
||||
<>
|
||||
{["system"].includes(message.role) ? (
|
||||
<Avatar avatar="2699-fe0f" />
|
||||
|
@ -5,8 +5,7 @@ require("../polyfill");
|
||||
import { useEffect, useState } from "react";
|
||||
import styles from "./home.module.scss";
|
||||
|
||||
//icon chebichat logo
|
||||
import BotIcon from "../icons/chebichat.svg";
|
||||
import BotIcon from "../icons/bot.svg";
|
||||
import LoadingIcon from "../icons/three-dots.svg";
|
||||
|
||||
import { getCSSVar, useMobileScreen } from "../utils";
|
||||
@ -15,7 +14,7 @@ import dynamic from "next/dynamic";
|
||||
import { Path, SlotID } from "../constant";
|
||||
import { ErrorBoundary } from "./error";
|
||||
|
||||
import { getISOLang } from "../locales";
|
||||
import { getISOLang, getLang } from "../locales";
|
||||
|
||||
import {
|
||||
HashRouter as Router,
|
||||
@ -213,7 +212,7 @@ function Screen() {
|
||||
<div
|
||||
className={clsx(styles.container, {
|
||||
[styles["tight-container"]]: shouldTightBorder,
|
||||
// [styles["rtl-screen"]]: getLang() === "ar", // Removed because "ar" is not a possible return value
|
||||
[styles["rtl-screen"]]: getLang() === "ar",
|
||||
})}
|
||||
>
|
||||
{renderContent()}
|
||||
|
@ -529,8 +529,6 @@ function SyncItems() {
|
||||
setShowSyncConfigModal(true);
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* thuc hien dong bo voi cloud */}
|
||||
{couldSync && (
|
||||
<IconButton
|
||||
icon={<ResetIcon />}
|
||||
|
@ -29,15 +29,13 @@ import {
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import { isIOS, useMobileScreen } from "../utils";
|
||||
import dynamic from "next/dynamic";
|
||||
import { Selector, showConfirm, showToast } from "./ui-lib";
|
||||
import { Selector, showConfirm } from "./ui-lib";
|
||||
import clsx from "clsx";
|
||||
import { isMcpEnabled } from "../mcp/actions";
|
||||
import { useSyncStore } from "../store/sync";
|
||||
|
||||
const DISCOVERY = [
|
||||
// { name: Locale.Plugin.Name, path: Path.Plugins },
|
||||
// { name: "Stable Diffusion", path: Path.Sd },
|
||||
{ name: Locale.UI.Sync, path: "/sync" },
|
||||
{ name: Locale.SearchChat.Page.Title, path: Path.SearchChat },
|
||||
];
|
||||
|
||||
@ -235,8 +233,6 @@ export function SideBar(props: { className?: string }) {
|
||||
const chatStore = useChatStore();
|
||||
const [mcpEnabled, setMcpEnabled] = useState(false);
|
||||
|
||||
const syncStore = useSyncStore();
|
||||
|
||||
useEffect(() => {
|
||||
// 检查 MCP 是否启用
|
||||
const checkMcpStatus = async () => {
|
||||
@ -310,20 +306,9 @@ export function SideBar(props: { className?: string }) {
|
||||
}),
|
||||
]}
|
||||
onClose={() => setshowDiscoverySelector(false)}
|
||||
onSelection={async (s) => {
|
||||
console.log(s[0]);
|
||||
if (s[0] == "/sync") {
|
||||
try {
|
||||
await syncStore.sync();
|
||||
console.log("Dong bo thanh cong ");
|
||||
showToast(Locale.Settings.Sync.Success);
|
||||
} catch (e) {
|
||||
showToast(Locale.Settings.Sync.Fail);
|
||||
console.error("[Sync]", e);
|
||||
}
|
||||
} else {
|
||||
navigate(s[0], { state: { fromHome: true } });
|
||||
}
|
||||
onSelection={(s) => {
|
||||
// Điều hướng đến trang được chọn
|
||||
navigate(s[0], { state: { fromHome: true } });
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
@ -57,12 +57,10 @@ export enum Path {
|
||||
Artifacts = "/artifacts",
|
||||
SearchChat = "/search-chat",
|
||||
McpMarket = "/mcp-market",
|
||||
Sync = "/sync",
|
||||
}
|
||||
|
||||
export enum ApiPath {
|
||||
Cors = "",
|
||||
Supabase = "/api/supabase",
|
||||
Azure = "/api/azure",
|
||||
OpenAI = "/api/alibaba", // Use Alibaba path for OpenAI API
|
||||
Anthropic = "/api/anthropic",
|
||||
|
@ -37,7 +37,7 @@ export default function RootLayout({
|
||||
const serverConfig = getServerSideConfig();
|
||||
|
||||
// Log server configuration for debugging
|
||||
// console.log("Server Configuration:");
|
||||
console.log("Server Configuration:");
|
||||
// console.log(serverConfig);
|
||||
|
||||
return (
|
||||
|
@ -35,10 +35,10 @@ export function compressImage(file: Blob, maxSize: number): Promise<string> {
|
||||
if (dataUrl.length < maxSize) break;
|
||||
|
||||
if (quality > 0.5) {
|
||||
// Ưu tiên giảm chất lượng
|
||||
// Prioritize quality reduction
|
||||
quality -= 0.1;
|
||||
} else {
|
||||
// Sau đó giảm kích thước
|
||||
// Then reduce the size
|
||||
width *= 0.9;
|
||||
height *= 0.9;
|
||||
}
|
||||
|
2
git.sh
2
git.sh
@ -2,7 +2,7 @@
|
||||
# git config --global user.name "quangdn-ght"
|
||||
|
||||
git add .
|
||||
git commit -m "Xu ly dong bo nguoi dung thanh cong"
|
||||
git commit -m "cap nhat giao dien"
|
||||
git push
|
||||
|
||||
# mdZddHXcuzsB0Akk
|
17622
package-lock.json
generated
17622
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -25,27 +25,22 @@
|
||||
"@hello-pangea/dnd": "^16.5.0",
|
||||
"@modelcontextprotocol/sdk": "^1.0.4",
|
||||
"@next/third-parties": "^14.1.0",
|
||||
"@supabase/ssr": "^0.6.1",
|
||||
"@supabase/supabase-js": "^2.50.1",
|
||||
"@svgr/webpack": "^6.5.1",
|
||||
"@vercel/analytics": "^0.1.11",
|
||||
"@vercel/speed-insights": "^1.0.2",
|
||||
"axios": "^1.7.5",
|
||||
"clsx": "^2.1.1",
|
||||
"cookie": "^1.0.2",
|
||||
"emoji-picker-react": "^4.9.2",
|
||||
"fuse.js": "^7.0.0",
|
||||
"heic2any": "^0.0.4",
|
||||
"html-to-image": "^1.11.11",
|
||||
"idb-keyval": "^6.2.1",
|
||||
"install": "^0.13.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"markdown-to-txt": "^2.0.1",
|
||||
"mermaid": "^10.6.1",
|
||||
"nanoid": "^5.0.3",
|
||||
"next": "^14.1.1",
|
||||
"node-fetch": "^3.3.1",
|
||||
"npm": "^11.4.2",
|
||||
"openapi-client-axios": "^7.5.5",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
@ -59,7 +54,6 @@
|
||||
"rt-client": "https://github.com/Azure-Samples/aoai-realtime-audio-sdk/releases/download/js/v0.5.0/rt-client-0.5.0.tgz",
|
||||
"sass": "^1.59.2",
|
||||
"spark-md5": "^3.0.2",
|
||||
"supabase": "^2.26.9",
|
||||
"use-debounce": "^9.0.4",
|
||||
"zod": "^3.24.1",
|
||||
"zustand": "^4.3.8"
|
||||
|
Loading…
Reference in New Issue
Block a user