Skip to content
5 changes: 2 additions & 3 deletions prisma/hyperdrive.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,7 @@ model sr_platform_bind {
}

model sr_bookmark_share {
id Int @id @default(autoincrement())
uuid String @unique @default(dbgenerated("gen_random_uuid()"))
id Int @id @default(autoincrement())

share_code String @default("")
user_id Int @default(0)
Expand All @@ -264,8 +263,8 @@ model sr_bookmark_share {
is_enable Boolean @default(true)
created_at DateTime @default(now())

@@unique([share_code])
@@unique([bookmark_id, user_id])
@@index([share_code])
}

model sr_bookmark_import {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
Warnings:

- You are about to drop the column `uuid` on the `sr_bookmark_share` table. All the data in the column will be lost.

*/
-- DropIndex
DROP INDEX "sr_bookmark_share_share_code_key";

-- DropIndex
DROP INDEX "sr_bookmark_share_uuid_key";

-- AlterTable
ALTER TABLE "sr_bookmark_share" DROP COLUMN "uuid";

-- CreateIndex
CREATE INDEX "sr_bookmark_share_share_code_idx" ON "sr_bookmark_share"("share_code");
18 changes: 10 additions & 8 deletions src/domain/bookmark.ts
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,10 @@ export class BookmarkService {
return await this.bookmarkRepo.getUserBookmarkByUuidWithDetail(uuid)
}

public async getBookmarkShareByBookmarkId(bmId: number, userId: number) {
return await this.bookmarkRepo.getBookmarkShareByBookmarkId(bmId, userId)
}

public async getUserBookmarkWithDetail(userId: number, bmId: number) {
return (await this.bookmarkRepo.getUserBookmarkWithDetail(bmId, userId)) ?? null
}
Expand Down Expand Up @@ -908,19 +912,17 @@ export class BookmarkService {

public async getBookmarkTitleContent(
ctx: ContextManager,
bmId?: number,
shareCode?: string,
cbId?: number,
title?: string,
content?: string
params: { bmId?: number; shareCode?: string; cbId?: number; title?: string; content?: string; bmUId?: string }
): Promise<{ title: string; content: string; bmId: number }> {
if (!bmId && !shareCode && !cbId && !title && !content) throw ErrorParam()
const { bmId, shareCode, cbId, title, content, bmUId } = params

if (!bmId && !shareCode && !cbId && title && content) {
const emptyId = !bmId && !shareCode && !cbId && !bmUId
if (emptyId && !title && !content) throw ErrorParam()
if (emptyId && title && content) {
return { title, content, bmId: 0 }
}

const bookmarkId = await this.getBookmarkId(ctx, { bmId, shareCode, cbId })
const bookmarkId = await this.getBookmarkId(ctx, { bmId, shareCode, cbId, bmUId })
if (!bookmarkId || bookmarkId < 1) throw ErrorParam()

const bookmark = await this.getBookmarkById(bookmarkId)
Expand Down
14 changes: 14 additions & 0 deletions src/domain/orchestrator/share.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,18 @@ export class ShareOrchestrator {
if (!userBm) return { mark_list: [], user_list: [] }
return await this.markService.getBookmarkMarkList(ctx, { id: userBm.id, isShowMarks: share.show_comment && share.show_line })
}

public async getBookmarkShareMarkListByUid(ctx: ContextManager, bmUId: string): Promise<markDetail> {
const empty = { mark_list: [], user_list: [] }
const ub = await this.bookmarkService.getUserBookmarkByUuidWithDetail(bmUId)
if (!ub) return empty

if (ub.user_id !== ctx.getUserId()) {
const share = await this.bookmarkService.getBookmarkShareByBookmarkId(ub.bookmark_id, ub.user_id)
const allowed = !share || (share.is_enable && share.allow_comment && share.allow_line)
if (!allowed) return empty
}

return await this.markService.getBookmarkMarkList(ctx, { id: ub.id, isShowMarks: true })
}
}
47 changes: 34 additions & 13 deletions src/domain/share.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ export interface updateBookmarkShareReq {
show_comment_line: boolean
show_userinfo: boolean
allow_action: boolean
bookmark_id: number
bookmark_id?: number
bookmark_uid?: string
}

export interface getBookmarkByShareResp {
Expand Down Expand Up @@ -51,13 +52,21 @@ export interface getBookmarkByShareResp {
export class ShareService {
constructor(@inject(BookmarkRepo) private bookmarkRepo: BookmarkRepo) {}

public async checkBookmarkShareExists(ctx: ContextManager, bmId: number): Promise<createBookmarkShareResp> {
const userId = ctx.getUserId()

bmId = ctx.hashIds.decodeId(bmId)
if (bmId < 1) throw ErrorParam()
public async checkBookmarkShareExists(ctx: ContextManager, params: { bmId?: number; bmUId?: string }): Promise<createBookmarkShareResp> {
let bmId: number
let ownerUserId: number
if (params.bmUId) {
const ub = await this.bookmarkRepo.getUserBookmarkByUuid(params.bmUId)
if (!ub) throw ErrorParam()
bmId = ub.bookmark_id
ownerUserId = ub.user_id
} else {
bmId = ctx.hashIds.decodeId(params.bmId ?? 0)
if (bmId < 1) throw ErrorParam()
ownerUserId = ctx.getUserId()
}

const res = await this.bookmarkRepo.getBookmarkShareByBookmarkId(bmId, userId)
const res = await this.bookmarkRepo.getBookmarkShareByBookmarkId(bmId, ownerUserId)
const isEnable = res && res.is_enable
return {
allow_action: isEnable ? res.allow_comment : false,
Expand All @@ -78,8 +87,16 @@ export class ShareService {
public async updateBookmarkShare(ctx: ContextManager, req: updateBookmarkShareReq): Promise<createBookmarkShareResp> {
const userId = ctx.getUserId()

const bmId = ctx.hashIds.decodeId(req.bookmark_id)
if (bmId < 1 || !bmId) throw ErrorParam()
let bmId: number
const viaUid = !!req.bookmark_uid
if (req.bookmark_uid) {
const ub = await this.bookmarkRepo.getUserBookmarkByUId(req.bookmark_uid, userId)
if (!ub) throw BookmarkNotFoundError()
bmId = ub.bookmark_id
} else {
bmId = ctx.hashIds.decodeId(req.bookmark_id ?? 0)
if (bmId < 1 || !bmId) throw ErrorParam()
}

const bookmark = await this.bookmarkRepo.getUserBookmark(bmId, userId)
if (!bookmark) throw BookmarkNotFoundError()
Expand All @@ -93,14 +110,18 @@ export class ShareService {
res = await this.bookmarkRepo.updateBookmarkShare(bmId, userId, req.show_comment_line, req.show_userinfo, req.allow_action)
} catch (err) {
console.log(`update bookmark share failed: ${err}`)
return BookmarkNotFoundError()
// 必须抛出:之前 return 的错误对象会被丢弃,导致 res 为 undefined,下方取 res.allow_comment 抛 500
throw BookmarkNotFoundError()
}
}
const createShare = async () => {
for (let i = 0; i < 3; i++) {
const timeCode = ctx.hashIds.generateTimeCode()
const hash = (await hashMD5(`${bmId}-${userId}-${Date.now()}`)).slice(0, 7)
const code = `${timeCode}${hash}`
let code = ''
if (!viaUid) {
const timeCode = ctx.hashIds.generateTimeCode()
const hash = (await hashMD5(`${bmId}-${userId}-${Date.now()}`)).slice(0, 7)
code = `${timeCode}${hash}`
}
const shareRes = await this.bookmarkRepo.createBookmarkShare(code, userId, bmId, req.show_comment_line, req.show_userinfo, req.allow_action)
if (!shareRes) throw ServerError()
res = shareRes
Expand Down
25 changes: 21 additions & 4 deletions src/handler/http/aigcController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { convertToGeminiContent } from '../../utils/conversation'

type SummaryRequest = {
bm_id?: number
bookmark_uid?: string
share_code?: string
cb_id?: number
collection_code: string
Expand All @@ -21,6 +22,7 @@ type SummaryRequest = {

type CompletionsRequest = {
bm_id?: number
bookmark_uid?: string
share_code?: string
cb_id?: number
collection_code?: string
Expand Down Expand Up @@ -52,11 +54,12 @@ export class AigcController {
ctx.set('country', request.cf?.country || '')
ctx.set('continent', request.cf?.continent || '')

if (!req.force && req.bm_id) {
if (!req.force && (req.bm_id || req.bookmark_uid)) {
const summary = await this.bookmarkService.getUserBookmarkSummary(ctx, {
bmId: req.bm_id,
shareCode: req.share_code,
cbId: req.cb_id
cbId: req.cb_id,
bmUId: req.bookmark_uid
})

if (summary) {
Expand All @@ -66,7 +69,14 @@ export class AigcController {
}
}

const { title, content, bmId } = await this.bookmarkService.getBookmarkTitleContent(ctx, req.bm_id, req.share_code, req.cb_id, 'no title', req.raw_content)
const { title, content, bmId } = await this.bookmarkService.getBookmarkTitleContent(ctx, {
bmId: req.bm_id,
shareCode: req.share_code,
cbId: req.cb_id,
title: 'no title',
content: req.raw_content,
bmUId: req.bookmark_uid
})
ctx.execution.waitUntil(
aiSvc.bookmarkSummary(ctx, content, writable, async result => {
bmId > 0 && (await this.bookmarkService.saveSummary(ctx, bmId, result.provider, result.response, result.model))
Expand All @@ -85,7 +95,14 @@ export class AigcController {

const [user, { title, content, bmId }] = await Promise.all([
this.userService.getUserInfo(ctx),
this.bookmarkService.getBookmarkTitleContent(ctx, req.bm_id, req.share_code, req.cb_id, req.title, req.raw_content)
this.bookmarkService.getBookmarkTitleContent(ctx, {
bmId: req.bm_id,
shareCode: req.share_code,
cbId: req.cb_id,
title: req.title,
content: req.raw_content,
bmUId: req.bookmark_uid
})
])

// 设置上下文
Expand Down
14 changes: 8 additions & 6 deletions src/handler/http/shareController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ export class ShareController {
*/
@Get('/exists')
public async existsShare(ctx: ContextManager, request: Request) {
const req = await RequestUtils.query<{ bookmark_id: number }>(request)
if (!req) return Failed(ErrorParam())
const req = await RequestUtils.query<{ bookmark_id?: number; bookmark_uid?: string }>(request)
if (!req || (!req.bookmark_id && !req.bookmark_uid)) return Failed(ErrorParam())

const res = await this.shareService.checkBookmarkShareExists(ctx, req.bookmark_id)
const res = await this.shareService.checkBookmarkShareExists(ctx, { bmId: req.bookmark_id, bmUId: req.bookmark_uid })
return Successed(res)
}

Expand All @@ -78,10 +78,12 @@ export class ShareController {
*/
@Get('/mark_list')
public async getMarkList(ctx: ContextManager, request: Request) {
const req = await RequestUtils.query<{ share_code: string }>(request)
if (!req) return Failed(ErrorParam())
const req = await RequestUtils.query<{ share_code?: string; bookmark_uid?: string }>(request)
if (!req || (!req.share_code && !req.bookmark_uid)) return Failed(ErrorParam())

const markList = await this.shareOrchestrator.getBookmarkShareMarkList(ctx, req.share_code)
const markList = req.bookmark_uid
? await this.shareOrchestrator.getBookmarkShareMarkListByUid(ctx, req.bookmark_uid)
: await this.shareOrchestrator.getBookmarkShareMarkList(ctx, req.share_code!)
return Successed(markList)
}
}
3 changes: 2 additions & 1 deletion src/infra/repository/dbBookmark.ts
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,8 @@ export class BookmarkRepo {
})
} catch (err) {
console.log(`create bookmark share failed: ${err}`)
return CreateBookmarkShareUniqueFail()
// 失败要抛出,让上层走错误响应;之前 return 错误对象会被 createShare 当成 share 行,导致返回畸形 200
throw CreateBookmarkShareUniqueFail()
}
}

Expand Down
Loading