返回 AiToEarn
index.ts
1 /**
2 * 抖音平台交互实现
3 *
4 * 实现策略:
5 * - 点赞、收藏、评论:统一使用自动化方案(避免 API 风控)
6 * - 首页列表:使用 API 方案获取推荐作品
7 * - 评论:不支持二级评论
8 *
9 * 目录结构:
10 * douyin/
11 * ├── index.ts # 主类和导出入口
12 * ├── types.ts # 抖音特定类型定义
13 * └── homeFeed.ts # 首页列表功能模块
14 */
15
16 import type {
17 CommentListParams,
18 CommentListResult,
19 CommentParams,
20 CommentResult,
21 DirectMessageParams,
22 DirectMessageResult,
23 FavoriteResult,
24 GetWorkDetailParams,
25 GetWorkDetailResult,
26 HomeFeedListParams,
27 HomeFeedListResult,
28 IPlatformInteraction,
29 LikeResult,
30 SubCommentListParams,
31 } from '../types'
32 import type { DouyinDirectMessageResponse, DouyinInteractionResponse } from './types'
33 import { PlatType } from '@/app/config/platConfig'
34 import { getHomeFeedList, homeFeedCursor } from './homeFeed'
35 import { getWorkDetail, getWorkDetailFromListItem } from './workDetail'
36
37 /**
38 * 抖音平台交互类
39 */
40 class DouyinPlatformInteraction implements IPlatformInteraction {
41 readonly platformType = PlatType.Douyin
42
43 /**
44 * 检查插件是否可用
45 */
46 private checkPlugin(): void {
47 if (!window.AIToEarnPlugin) {
48 throw new Error('插件未安装或未就绪')
49 }
50 }
51
52 /**
53 * 重置首页列表游标缓存
54 * 用于刷新列表时清除缓存
55 */
56 resetHomeFeedCursor(): void {
57 homeFeedCursor.reset()
58 }
59
60 /**
61 * 点赞/取消点赞作品(自动化方案)
62 * 使用自动化方案避免 API 风控
63 * @param workId 作品ID
64 * @param isLike true=点赞,false=取消点赞
65 */
66 async likeWork(workId: string, isLike: boolean): Promise<LikeResult> {
67 this.checkPlugin()
68
69 if (window.AIToEarnPlugin!.unifiedInteraction) {
70 const response = await window.AIToEarnPlugin!.unifiedInteraction({
71 platform: 'douyin',
72 action: 'like',
73 workLink: `https://www.douyin.com/video/${workId}`,
74 targetState: isLike,
75 needScreenshot: true,
76 })
77 return {
78 success: response.success,
79 message: response.message || response.error,
80 screenshot: response.screenshot,
81 rawData: response,
82 }
83 }
84
85 const response = (await window.AIToEarnPlugin!.douyinInteraction({
86 action: 'like',
87 workId,
88 targetState: isLike,
89 })) as DouyinInteractionResponse
90
91 return {
92 success: response.success,
93 message: response.message || response.error,
94 rawData: response,
95 }
96 }
97
98 /**
99 * 评论作品(自动化方案)
100 * 使用自动化方案避免 API 风控
101 * 注意:不支持二级评论
102 * @param params 评论参数
103 */
104 async commentWork(params: CommentParams): Promise<CommentResult> {
105 this.checkPlugin()
106
107 // 不支持二级评论
108 if (params.replyToCommentId) {
109 return {
110 success: false,
111 message: '抖音评论暂不支持二级评论',
112 }
113 }
114
115 if (window.AIToEarnPlugin!.unifiedInteraction) {
116 const response = await window.AIToEarnPlugin!.unifiedInteraction({
117 platform: 'douyin',
118 action: 'comment',
119 workLink: `https://www.douyin.com/video/${params.workId}`,
120 targetState: true,
121 content: params.content,
122 needScreenshot: true,
123 })
124 return {
125 success: response.success,
126 message: response.message || response.error,
127 screenshot: response.screenshot,
128 needHumanAssist: response.needHumanAssist,
129 verificationReason: response.verificationReason,
130 rawData: response,
131 }
132 }
133
134 const response = (await window.AIToEarnPlugin!.douyinInteraction({
135 action: 'comment',
136 workId: params.workId,
137 targetState: true,
138 content: params.content,
139 })) as DouyinInteractionResponse
140
141 return {
142 success: response.success,
143 message: response.message || response.error,
144 rawData: response,
145 }
146 }
147
148 /**
149 * 收藏/取消收藏作品(自动化方案)
150 * 使用自动化方案避免 API 风控
151 * @param workId 作品ID
152 * @param isFavorite true=收藏,false=取消收藏
153 */
154 async favoriteWork(workId: string, isFavorite: boolean): Promise<FavoriteResult> {
155 this.checkPlugin()
156
157 if (window.AIToEarnPlugin!.unifiedInteraction) {
158 const response = await window.AIToEarnPlugin!.unifiedInteraction({
159 platform: 'douyin',
160 action: 'favorite',
161 workLink: `https://www.douyin.com/video/${workId}`,
162 targetState: isFavorite,
163 needScreenshot: true,
164 })
165 return {
166 success: response.success,
167 message: response.message || response.error,
168 screenshot: response.screenshot,
169 rawData: response,
170 }
171 }
172
173 const response = (await window.AIToEarnPlugin!.douyinInteraction({
174 action: 'favorite',
175 workId,
176 targetState: isFavorite,
177 })) as DouyinInteractionResponse
178
179 return {
180 success: response.success,
181 message: response.message || response.error,
182 rawData: response,
183 }
184 }
185
186 /**
187 * 发送私信(自动化方案)
188 * 根据作品ID或作者链接发送私信
189 * @param params 私信参数
190 */
191 async sendDirectMessage(params: DirectMessageParams): Promise<DirectMessageResult> {
192 this.checkPlugin()
193
194 // 验证参数
195 if (!params.workId && !params.authorUrl) {
196 return {
197 success: false,
198 message: '必须提供作品ID或作者链接',
199 }
200 }
201
202 if (!params.content) {
203 return {
204 success: false,
205 message: '私信内容不能为空',
206 }
207 }
208
209 const response = (await window.AIToEarnPlugin!.douyinDirectMessage({
210 workId: params.workId,
211 authorUrl: params.authorUrl,
212 content: params.content,
213 })) as DouyinDirectMessageResponse
214
215 return {
216 success: response.success,
217 message: response.message || response.error,
218 rawData: response,
219 }
220 }
221
222 /**
223 * 获取首页作品列表
224 * @param params 分页参数
225 */
226 async getHomeFeedList(params: HomeFeedListParams): Promise<HomeFeedListResult> {
227 return getHomeFeedList(params)
228 }
229
230 /**
231 * 获取作品详情
232 * 抖音直接从list的item数据获取详情,不需要额外请求API
233 * @param params 详情请求参数
234 */
235 async getWorkDetail(params: GetWorkDetailParams): Promise<GetWorkDetailResult> {
236 return getWorkDetail(params)
237 }
238
239 /**
240 * 从列表项获取作品详情
241 * 这是抖音特有的方法,直接从 HomeFeedItem.origin 获取详情
242 * @param listItemOrigin HomeFeedItem.origin 原始数据
243 */
244 getWorkDetailFromListItem(listItemOrigin: unknown): GetWorkDetailResult {
245 return getWorkDetailFromListItem(listItemOrigin)
246 }
247
248 /**
249 * 获取评论列表
250 * TODO: 待实现抖音评论列表功能
251 * @param params 评论列表请求参数
252 */
253 async getCommentList(params: CommentListParams): Promise<CommentListResult> {
254 // TODO: 实现抖音评论列表
255 return {
256 success: false,
257 message: '抖音评论列表功能开发中',
258 comments: [],
259 cursor: '',
260 hasMore: false,
261 }
262 }
263
264 /**
265 * 获取子评论列表(查看更多回复)
266 * TODO: 待实现抖音子评论列表功能
267 * @param params 子评论列表请求参数
268 */
269 async getSubCommentList(params: SubCommentListParams): Promise<CommentListResult> {
270 // TODO: 实现抖音子评论列表
271 return {
272 success: false,
273 message: '抖音子评论列表功能开发中',
274 comments: [],
275 cursor: '',
276 hasMore: false,
277 }
278 }
279 }
280
281 /**
282 * 抖音平台交互实例
283 */
284 export const douyinInteraction = new DouyinPlatformInteraction()
285
286 // 导出类型(方便外部使用)
287 export type { DouyinHomeFeedItem, DouyinHomeFeedResponse } from './types'
288
289 // 导出工具方法
290 export { getWorkDetailFromListItem } from './workDetail'
291
291 lines TYPESCRIPT