Skip to content

Commit

Permalink
Merge pull request #340 from wblu214/1231-wblu/feishu-reader
Browse files Browse the repository at this point in the history
1231 wblu/feishu reader fix
  • Loading branch information
chickenlj authored Jan 13, 2025
2 parents b9cd1c0 + e288243 commit f6b8b21
Show file tree
Hide file tree
Showing 5 changed files with 294 additions and 52 deletions.
46 changes: 15 additions & 31 deletions community/document-readers/feishu-document-reader/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
Expand All @@ -29,6 +28,7 @@
<version>0.0.1-SNAPSHOT</version>
<name>feishu-document-reader</name>
<description>FeiShu Reader for Spring AI Alibaba</description>
<packaging>jar</packaging>
<url>https://github.com/alibaba/spring-ai-alibaba</url>
<scm>
<url>https://github.com/alibaba/spring-ai-alibaba</url>
Expand All @@ -41,43 +41,27 @@
</properties>

<dependencies>
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-core</artifactId>
<version>${project.parent.version}</version>
</dependency>

<dependency>
<groupId>com.larksuite.oapi</groupId>
<artifactId>oapi-sdk</artifactId>
<version>2.3.7</version>
</dependency>
<!-- test dependencies -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-core</artifactId>
<artifactId>spring-ai-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>${maven-deploy-plugin.version}</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>

<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -22,31 +22,57 @@
import com.lark.oapi.service.docx.v1.model.*;
import com.lark.oapi.service.drive.v1.model.ListFileReq;
import com.lark.oapi.service.drive.v1.model.ListFileResp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.document.Document;
import org.springframework.ai.document.DocumentReader;
import org.springframework.ai.reader.ExtractedTextFormatter;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import static java.lang.String.format;

/**
* @author wblu214
* @author <a href="mailto:2897718178@qq.com">wblu214</a>
*/
public class FeiShuDocumentReader implements DocumentReader {

private static final Logger log = LoggerFactory.getLogger(FeiShuDocumentReader.class);

private final FeiShuResource feiShuResource;

private final Client client;

private ExtractedTextFormatter textFormatter;
private String documentId;

private String userAccessToken;

private String tenantAccessToken;

public FeiShuDocumentReader(FeiShuResource feiShuResource) {
this.feiShuResource = feiShuResource;
this.client = feiShuResource.buildDefaultFeiShuClient();
}

public FeiShuDocumentReader(FeiShuResource feiShuResource, String documentId, String userAccessToken,
String tenantAccessToken) {
this(feiShuResource);
this.documentId = documentId;
this.userAccessToken = userAccessToken;
this.tenantAccessToken = tenantAccessToken;
}

public FeiShuDocumentReader(Client client) {
this.client = client;
public FeiShuDocumentReader(FeiShuResource feiShuResource, String userAccessToken) {
this(feiShuResource);
this.userAccessToken = userAccessToken;
}

public FeiShuDocumentReader(Client client, ExtractedTextFormatter textFormatter) {
this.client = client;
this.textFormatter = textFormatter;
public FeiShuDocumentReader(FeiShuResource feiShuResource, String userAccessToken, String documentId) {
this(feiShuResource);
this.userAccessToken = userAccessToken;
this.documentId = documentId;
}

/**
Expand All @@ -55,7 +81,7 @@ public FeiShuDocumentReader(Client client, ExtractedTextFormatter textFormatter)
* @param userAccessToken userAccessToken
* @return String
*/
public String getDocumentContentByUser(String documentId, String userAccessToken) throws Exception {
public Document getDocumentContentByUser(String documentId, String userAccessToken) throws Exception {
RawContentDocumentReq req = RawContentDocumentReq.newBuilder().documentId(documentId).lang(0).build();

RawContentDocumentResp resp = client.docx()
Expand All @@ -69,7 +95,7 @@ public String getDocumentContentByUser(String documentId, String userAccessToken
throw new Exception(resp.getMsg());
}

return Jsons.DEFAULT.toJson(resp.getData());
return toDocument(Jsons.DEFAULT.toJson(resp.getData()));
}

/**
Expand All @@ -78,7 +104,7 @@ public String getDocumentContentByUser(String documentId, String userAccessToken
* @param tenantAccessToken tenantAccessToken
* @return String
*/
public String getDocumentContentByTenant(String documentId, String tenantAccessToken) throws Exception {
public Document getDocumentContentByTenant(String documentId, String tenantAccessToken) throws Exception {
RawContentDocumentReq req = RawContentDocumentReq.newBuilder().documentId(documentId).lang(0).build();

RawContentDocumentResp resp = client.docx()
Expand All @@ -91,15 +117,15 @@ public String getDocumentContentByTenant(String documentId, String tenantAccessT
.parseString(new String(resp.getRawResponse().getBody(), StandardCharsets.UTF_8))));
throw new Exception(resp.getMsg());
}
return Jsons.DEFAULT.toJson(resp.getData());
return toDocument(Jsons.DEFAULT.toJson(resp.getData()));
}

/**
* get document list
* @param userAccessToken userAccessToken
* @return String
*/
public String getDocumentListByUser(String userAccessToken) throws Exception {
public Document getDocumentListByUser(String userAccessToken) throws Exception {
ListFileReq req = ListFileReq.newBuilder().orderBy("EditedTime").direction("DESC").build();
ListFileResp resp = client.drive()
.file()
Expand All @@ -111,23 +137,51 @@ public String getDocumentListByUser(String userAccessToken) throws Exception {
.parseString(new String(resp.getRawResponse().getBody(), StandardCharsets.UTF_8))));
throw new Exception(resp.getMsg());
}
return Jsons.DEFAULT.toJson(resp.getData());
return toDocument(Jsons.DEFAULT.toJson(resp.getData()));
}

private Document toDocument(String docText) {
docText = Objects.requireNonNullElse(docText, "");
docText = this.textFormatter.format(docText);
return new Document(docText);
}

@Override
public List<Document> get() {
return null;
List<Document> documents = new ArrayList<>();
if (this.feiShuResource != null) {
loadDocuments(documents, this.feiShuResource);
}
return documents;
}

@Override
public List<Document> read() {
return DocumentReader.super.read();
private void loadDocuments(List<Document> documents, FeiShuResource feiShuResource) {
String appId = feiShuResource.getAppId();
String appSecret = feiShuResource.getAppSecret();
String source = format("feishu://%s/%s", appId, appSecret);
try {
documents.add(new Document(source));
if (this.userAccessToken != null) {
documents.add(getDocumentListByUser(userAccessToken));
}
else {
log.info("userAccessToken is null");
}
if (this.tenantAccessToken != null && this.documentId != null) {
documents.add(getDocumentContentByTenant(documentId, tenantAccessToken));
}
else {
log.info("tenantAccessToken or documentId is null");
}
if (this.userAccessToken != null && this.documentId != null) {
documents.add(getDocumentContentByUser(documentId, userAccessToken));
}
else {
log.info("userAccessToken or documentId is null");
}

}
catch (Exception e) {
log.warn("Failed to load an object with appId: {}, appSecret: {},{}", appId, appSecret, e.getMessage(), e);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/*
* Copyright 2024-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.cloud.ai.reader.feishu;

import com.lark.oapi.Client;
import com.lark.oapi.core.enums.BaseUrlEnum;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URL;

public class FeiShuResource implements Resource {

public static final String SOURCE = "source";

public static final String FEISHU_PROPERTIES_PREFIX = "spring.ai.alibaba.plugin.feishu";

private final String appId;

private final String appSecret;

public String getAppId() {
return appId;
}

public String getAppSecret() {
return appSecret;
}

public FeiShuResource(String appId, String appSecret) {
this.appId = appId;
this.appSecret = appSecret;
}

public static Builder builder() {
return new Builder();
}

public static class Builder {

private String appId;

private String appSecret;

public Builder appId(String appId) {
this.appId = appId;
return this;
}

public Builder appSecret(String appSecret) {
this.appSecret = appSecret;
return this;
}

public FeiShuResource build() {
Assert.notNull(appId, "FeiShu AppId must not be empty");
Assert.notNull(appSecret, "FeiShu AppSecret must not be empty");
return new FeiShuResource(appId, appSecret);
}

}

public Client buildDefaultFeiShuClient() {
Assert.notNull(this.appId, "FeiShu AppId must not be empty");
Assert.notNull(this.appSecret, "FeiShu AppSecret must not be empty");
return Client.newBuilder(this.appId, this.appSecret)
.openBaseUrl(BaseUrlEnum.FeiShu)
.logReqAtDebug(true)
.build();
}

@Override
public boolean exists() {
return false;
}

@Override
public URL getURL() throws IOException {
return null;
}

@Override
public URI getURI() throws IOException {
return null;
}

@Override
public File getFile() throws IOException {
return null;
}

@Override
public long contentLength() throws IOException {
return 0;
}

@Override
public long lastModified() throws IOException {
return 0;
}

@Override
public Resource createRelative(String relativePath) throws IOException {
return null;
}

@Override
public String getFilename() {
return null;
}

@Override
public String getDescription() {
return null;
}

@Override
public InputStream getInputStream() throws IOException {
return null;
}

}

This file was deleted.

Loading

0 comments on commit f6b8b21

Please sign in to comment.