-
Notifications
You must be signed in to change notification settings - Fork 242
/
utils.ts
110 lines (99 loc) · 3.86 KB
/
utils.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import {
createParser,
ParseEvent,
ReconnectInterval,
} from 'eventsource-parser';
import CryptoJS from 'crypto-js';
export const SECRET_KEY =
'64787423c7ea99e608bab61303b309a996a1e000db87bd73533bd979892b1644';
export const encryptApiKey = (apiKey: string) => {
const encryptedApiKey = CryptoJS.AES.encrypt(apiKey, SECRET_KEY).toString();
return encryptedApiKey;
};
export const decryptApiKey = (encryptedApiKey: string) => {
// 使用AES加密算法进行解密
const bytes = CryptoJS.AES.decrypt(encryptedApiKey, SECRET_KEY);
const decryptedApiKey = bytes.toString(CryptoJS.enc.Utf8);
return decryptedApiKey;
};
export const parseOpenAIStream = (rawResponse: Response) => {
const encoder = new TextEncoder();
const decoder = new TextDecoder();
const stream = new ReadableStream({
async start(controller) {
const streamParser = (event: ParseEvent | ReconnectInterval) => {
if (event.type === 'event') {
const data = event.data;
if (data === '[DONE]') {
controller.close();
return;
}
try {
const json = JSON.parse(data);
const text = json.choices?.[0]?.delta?.content || '';
const queue = encoder.encode(text);
controller.enqueue(queue);
} catch (e) {}
}
};
const parser = createParser(streamParser);
if (!rawResponse.body) return;
const reader = rawResponse.body.getReader();
try {
while (true) {
const { done, value } = await reader.read();
if (done) {
break;
}
parser.feed(decoder.decode(value));
}
} catch (error) {}
},
});
return stream;
};
export function dataURItoBlob(dataURI: string) {
// 将base64编码的数据去掉头部信息
const byteString = atob(dataURI.split(',')[1]);
// 创建一个类型数组对象来存放转换后的字符
const ia = new Uint8Array(byteString.length);
// 循环遍历每个字符,将它们转换成Unicode字符码,并存储到数组中
for (let i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
// 使用Blob对象封装二进制数据,并设置MIME类型为图片格式
const blob = new Blob([ia], { type: 'image/png' });
return blob;
}
export const readBlobAsDataURL = (blob: Blob): Promise<string> => {
return new Promise<string>((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result?.toString() || '');
reader.onerror = reject;
reader.readAsDataURL(blob);
});
};
export const formatTimestamp = (timestamp: number) => {
const length = timestamp.toString().length;
if (length === 10) {
timestamp *= 1000; // 转换为毫秒
}
const date = new Date(timestamp);
const year = date.getFullYear();
const month = date.getMonth() + 1;
const day = date.getDate();
const formattedDate =
year +
'/' +
(month > 9 ? month : `0${month}`) +
'/' +
(day > 9 ? day : `0${day}`);
return formattedDate;
};
export const ThemeLocalKey = 'light_gpt_theme';
export const UserAvatarLocalKey = 'light_gpt_user_avatar';
export const RobotAvatarLocalKey = 'light_gpt_robot_avatar';
export const SystemRoleLocalKey = 'light_gpt_system_role';
export const APIKeyLocalKey = 'light_gpt_api_key';
export const GenerateImagePromptPrefix = 'img-';
export const DefaultSystemRole = `You are a versatile expert, please answer each of my questions in a simple and easy-to-understand way as much as possible`;