Skip to content

Commit 9cbcec1

Browse files
author
dreamer6680
committed
add feishu oauth for feishudataset
1 parent 99bc704 commit 9cbcec1

File tree

24 files changed

+327
-245
lines changed

24 files changed

+327
-245
lines changed

packages/global/core/dataset/apiDataset.d.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@ export type APIFileServer = {
1818
basePath?: string;
1919
};
2020
export type FeishuShareServer = {
21-
appId: string;
22-
appSecret?: string;
21+
user_access_token: string;
22+
refresh_token: string;
23+
outdate_time: number;
2324
folderToken: string;
2425
};
2526
export type FeishuKnowledgeServer = {
26-
appId: string;
27-
appSecret: string;
27+
user_access_token: string;
28+
refresh_token: string;
29+
outdate_time: number;
2830
basePath?: string;
2931
};
3032

packages/service/core/dataset/feishuKnowledgeDataset/api.ts

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -121,15 +121,7 @@ export const useFeishuKnowledgeDatasetRequest = ({
121121
// 添加请求拦截器
122122
instance.interceptors.request.use(async (config) => {
123123
if (!config.headers.Authorization) {
124-
const { data } = await axios.post<{ tenant_access_token: string }>(
125-
`${feishuBaseUrl}/open-apis/auth/v3/tenant_access_token/internal`,
126-
{
127-
app_id: feishuKnowledgeServer.appId,
128-
app_secret: feishuKnowledgeServer.appSecret
129-
}
130-
);
131-
132-
config.headers['Authorization'] = `Bearer ${data.tenant_access_token}`;
124+
config.headers['Authorization'] = `Bearer ${feishuKnowledgeServer.user_access_token}`;
133125
config.headers['Content-Type'] = 'application/json; charset=utf-8';
134126
}
135127
return config;

packages/service/core/dataset/feishuPrivateDataset/api.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,10 @@ export const useFeishuPrivateDatasetRequest = ({
130130

131131
return data.files;
132132
};
133-
const parent = parentId?.split('-')[1];
133+
if (!parentId) {
134+
parentId = feishuPrivateServer.basePath?.split('-').slice(-1)[0];
135+
}
136+
const parent = parentId ? parentId.split('-').slice(-1)[0] : undefined;
134137

135138
const allFiles = await fetchFiles(undefined, parent);
136139

@@ -147,8 +150,8 @@ export const useFeishuPrivateDatasetRequest = ({
147150
.map((file) => ({
148151
id:
149152
file.type === 'shortcut'
150-
? file.parent_token + '-' + file.shortcut_info!.target_token
151-
: file.parent_token + '-' + file.token,
153+
? parentId + '-' + file.shortcut_info!.target_token
154+
: parentId + '-' + file.token,
152155
parentId: parentId,
153156
name: file.name,
154157
type: file.type === 'folder' ? ('folder' as const) : ('file' as const),
@@ -199,15 +202,15 @@ export const useFeishuPrivateDatasetRequest = ({
199202
}: {
200203
apiFileId: string;
201204
}): Promise<ApiDatasetDetailResponse> => {
202-
const parentId = apiFileId.split('-')[0];
203-
const fileId = apiFileId.split('-')[1];
205+
const parentId = apiFileId.split('-').slice(0, -1).join('-');
206+
const fileId = apiFileId.split('-').slice(-1)[0];
204207

205208
const fileDetail = await request<FeishuFileDetailResponse['data']>(
206209
`/open-apis/drive/explorer/v2/folder/${fileId}/meta`,
207210
{},
208211
'GET'
209212
);
210-
console.log('fileDetail', fileDetail);
213+
211214
if (!fileDetail) {
212215
return {
213216
name: '',
@@ -218,7 +221,7 @@ export const useFeishuPrivateDatasetRequest = ({
218221

219222
return {
220223
name: fileDetail?.name,
221-
parentId: null,
224+
parentId: parentId !== 'null' ? parentId : null,
222225
id: apiFileId
223226
};
224227
};

packages/service/core/dataset/feishuPrivateDataset/refreshToken.ts

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,29 @@ import axios from 'axios';
22
import { MongoDataset } from '../schema';
33
import { addLog } from '../../../common/system/log';
44

5-
const appId = global.feConfigs.feishu_auth_robot_client_id;
6-
const appSecret = global.feConfigs.feishu_auth_robot_client_secret;
7-
85
/**
96
* refresh feishu token
107
* refresh token before 10 minutes
118
*/
129
export async function refreshFeishuToken() {
1310
try {
1411
const datasets = await MongoDataset.find({
15-
type: { $in: ['feishuPrivate'] }
12+
type: { $in: ['feishuPrivate', 'feishuShare', 'feishuKnowledge'] }
1613
});
1714

15+
const appId = global.feConfigs?.feishu_auth_robot_client_id;
16+
const appSecret = global.feConfigs?.feishu_auth_robot_client_secret;
17+
1818
const refreshPromises = datasets
19-
.filter((dataset) => dataset.feishuPrivateServer)
19+
.filter(
20+
(dataset) =>
21+
(dataset.type === 'feishuPrivate' && dataset.feishuPrivateServer) ||
22+
(dataset.type === 'feishuShare' && dataset.feishuShareServer) ||
23+
(dataset.type === 'feishuKnowledge' && dataset.feishuKnowledgeServer)
24+
)
2025
.map(async (dataset) => {
2126
try {
27+
const serverKey = `${dataset.type}Server` as keyof typeof dataset;
2228
const response = await axios.post<{
2329
access_token: string;
2430
refresh_token: string;
@@ -29,11 +35,11 @@ export async function refreshFeishuToken() {
2935
client_id: appId,
3036
client_secret: appSecret,
3137
grant_type: 'refresh_token',
32-
refresh_token: dataset.feishuPrivateServer?.refresh_token
38+
refresh_token: dataset[serverKey]?.refresh_token
3339
},
3440
{
3541
headers: {
36-
'Content-Type': 'application/json'
42+
'Content-Type': 'application/json; charset=utf-8'
3743
}
3844
}
3945
);
@@ -48,7 +54,7 @@ export async function refreshFeishuToken() {
4854
// update dataset
4955
await MongoDataset.findByIdAndUpdate(dataset._id, {
5056
$set: {
51-
feishuPrivateServer: {
57+
[serverKey]: {
5258
user_access_token: response.data.access_token,
5359
refresh_token: response.data.refresh_token,
5460
outdate_time: Date.now() + response.data.expires_in * 1000
@@ -61,8 +67,8 @@ export async function refreshFeishuToken() {
6167
});
6268
} catch (error) {
6369
addLog.error('Refresh Feishu token error', {
64-
error,
65-
datasetId: dataset._id
70+
datasetId: dataset._id,
71+
error: JSON.stringify(error)
6672
});
6773
}
6874
});

packages/service/core/dataset/feishuShareDataset/api.ts

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ type FeishuFileListResponse = {
2424
created_time: number;
2525
url: string;
2626
owner_id: string;
27+
shortcut_info?: {
28+
target_token: string;
29+
target_type: string;
30+
};
2731
}[];
2832
has_more: boolean;
2933
next_page_token: string;
@@ -44,15 +48,7 @@ export const useFeishuShareDatasetRequest = ({
4448
// 添加请求拦截器
4549
instance.interceptors.request.use(async (config) => {
4650
if (!config.headers.Authorization) {
47-
const { data } = await axios.post<{ tenant_access_token: string }>(
48-
`${feishuBaseUrl}/open-apis/auth/v3/tenant_access_token/internal`,
49-
{
50-
app_id: feishuShareServer.appId,
51-
app_secret: feishuShareServer.appSecret
52-
}
53-
);
54-
55-
config.headers['Authorization'] = `Bearer ${data.tenant_access_token}`;
51+
config.headers['Authorization'] = `Bearer ${feishuShareServer.user_access_token}`;
5652
config.headers['Content-Type'] = 'application/json; charset=utf-8';
5753
}
5854
return config;
@@ -131,10 +127,18 @@ export const useFeishuShareDatasetRequest = ({
131127
const allFiles = await fetchFiles();
132128

133129
return allFiles
134-
.filter((file) => ['folder', 'docx'].includes(file.type))
130+
.filter((file) => {
131+
if (file.type === 'shortcut') {
132+
return (
133+
file.shortcut_info?.target_type === 'docx' ||
134+
file.shortcut_info?.target_type === 'folder'
135+
);
136+
}
137+
return file.type === 'folder' || file.type === 'docx';
138+
})
135139
.map((file) => ({
136-
id: file.token,
137-
parentId: file.parent_token,
140+
id: file.type === 'shortcut' ? file.shortcut_info!.target_token : file.token,
141+
parentId: parentId,
138142
name: file.name,
139143
type: file.type === 'folder' ? ('folder' as const) : ('file' as const),
140144
hasChild: file.type === 'folder',
@@ -148,17 +152,10 @@ export const useFeishuShareDatasetRequest = ({
148152
}: {
149153
apiFileId: string;
150154
}): Promise<ApiFileReadContentResponse> => {
155+
const fileId = apiFileId.split('-')[1];
151156
const [{ content }, { document }] = await Promise.all([
152-
request<{ content: string }>(
153-
`/open-apis/docx/v1/documents/${apiFileId}/raw_content`,
154-
{},
155-
'GET'
156-
),
157-
request<{ document: { title: string } }>(
158-
`/open-apis/docx/v1/documents/${apiFileId}`,
159-
{},
160-
'GET'
161-
)
157+
request<{ content: string }>(`/open-apis/docx/v1/documents/${fileId}/raw_content`, {}, 'GET'),
158+
request<{ document: { title: string } }>(`/open-apis/docx/v1/documents/${fileId}`, {}, 'GET')
162159
]);
163160

164161
return {
@@ -168,12 +165,13 @@ export const useFeishuShareDatasetRequest = ({
168165
};
169166

170167
const getFilePreviewUrl = async ({ apiFileId }: { apiFileId: string }): Promise<string> => {
168+
const fileId = apiFileId.split('-')[1];
171169
const { metas } = await request<{ metas: { url: string }[] }>(
172170
`/open-apis/drive/v1/metas/batch_query`,
173171
{
174172
request_docs: [
175173
{
176-
doc_token: apiFileId,
174+
doc_token: fileId,
177175
doc_type: 'docx'
178176
}
179177
],
Lines changed: 6 additions & 1 deletion
Loading
Lines changed: 4 additions & 1 deletion
Loading
Lines changed: 4 additions & 1 deletion
Loading
Lines changed: 11 additions & 1 deletion
Loading

packages/web/i18n/en/dataset.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,10 @@
7979
"external_url": "File Access URL",
8080
"failedToLoadRootDirectories": "Failed to load root directories",
8181
"failedToLoadSubDirectories": "Failed to load subdirectories",
82-
"feishu_auth_button": "Click Authorization",
82+
"feishu_auth_button": "Authorization",
8383
"feishu_auth_description": "Please complete Feishu authorization first to use personal knowledge base functions",
8484
"feishu_auth_title": "Need to authorize Feishu",
85+
"feishu_change_auth_button": "replace",
8586
"feishu_knowledge_dataset": "Feishu Knowledge Base",
8687
"feishu_knowledge_dataset_config": "Configure Feishu Knowledge Base",
8788
"feishu_knowledge_dataset_desc": "You can use Feishu Knowledge Base to build a knowledge base by configuring Feishu Knowledge Base. The knowledge base documents will not be stored secondaryly.",
@@ -96,6 +97,8 @@
9697
"filename": "Filename",
9798
"folder_dataset": "Folder",
9899
"getDirectoryFailed": "Get directory failed",
100+
"have_auth": "Authorized",
101+
"have_not_auth": "Unauthorized",
99102
"image_auto_parse": "Automatic image indexing",
100103
"image_auto_parse_tips": "Call VLM to automatically label the pictures in the document and generate additional search indexes",
101104
"image_training_queue": "Queue of image processing",
@@ -122,6 +125,7 @@
122125
"noSelectedFolder": "No selected folder",
123126
"noSelectedId": "No selected ID",
124127
"noValidId": "No valid ID",
128+
"not_set": "Not configured",
125129
"open_auto_sync": "After scheduled synchronization is turned on, the system will try to synchronize the collection from time to time every day. During the collection synchronization period, the collection data will not be searched.",
126130
"other_dataset": "Third-party knowledge base",
127131
"paragraph_max_deep": "Maximum paragraph depth",

0 commit comments

Comments
 (0)