Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
KnowledgePlanet
road-map
xfg-dev-tech-mock
提交
c3ec1f2f
xfg-dev-tech-mock
项目概览
KnowledgePlanet
/
road-map
/
xfg-dev-tech-mock
通知
80
Star
13
Fork
6
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
xfg-dev-tech-mock
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
c3ec1f2f
编写于
10月 22, 2023
作者:
小傅哥
⛹
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: Ai 自动回帖实现
上级
76e3453b
变更
26
隐藏空白更改
内联
并排
Showing
26 changed file
with
946 addition
and
0 deletion
+946
-0
docs/images/mock.png
docs/images/mock.png
+0
-0
pom.xml
pom.xml
+24
-0
xfg-dev-tech-app/pom.xml
xfg-dev-tech-app/pom.xml
+15
-0
xfg-dev-tech-app/src/main/java/cn/bugstack/xfg/dev/tech/config/ChatGLMSDKConfig.java
...ava/cn/bugstack/xfg/dev/tech/config/ChatGLMSDKConfig.java
+35
-0
xfg-dev-tech-app/src/main/java/cn/bugstack/xfg/dev/tech/config/ChatGLMSDKConfigProperties.java
...stack/xfg/dev/tech/config/ChatGLMSDKConfigProperties.java
+22
-0
xfg-dev-tech-app/src/main/resources/application-dev.yml
xfg-dev-tech-app/src/main/resources/application-dev.yml
+19
-0
xfg-dev-tech-app/src/test/java/cn/bugstack/xfg/dev/tech/test/ApiTest.java
.../src/test/java/cn/bugstack/xfg/dev/tech/test/ApiTest.java
+32
-0
xfg-dev-tech-domain/pom.xml
xfg-dev-tech-domain/pom.xml
+56
-0
xfg-dev-tech-domain/src/main/java/cn/bugstack/xfg/dev/tech/domain/zsxq/adapter/IZSXQAdapter.java
...gstack/xfg/dev/tech/domain/zsxq/adapter/IZSXQAdapter.java
+18
-0
xfg-dev-tech-domain/src/main/java/cn/bugstack/xfg/dev/tech/domain/zsxq/model/vo/TopicsItemVO.java
...stack/xfg/dev/tech/domain/zsxq/model/vo/TopicsItemVO.java
+35
-0
xfg-dev-tech-domain/src/main/java/cn/bugstack/xfg/dev/tech/domain/zsxq/service/AiReply.java
...cn/bugstack/xfg/dev/tech/domain/zsxq/service/AiReply.java
+159
-0
xfg-dev-tech-domain/src/main/java/cn/bugstack/xfg/dev/tech/domain/zsxq/service/IAiReply.java
...n/bugstack/xfg/dev/tech/domain/zsxq/service/IAiReply.java
+12
-0
xfg-dev-tech-infrastructure/pom.xml
xfg-dev-tech-infrastructure/pom.xml
+46
-0
xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/gateway/adapter/ZSXQAdapter.java
.../dev/tech/infrastructure/gateway/adapter/ZSXQAdapter.java
+65
-0
xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/gateway/api/IZSXQApi.java
...ack/xfg/dev/tech/infrastructure/gateway/api/IZSXQApi.java
+30
-0
xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/gateway/api/impl/ZSXQApi.java
...xfg/dev/tech/infrastructure/gateway/api/impl/ZSXQApi.java
+112
-0
xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/gateway/dto/Group.java
...gstack/xfg/dev/tech/infrastructure/gateway/dto/Group.java
+20
-0
xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/gateway/dto/Owner.java
...gstack/xfg/dev/tech/infrastructure/gateway/dto/Owner.java
+20
-0
xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/gateway/dto/RespData.java
...ack/xfg/dev/tech/infrastructure/gateway/dto/RespData.java
+13
-0
xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/gateway/dto/ResponseDTO.java
.../xfg/dev/tech/infrastructure/gateway/dto/ResponseDTO.java
+14
-0
xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/gateway/dto/ShowCommentsItem.java
...dev/tech/infrastructure/gateway/dto/ShowCommentsItem.java
+29
-0
xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/gateway/dto/Talk.java
...ugstack/xfg/dev/tech/infrastructure/gateway/dto/Talk.java
+14
-0
xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/gateway/dto/TopicsItem.java
...k/xfg/dev/tech/infrastructure/gateway/dto/TopicsItem.java
+52
-0
xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/gateway/dto/UserSpecific.java
...xfg/dev/tech/infrastructure/gateway/dto/UserSpecific.java
+14
-0
xfg-dev-tech-trigger/pom.xml
xfg-dev-tech-trigger/pom.xml
+63
-0
xfg-dev-tech-trigger/src/main/java/cn/bugstack/xfg/dev/tech/job/ReplyJob.java
.../src/main/java/cn/bugstack/xfg/dev/tech/job/ReplyJob.java
+27
-0
未找到文件。
docs/images/mock.png
0 → 100644
浏览文件 @
c3ec1f2f
61.4 KB
pom.xml
浏览文件 @
c3ec1f2f
...
@@ -10,6 +10,9 @@
...
@@ -10,6 +10,9 @@
<packaging>
pom
</packaging>
<packaging>
pom
</packaging>
<modules>
<modules>
<module>
xfg-dev-tech-app
</module>
<module>
xfg-dev-tech-app
</module>
<module>
xfg-dev-tech-infrastructure
</module>
<module>
xfg-dev-tech-domain
</module>
<module>
xfg-dev-tech-trigger
</module>
</modules>
</modules>
<properties>
<properties>
...
@@ -45,6 +48,27 @@
...
@@ -45,6 +48,27 @@
<artifactId>
guava
</artifactId>
<artifactId>
guava
</artifactId>
<version>
32.1.2-jre
</version>
<version>
32.1.2-jre
</version>
</dependency>
</dependency>
<dependency>
<groupId>
com.squareup.retrofit2
</groupId>
<artifactId>
converter-gson
</artifactId>
<version>
2.9.0
</version>
</dependency>
<dependency>
<groupId>
cn.bugstack
</groupId>
<artifactId>
chatglm-sdk-java
</artifactId>
<version>
1.0-SNAPSHOT
</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency>
<groupId>
org.apache.httpcomponents
</groupId>
<artifactId>
httpclient
</artifactId>
<version>
4.5.14
</version>
</dependency>
<dependency>
<groupId>
org.apache.httpcomponents
</groupId>
<artifactId>
httpmime
</artifactId>
<version>
4.5.10
</version>
</dependency>
</dependencies>
</dependencies>
</dependencyManagement>
</dependencyManagement>
...
...
xfg-dev-tech-app/pom.xml
浏览文件 @
c3ec1f2f
...
@@ -54,6 +54,21 @@
...
@@ -54,6 +54,21 @@
<groupId>
com.google.guava
</groupId>
<groupId>
com.google.guava
</groupId>
<artifactId>
guava
</artifactId>
<artifactId>
guava
</artifactId>
</dependency>
</dependency>
<dependency>
<groupId>
cn.bugstack
</groupId>
<artifactId>
chatglm-sdk-java
</artifactId>
</dependency>
<!-- 系统 module -->
<dependency>
<groupId>
cn.bugstack
</groupId>
<artifactId>
xfg-dev-tech-infrastructure
</artifactId>
<version>
1.0-SNAPSHOT
</version>
</dependency>
<dependency>
<groupId>
cn.bugstack
</groupId>
<artifactId>
xfg-dev-tech-trigger
</artifactId>
<version>
1.0-SNAPSHOT
</version>
</dependency>
</dependencies>
</dependencies>
<build>
<build>
...
...
xfg-dev-tech-app/src/main/java/cn/bugstack/xfg/dev/tech/config/ChatGLMSDKConfig.java
0 → 100644
浏览文件 @
c3ec1f2f
package
cn.bugstack.xfg.dev.tech.config
;
import
cn.bugstack.chatglm.session.OpenAiSession
;
import
cn.bugstack.chatglm.session.OpenAiSessionFactory
;
import
cn.bugstack.chatglm.session.defaults.DefaultOpenAiSessionFactory
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
;
import
org.springframework.boot.context.properties.EnableConfigurationProperties
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description ChatGLMSDK
* @create 2023-10-22 10:00
*/
@Configuration
@EnableConfigurationProperties
(
ChatGLMSDKConfigProperties
.
class
)
public
class
ChatGLMSDKConfig
{
@Bean
@ConditionalOnProperty
(
value
=
"chatglm.sdk.config.enabled"
,
havingValue
=
"true"
,
matchIfMissing
=
false
)
public
OpenAiSession
openAiSession
(
ChatGLMSDKConfigProperties
properties
)
{
// 1. 配置文件
cn
.
bugstack
.
chatglm
.
session
.
Configuration
configuration
=
new
cn
.
bugstack
.
chatglm
.
session
.
Configuration
();
configuration
.
setApiHost
(
properties
.
getApiHost
());
configuration
.
setApiSecretKey
(
properties
.
getApiSecretKey
());
// 2. 会话工厂
OpenAiSessionFactory
factory
=
new
DefaultOpenAiSessionFactory
(
configuration
);
// 3. 开启会话
return
factory
.
openSession
();
}
}
xfg-dev-tech-app/src/main/java/cn/bugstack/xfg/dev/tech/config/ChatGLMSDKConfigProperties.java
0 → 100644
浏览文件 @
c3ec1f2f
package
cn.bugstack.xfg.dev.tech.config
;
import
lombok.Data
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description ChatGLMSDK Config
* @create 2023-10-22 10:00
*/
@Data
@ConfigurationProperties
(
prefix
=
"chatglm.sdk.config"
,
ignoreInvalidFields
=
true
)
public
class
ChatGLMSDKConfigProperties
{
/** 状态;open = 开启、close 关闭 */
private
boolean
enable
;
/** 转发地址 */
private
String
apiHost
;
/** 可以申请 sk-*** */
private
String
apiSecretKey
;
}
xfg-dev-tech-app/src/main/resources/application-dev.yml
浏览文件 @
c3ec1f2f
...
@@ -2,6 +2,25 @@ server:
...
@@ -2,6 +2,25 @@ server:
port
:
8091
port
:
8091
application
:
application
:
name
:
xfg-dev-tech-mock
name
:
xfg-dev-tech-mock
# ChatGLM SDK Config
chatglm
:
sdk
:
config
:
# 状态;true = 开启、false 关闭
enabled
:
true
# 官网地址
api-host
:
https://open.bigmodel.cn/
# 官网申请 https://open.bigmodel.cn/usercenter/apikeys
api-secret-key
:
d570f7c5d289cdac2abdfdc562e39f3f.trqz1dH8ZK6ED7Pg
# 知识星球配置信息;id -> 星球ID、user-id -> 用户ID、cookie -> 登录cookie
zsxq
:
config
:
id
:
28885518425541
user-id
:
241858242255511
cookie
:
zsxq_access_token=E0538FF2-B440-69E9-57D1-59EA37B9C0C6_9D76421394C6F474
# 日志
# 日志
logging
:
logging
:
level
:
level
:
...
...
xfg-dev-tech-app/src/test/java/cn/bugstack/xfg/dev/tech/test/ApiTest.java
0 → 100644
浏览文件 @
c3ec1f2f
package
cn.bugstack.xfg.dev.tech.test
;
import
cn.bugstack.xfg.dev.tech.domain.zsxq.service.IAiReply
;
import
lombok.extern.slf4j.Slf4j
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.springframework.boot.test.context.SpringBootTest
;
import
org.springframework.test.context.junit4.SpringRunner
;
import
javax.annotation.Resource
;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 单元测试
* @create 2023-10-22 09:08
*/
@Slf4j
@RunWith
(
SpringRunner
.
class
)
@SpringBootTest
public
class
ApiTest
{
@Resource
private
IAiReply
aiReply
;
@Test
public
void
test_IAiReply
()
{
aiReply
.
doAiReply
();
}
}
xfg-dev-tech-domain/pom.xml
0 → 100644
浏览文件 @
c3ec1f2f
<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<modelVersion>
4.0.0
</modelVersion>
<parent>
<groupId>
cn.bugstack
</groupId>
<artifactId>
xfg-dev-tech-mock
</artifactId>
<version>
1.0-SNAPSHOT
</version>
</parent>
<artifactId>
xfg-dev-tech-domain
</artifactId>
<dependencies>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-web
</artifactId>
</dependency>
<dependency>
<groupId>
org.projectlombok
</groupId>
<artifactId>
lombok
</artifactId>
</dependency>
<dependency>
<groupId>
com.alibaba
</groupId>
<artifactId>
fastjson
</artifactId>
</dependency>
<dependency>
<groupId>
org.apache.commons
</groupId>
<artifactId>
commons-lang3
</artifactId>
</dependency>
<dependency>
<groupId>
com.google.guava
</groupId>
<artifactId>
guava
</artifactId>
</dependency>
<dependency>
<groupId>
cn.bugstack
</groupId>
<artifactId>
chatglm-sdk-java
</artifactId>
</dependency>
</dependencies>
<build>
<finalName>
xfg-dev-tech-domain
</finalName>
<plugins>
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-compiler-plugin
</artifactId>
<configuration>
<source>
${java.version}
</source>
<target>
${java.version}
</target>
<compilerVersion>
${java.version}
</compilerVersion>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
xfg-dev-tech-domain/src/main/java/cn/bugstack/xfg/dev/tech/domain/zsxq/adapter/IZSXQAdapter.java
0 → 100644
浏览文件 @
c3ec1f2f
package
cn.bugstack.xfg.dev.tech.domain.zsxq.adapter
;
import
cn.bugstack.xfg.dev.tech.domain.zsxq.model.vo.TopicsItemVO
;
import
java.util.List
;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 知识星球接口适配
* @create 2023-10-22 10:11
*/
public
interface
IZSXQAdapter
{
List
<
TopicsItemVO
>
queryTopics
();
void
comment
(
long
topicId
,
String
content
);
}
xfg-dev-tech-domain/src/main/java/cn/bugstack/xfg/dev/tech/domain/zsxq/model/vo/TopicsItemVO.java
0 → 100644
浏览文件 @
c3ec1f2f
package
cn.bugstack.xfg.dev.tech.domain.zsxq.model.vo
;
import
lombok.AllArgsConstructor
;
import
lombok.Builder
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
java.util.List
;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 话题
* @create 2023-10-22 10:13
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public
class
TopicsItemVO
{
private
long
topicId
;
private
String
talk
;
private
List
<
ShowCommentsItem
>
showCommentsItems
;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public
static
class
ShowCommentsItem
{
private
long
userId
;
}
}
xfg-dev-tech-domain/src/main/java/cn/bugstack/xfg/dev/tech/domain/zsxq/service/AiReply.java
0 → 100644
浏览文件 @
c3ec1f2f
package
cn.bugstack.xfg.dev.tech.domain.zsxq.service
;
import
cn.bugstack.chatglm.model.*
;
import
cn.bugstack.chatglm.session.OpenAiSession
;
import
cn.bugstack.xfg.dev.tech.domain.zsxq.adapter.IZSXQAdapter
;
import
cn.bugstack.xfg.dev.tech.domain.zsxq.model.vo.TopicsItemVO
;
import
com.alibaba.fastjson.JSON
;
import
com.fasterxml.jackson.core.JsonProcessingException
;
import
lombok.extern.slf4j.Slf4j
;
import
okhttp3.sse.EventSource
;
import
okhttp3.sse.EventSourceListener
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.stereotype.Service
;
import
javax.annotation.Nullable
;
import
javax.annotation.Resource
;
import
java.util.ArrayList
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Set
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 只能回帖
* @create 2023-10-22 10:10
*/
@Slf4j
@Service
public
class
AiReply
implements
IAiReply
{
@Autowired
(
required
=
false
)
private
OpenAiSession
openAiSession
;
@Resource
private
IZSXQAdapter
zsxqAdapter
;
@Value
(
"${zsxq.config.user-id}"
)
private
Long
userId
;
private
final
String
regex
=
"<e type=\"mention\" uid=\"(\\d+)\" title=\"(.*?)\" /> (.*)"
;
private
volatile
Set
<
Long
>
topicIds
=
new
HashSet
<>();
@Override
public
void
doAiReply
()
{
List
<
TopicsItemVO
>
topicsItemVOS
=
zsxqAdapter
.
queryTopics
();
for
(
TopicsItemVO
topicsItem
:
topicsItemVOS
)
{
// 是否回答过判断
if
(!
isCommentDone
(
topicsItem
))
continue
;
// 找到圈我我帖子
long
topicId
=
topicsItem
.
getTopicId
();
String
text
=
topicsItem
.
getTalk
();
// "<e type="mention" uid="241858242255511" title="%40%E5%B0%8F%E5%82%85%E5%93%A5" /> 提问 java 冒泡排序"
Pattern
pattern
=
Pattern
.
compile
(
regex
);
Matcher
matcher
=
pattern
.
matcher
(
text
);
if
(!
matcher
.
find
())
continue
;
String
uid
=
matcher
.
group
(
1
);
String
remainingText
=
matcher
.
group
(
3
);
if
(
this
.
userId
.
equals
(
Long
.
valueOf
(
uid
)))
{
if
(
null
==
openAiSession
)
{
log
.
info
(
"你没有开启 ChatGLM 参考yml配置文件来开启"
);
// 你可以使用 ChatGLM SDK 进行回答,回复问题;
zsxqAdapter
.
comment
(
topicId
,
"【测试,只回答圈我的帖子】对接 ChatGLM SDK https://bugstack.cn/md/project/chatgpt/sdk/chatglm-sdk-java.html 回答:"
+
remainingText
);
}
else
{
log
.
info
(
"ChatGLM 进入回答 {} {}"
,
topicId
,
remainingText
);
if
(
topicIds
.
contains
(
topicId
))
{
continue
;
}
else
{
topicIds
.
add
(
topicId
);
}
new
Thread
(()
->
{
// 入参;模型、请求信息
ChatCompletionRequest
request
=
new
ChatCompletionRequest
();
request
.
setModel
(
Model
.
CHATGLM_LITE
);
// chatGLM_6b_SSE、chatglm_lite、chatglm_lite_32k、chatglm_std、chatglm_pro
request
.
setPrompt
(
new
ArrayList
<
ChatCompletionRequest
.
Prompt
>()
{
private
static
final
long
serialVersionUID
=
-
7988151926241837899L
;
{
add
(
ChatCompletionRequest
.
Prompt
.
builder
()
.
role
(
Role
.
user
.
getCode
())
.
content
(
remainingText
)
.
build
());
}
});
// 请求
try
{
StringBuilder
content
=
new
StringBuilder
();
openAiSession
.
completions
(
request
,
new
EventSourceListener
()
{
@Override
public
void
onEvent
(
EventSource
eventSource
,
@Nullable
String
id
,
@Nullable
String
type
,
String
data
)
{
ChatCompletionResponse
chatCompletionResponse
=
com
.
alibaba
.
fastjson
.
JSON
.
parseObject
(
data
,
ChatCompletionResponse
.
class
);
log
.
info
(
"测试结果 onEvent:{}"
,
chatCompletionResponse
.
getData
());
// type 消息类型,add 增量,finish 结束,error 错误,interrupted 中断
if
(
EventType
.
finish
.
getCode
().
equals
(
type
))
{
ChatCompletionResponse
.
Meta
meta
=
com
.
alibaba
.
fastjson
.
JSON
.
parseObject
(
chatCompletionResponse
.
getMeta
(),
ChatCompletionResponse
.
Meta
.
class
);
log
.
info
(
"[输出结束] Tokens {}"
,
com
.
alibaba
.
fastjson
.
JSON
.
toJSONString
(
meta
));
}
content
.
append
(
chatCompletionResponse
.
getData
());
}
@Override
public
void
onClosed
(
EventSource
eventSource
)
{
log
.
info
(
"对话完成"
);
// 你可以使用 ChatGLM SDK 进行回答,回复问题;
String
contents
=
"ChatGLM 回答:"
+
content
;
int
maxLength
=
5000
;
int
contentLength
=
contents
.
length
();
int
startIndex
=
0
;
int
endIndex
=
maxLength
;
while
(
startIndex
<
contentLength
)
{
if
(
endIndex
>
contentLength
)
{
endIndex
=
contentLength
;
}
String
subContent
=
contents
.
substring
(
startIndex
,
endIndex
);
zsxqAdapter
.
comment
(
topicId
,
subContent
);
startIndex
=
endIndex
;
endIndex
+=
maxLength
;
}
topicIds
.
remove
(
topicId
);
}
});
}
catch
(
JsonProcessingException
e
)
{
throw
new
RuntimeException
(
e
);
}
}).
start
();
}
}
}
log
.
info
(
"AI回复:{}"
,
JSON
.
toJSONString
(
topicsItemVOS
));
}
private
boolean
isCommentDone
(
TopicsItemVO
topicsItem
)
{
List
<
TopicsItemVO
.
ShowCommentsItem
>
showComments
=
topicsItem
.
getShowCommentsItems
();
if
(
null
==
showComments
||
showComments
.
isEmpty
())
return
true
;
for
(
TopicsItemVO
.
ShowCommentsItem
item
:
topicsItem
.
getShowCommentsItems
())
{
long
userId
=
item
.
getUserId
();
if
(
this
.
userId
==
userId
)
{
return
false
;
}
}
return
true
;
}
}
xfg-dev-tech-domain/src/main/java/cn/bugstack/xfg/dev/tech/domain/zsxq/service/IAiReply.java
0 → 100644
浏览文件 @
c3ec1f2f
package
cn.bugstack.xfg.dev.tech.domain.zsxq.service
;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 智能AI回帖
* @create 2023-10-22 10:08
*/
public
interface
IAiReply
{
void
doAiReply
();
}
xfg-dev-tech-infrastructure/pom.xml
0 → 100644
浏览文件 @
c3ec1f2f
<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<modelVersion>
4.0.0
</modelVersion>
<parent>
<groupId>
cn.bugstack
</groupId>
<artifactId>
xfg-dev-tech-mock
</artifactId>
<version>
1.0-SNAPSHOT
</version>
</parent>
<artifactId>
xfg-dev-tech-infrastructure
</artifactId>
<dependencies>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-web
</artifactId>
</dependency>
<dependency>
<groupId>
org.projectlombok
</groupId>
<artifactId>
lombok
</artifactId>
</dependency>
<dependency>
<groupId>
com.squareup.retrofit2
</groupId>
<artifactId>
converter-gson
</artifactId>
</dependency>
<dependency>
<groupId>
org.apache.httpcomponents
</groupId>
<artifactId>
httpclient
</artifactId>
</dependency>
<dependency>
<groupId>
org.apache.httpcomponents
</groupId>
<artifactId>
httpmime
</artifactId>
</dependency>
<dependency>
<groupId>
cn.bugstack
</groupId>
<artifactId>
xfg-dev-tech-domain
</artifactId>
<version>
1.0-SNAPSHOT
</version>
</dependency>
</dependencies>
<build>
<finalName>
xfg-dev-tech-infrastructure
</finalName>
</build>
</project>
\ No newline at end of file
xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/gateway/adapter/ZSXQAdapter.java
0 → 100644
浏览文件 @
c3ec1f2f
package
cn.bugstack.xfg.dev.tech.infrastructure.gateway.adapter
;
import
cn.bugstack.xfg.dev.tech.domain.zsxq.adapter.IZSXQAdapter
;
import
cn.bugstack.xfg.dev.tech.domain.zsxq.model.vo.TopicsItemVO
;
import
cn.bugstack.xfg.dev.tech.infrastructure.gateway.api.IZSXQApi
;
import
cn.bugstack.xfg.dev.tech.infrastructure.gateway.dto.RespData
;
import
cn.bugstack.xfg.dev.tech.infrastructure.gateway.dto.ResponseDTO
;
import
cn.bugstack.xfg.dev.tech.infrastructure.gateway.dto.TopicsItem
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.stereotype.Service
;
import
javax.annotation.Resource
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.stream.Collectors
;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 知识星球适配器接口
* @create 2023-10-22 10:18
*/
@Slf4j
@Service
public
class
ZSXQAdapter
implements
IZSXQAdapter
{
@Resource
private
IZSXQApi
zsxqApi
;
@Override
public
List
<
TopicsItemVO
>
queryTopics
()
{
try
{
ResponseDTO
responseDTO
=
zsxqApi
.
topics
();
RespData
respData
=
responseDTO
.
getRespData
();
List
<
TopicsItem
>
topics
=
respData
.
getTopics
();
List
<
TopicsItemVO
>
topicsItemVOList
=
new
ArrayList
<>();
for
(
TopicsItem
topicsItem
:
topics
)
{
TopicsItemVO
topicsItemVO
=
TopicsItemVO
.
builder
()
.
topicId
(
topicsItem
.
getTopicId
())
.
talk
(
topicsItem
.
getTalk
().
getText
())
.
showCommentsItems
(
topicsItem
.
getShowComments
()
!=
null
?
topicsItem
.
getShowComments
().
stream
()
.
map
(
showCommentsItem
->
{
TopicsItemVO
.
ShowCommentsItem
item
=
new
TopicsItemVO
.
ShowCommentsItem
();
item
.
setUserId
(
showCommentsItem
.
getOwner
().
getUserId
());
return
item
;
})
.
collect
(
Collectors
.
toList
())
:
new
ArrayList
<>())
.
build
();
topicsItemVOList
.
add
(
topicsItemVO
);
}
return
topicsItemVOList
;
}
catch
(
IOException
e
)
{
throw
new
RuntimeException
(
e
);
}
}
@Override
public
void
comment
(
long
topicId
,
String
content
)
{
zsxqApi
.
comment
(
topicId
,
content
);
}
}
xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/gateway/api/IZSXQApi.java
0 → 100644
浏览文件 @
c3ec1f2f
package
cn.bugstack.xfg.dev.tech.infrastructure.gateway.api
;
import
cn.bugstack.xfg.dev.tech.infrastructure.gateway.dto.ResponseDTO
;
import
java.io.IOException
;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 知识星球API接口
* @create 2023-10-22 09:47
*/
public
interface
IZSXQApi
{
/**
* 查询知识星球帖子内容
*
* @return 帖子数据
* @throws IOException 异常
*/
ResponseDTO
topics
()
throws
IOException
;
/**
* 回复帖子
*
* @param topicId 帖子ID
* @param content 回复内容
*/
void
comment
(
long
topicId
,
String
content
);
}
xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/gateway/api/impl/ZSXQApi.java
0 → 100644
浏览文件 @
c3ec1f2f
package
cn.bugstack.xfg.dev.tech.infrastructure.gateway.api.impl
;
import
cn.bugstack.xfg.dev.tech.infrastructure.gateway.api.IZSXQApi
;
import
cn.bugstack.xfg.dev.tech.infrastructure.gateway.dto.ResponseDTO
;
import
com.alibaba.fastjson2.JSON
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringEscapeUtils
;
import
org.apache.http.HttpEntity
;
import
org.apache.http.HttpResponse
;
import
org.apache.http.HttpStatus
;
import
org.apache.http.client.methods.CloseableHttpResponse
;
import
org.apache.http.client.methods.HttpGet
;
import
org.apache.http.client.methods.HttpPost
;
import
org.apache.http.entity.StringEntity
;
import
org.apache.http.impl.client.CloseableHttpClient
;
import
org.apache.http.impl.client.HttpClientBuilder
;
import
org.apache.http.util.EntityUtils
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.stereotype.Component
;
import
java.io.IOException
;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 知识星球Api实现
* @create 2023-10-22 09:53
*/
@Slf4j
@Component
public
class
ZSXQApi
implements
IZSXQApi
{
@Value
(
"${zsxq.config.id}"
)
private
String
id
;
@Value
(
"${zsxq.config.cookie}"
)
private
String
cookie
;
@Override
public
ResponseDTO
topics
()
throws
IOException
{
CloseableHttpClient
httpClient
=
HttpClientBuilder
.
create
().
build
();
HttpGet
get
=
new
HttpGet
(
"https://api.zsxq.com/v2/groups/"
+
id
+
"/topics?scope=all&count=20"
);
get
.
addHeader
(
"Accept-Encoding"
,
"deflate, gzip"
);
get
.
addHeader
(
"accept"
,
"application/json, text/plain, */*"
);
get
.
addHeader
(
"accept-language"
,
"zh-CN,zh;q=0.9,en;q=0.8"
);
get
.
addHeader
(
"authority"
,
"api.zsxq.com"
);
get
.
addHeader
(
"cookie"
,
cookie
);
get
.
addHeader
(
"dnt"
,
"1"
);
get
.
addHeader
(
"origin"
,
"https://wx.zsxq.com"
);
get
.
addHeader
(
"referer"
,
"https://wx.zsxq.com/"
);
get
.
addHeader
(
"sec-ch-ua"
,
"\"Chromium\";v=\"118\", \"Google Chrome\";v=\"118\", \"Not=A?Brand\";v=\"99\""
);
get
.
addHeader
(
"sec-ch-ua-mobile"
,
"?0"
);
get
.
addHeader
(
"sec-ch-ua-platform"
,
"\"macOS\""
);
get
.
addHeader
(
"sec-fetch-dest"
,
"empty"
);
get
.
addHeader
(
"sec-fetch-mode"
,
"cors"
);
get
.
addHeader
(
"sec-fetch-site"
,
"same-site"
);
get
.
addHeader
(
"user-agent"
,
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36"
);
get
.
addHeader
(
"x-request-id"
,
"372177b46-4e7d-9373-d891-98a22adaeb7"
);
get
.
addHeader
(
"x-signature"
,
"32b39b5d1af5995e3b5022e58a8d8f23cd427434"
);
get
.
addHeader
(
"x-timestamp"
,
"1697249698"
);
get
.
addHeader
(
"x-version"
,
"2.45.0"
);
CloseableHttpResponse
response
=
httpClient
.
execute
(
get
);
if
(
response
.
getStatusLine
().
getStatusCode
()
==
HttpStatus
.
SC_OK
)
{
String
jsonStr
=
EntityUtils
.
toString
(
response
.
getEntity
());
return
JSON
.
parseObject
(
jsonStr
,
ResponseDTO
.
class
);
}
else
{
throw
new
RuntimeException
(
"Err Code is "
+
response
.
getStatusLine
().
getStatusCode
());
}
}
@Override
public
void
comment
(
long
topicId
,
String
content
)
{
CloseableHttpClient
httpClient
=
HttpClientBuilder
.
create
().
build
();
HttpPost
httpPost
=
new
HttpPost
(
"https://api.zsxq.com/v2/topics/"
+
topicId
+
"/comments"
);
httpPost
.
setHeader
(
"Accept-Encoding"
,
"deflate, gzip"
);
httpPost
.
setHeader
(
"accept"
,
"application/json, text/plain, */*"
);
httpPost
.
setHeader
(
"accept-language"
,
"zh-CN,zh;q=0.9,en;q=0.8"
);
httpPost
.
setHeader
(
"authority"
,
"api.zsxq.com"
);
httpPost
.
setHeader
(
"content-type"
,
"application/json"
);
httpPost
.
setHeader
(
"cookie"
,
cookie
);
httpPost
.
setHeader
(
"dnt"
,
"1"
);
httpPost
.
setHeader
(
"origin"
,
"https://wx.zsxq.com"
);
httpPost
.
setHeader
(
"referer"
,
"https://wx.zsxq.com/"
);
httpPost
.
setHeader
(
"sec-ch-ua"
,
"\"Chromium\";v=\"118\", \"Google Chrome\";v=\"118\", \"Not=A?Brand\";v=\"99\""
);
httpPost
.
setHeader
(
"sec-ch-ua-mobile"
,
"?0"
);
httpPost
.
setHeader
(
"sec-ch-ua-platform"
,
"\"macOS\""
);
httpPost
.
setHeader
(
"sec-fetch-dest"
,
"empty"
);
httpPost
.
setHeader
(
"sec-fetch-mode"
,
"cors"
);
httpPost
.
setHeader
(
"sec-fetch-site"
,
"same-site"
);
httpPost
.
setHeader
(
"user-agent"
,
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36"
);
httpPost
.
setHeader
(
"x-request-id"
,
"162ae5f17-2123-4ae3-67df-8b9775414e0"
);
httpPost
.
setHeader
(
"x-signature"
,
"698895e3ec4e651128b3d16755546bd2bc659687"
);
httpPost
.
setHeader
(
"x-timestamp"
,
"1697257286"
);
httpPost
.
setHeader
(
"x-version"
,
"2.45.0"
);
String
requestBody
=
"{\"req_data\":{\"text\":\""
+
StringEscapeUtils
.
escapeJava
(
content
)
+
"\",\"image_ids\":[],\"mentioned_user_ids\":[]}}"
;
try
{
httpPost
.
setEntity
(
new
StringEntity
(
requestBody
));
HttpResponse
response
=
httpClient
.
execute
(
httpPost
);
HttpEntity
entity
=
response
.
getEntity
();
String
responseString
=
EntityUtils
.
toString
(
entity
);
log
.
info
(
"回贴结果 {}"
,
responseString
);
httpClient
.
close
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
}
\ No newline at end of file
xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/gateway/dto/Group.java
0 → 100644
浏览文件 @
c3ec1f2f
package
cn.bugstack.xfg.dev.tech.infrastructure.gateway.dto
;
import
com.google.gson.annotations.SerializedName
;
import
lombok.Data
;
@Data
public
class
Group
{
@SerializedName
(
"group_id"
)
private
long
groupId
;
@SerializedName
(
"background_url"
)
private
String
backgroundUrl
;
@SerializedName
(
"name"
)
private
String
name
;
@SerializedName
(
"type"
)
private
String
type
;
}
\ No newline at end of file
xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/gateway/dto/Owner.java
0 → 100644
浏览文件 @
c3ec1f2f
package
cn.bugstack.xfg.dev.tech.infrastructure.gateway.dto
;
import
com.google.gson.annotations.SerializedName
;
import
lombok.Data
;
@Data
public
class
Owner
{
@SerializedName
(
"avatar_url"
)
private
String
avatarUrl
;
@SerializedName
(
"user_id"
)
private
long
userId
;
@SerializedName
(
"name"
)
private
String
name
;
@SerializedName
(
"location"
)
private
String
location
;
}
\ No newline at end of file
xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/gateway/dto/RespData.java
0 → 100644
浏览文件 @
c3ec1f2f
package
cn.bugstack.xfg.dev.tech.infrastructure.gateway.dto
;
import
com.google.gson.annotations.SerializedName
;
import
lombok.Data
;
import
java.util.List
;
@Data
public
class
RespData
{
@SerializedName
(
"topics"
)
private
List
<
TopicsItem
>
topics
;
}
\ No newline at end of file
xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/gateway/dto/ResponseDTO.java
0 → 100644
浏览文件 @
c3ec1f2f
package
cn.bugstack.xfg.dev.tech.infrastructure.gateway.dto
;
import
com.google.gson.annotations.SerializedName
;
import
lombok.Data
;
@Data
public
class
ResponseDTO
{
@SerializedName
(
"resp_data"
)
private
RespData
respData
;
@SerializedName
(
"succeeded"
)
private
boolean
succeeded
;
}
\ No newline at end of file
xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/gateway/dto/ShowCommentsItem.java
0 → 100644
浏览文件 @
c3ec1f2f
package
cn.bugstack.xfg.dev.tech.infrastructure.gateway.dto
;
import
com.google.gson.annotations.SerializedName
;
import
lombok.Data
;
@Data
public
class
ShowCommentsItem
{
@SerializedName
(
"owner"
)
private
Owner
owner
;
@SerializedName
(
"likes_count"
)
private
int
likesCount
;
@SerializedName
(
"create_time"
)
private
String
createTime
;
@SerializedName
(
"rewards_count"
)
private
int
rewardsCount
;
@SerializedName
(
"sticky"
)
private
boolean
sticky
;
@SerializedName
(
"text"
)
private
String
text
;
@SerializedName
(
"comment_id"
)
private
long
commentId
;
}
\ No newline at end of file
xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/gateway/dto/Talk.java
0 → 100644
浏览文件 @
c3ec1f2f
package
cn.bugstack.xfg.dev.tech.infrastructure.gateway.dto
;
import
com.google.gson.annotations.SerializedName
;
import
lombok.Data
;
@Data
public
class
Talk
{
@SerializedName
(
"owner"
)
private
Owner
owner
;
@SerializedName
(
"text"
)
private
String
text
;
}
\ No newline at end of file
xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/gateway/dto/TopicsItem.java
0 → 100644
浏览文件 @
c3ec1f2f
package
cn.bugstack.xfg.dev.tech.infrastructure.gateway.dto
;
import
com.google.gson.annotations.SerializedName
;
import
lombok.Data
;
import
java.util.List
;
@Data
public
class
TopicsItem
{
@SerializedName
(
"reading_count"
)
private
int
readingCount
;
@SerializedName
(
"create_time"
)
private
String
createTime
;
@SerializedName
(
"user_specific"
)
private
UserSpecific
userSpecific
;
@SerializedName
(
"rewards_count"
)
private
int
rewardsCount
;
@SerializedName
(
"show_comments"
)
private
List
<
ShowCommentsItem
>
showComments
;
@SerializedName
(
"type"
)
private
String
type
;
@SerializedName
(
"digested"
)
private
boolean
digested
;
@SerializedName
(
"likes_count"
)
private
int
likesCount
;
@SerializedName
(
"comments_count"
)
private
int
commentsCount
;
@SerializedName
(
"sticky"
)
private
boolean
sticky
;
@SerializedName
(
"talk"
)
private
Talk
talk
;
@SerializedName
(
"topic_id"
)
private
long
topicId
;
@SerializedName
(
"readers_count"
)
private
int
readersCount
;
@SerializedName
(
"group"
)
private
Group
group
;
}
\ No newline at end of file
xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/gateway/dto/UserSpecific.java
0 → 100644
浏览文件 @
c3ec1f2f
package
cn.bugstack.xfg.dev.tech.infrastructure.gateway.dto
;
import
com.google.gson.annotations.SerializedName
;
import
lombok.Data
;
@Data
public
class
UserSpecific
{
@SerializedName
(
"subscribed"
)
private
boolean
subscribed
;
@SerializedName
(
"liked"
)
private
boolean
liked
;
}
\ No newline at end of file
xfg-dev-tech-trigger/pom.xml
0 → 100644
浏览文件 @
c3ec1f2f
<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<modelVersion>
4.0.0
</modelVersion>
<parent>
<groupId>
cn.bugstack
</groupId>
<artifactId>
xfg-dev-tech-mock
</artifactId>
<version>
1.0-SNAPSHOT
</version>
</parent>
<artifactId>
xfg-dev-tech-trigger
</artifactId>
<dependencies>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-web
</artifactId>
</dependency>
<dependency>
<groupId>
com.alibaba
</groupId>
<artifactId>
fastjson
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework
</groupId>
<artifactId>
spring-tx
</artifactId>
</dependency>
<dependency>
<groupId>
org.apache.commons
</groupId>
<artifactId>
commons-lang3
</artifactId>
</dependency>
<dependency>
<groupId>
org.projectlombok
</groupId>
<artifactId>
lombok
</artifactId>
<version>
1.18.26
</version>
</dependency>
<dependency>
<groupId>
org.springframework
</groupId>
<artifactId>
spring-context
</artifactId>
</dependency>
<dependency>
<groupId>
cn.bugstack
</groupId>
<artifactId>
xfg-dev-tech-domain
</artifactId>
<version>
1.0-SNAPSHOT
</version>
<scope>
compile
</scope>
</dependency>
</dependencies>
<build>
<finalName>
xfg-dev-tech-trigger
</finalName>
<plugins>
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-compiler-plugin
</artifactId>
<configuration>
<source>
${java.version}
</source>
<target>
${java.version}
</target>
<compilerVersion>
${java.version}
</compilerVersion>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
xfg-dev-tech-trigger/src/main/java/cn/bugstack/xfg/dev/tech/job/ReplyJob.java
0 → 100644
浏览文件 @
c3ec1f2f
package
cn.bugstack.xfg.dev.tech.job
;
import
cn.bugstack.xfg.dev.tech.domain.zsxq.service.IAiReply
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.scheduling.annotation.Scheduled
;
import
org.springframework.stereotype.Component
;
import
javax.annotation.Resource
;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 回帖JOB
* @create 2023-10-22 11:02
*/
@Slf4j
@Component
()
public
class
ReplyJob
{
@Resource
private
IAiReply
aiReply
;
@Scheduled
(
cron
=
"0/10 * * * * ?"
)
public
void
exec
()
throws
Exception
{
aiReply
.
doAiReply
();
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录