11import { H3Event , parseCookies } from 'h3' ;
2- import { readFileSync , writeFileSync } from 'node:fs' ;
3- import fs from 'node:fs' ;
4- import path from 'node:path' ;
5- import { root } from '~/server/config' ;
2+ import { getMpCookie , setMpCookie } from '~/server/kv/cookie' ;
3+ import { getMpToken , setMpToken } from '~/server/kv/token' ;
64
75// 表示一条 set-cookie 记录的解析结果
8- type TCookie = Record < string , string | number > ;
6+ export type CookieEntity = Record < string , string | number > ;
97
10- // 公众号对应的 cookie 对象 (已解析)
8+ // 公众号所有的 set- cookie 解析结果
119export class AccountCookie {
12- private readonly _cookie : TCookie [ ] ;
10+ private readonly _cookie : CookieEntity [ ] ;
1311
12+ /**
13+ * @param cookies response.headers.getSetCookie() 的结果,是一个字符串数组
14+ */
1415 constructor ( cookies : string [ ] ) {
1516 this . _cookie = this . parse ( cookies ) ;
1617 }
@@ -19,11 +20,11 @@ export class AccountCookie {
1920 return this . stringify ( this . _cookie ) ;
2021 }
2122
22- public toJSON ( ) : TCookie [ ] {
23+ public toJSON ( ) : CookieEntity [ ] {
2324 return this . _cookie ;
2425 }
2526
26- public get ( name : string ) : TCookie | undefined {
27+ public get ( name : string ) : CookieEntity | undefined {
2728 return this . _cookie . find ( cookie => cookie . name === name ) ;
2829 }
2930
@@ -33,13 +34,13 @@ export class AccountCookie {
3334 return false ;
3435 }
3536
36- private parse ( cookies : string [ ] ) : TCookie [ ] {
37- // Use a Map to store cookies by name, ensuring the last occurrence overwrites duplicates
38- const cookieMap = new Map < string , TCookie > ( ) ;
37+ private parse ( cookies : string [ ] ) : CookieEntity [ ] {
38+ // key 为 cookie 的 name
39+ const cookieMap = new Map < string , CookieEntity > ( ) ;
3940
4041 for ( const cookie of cookies ) {
41- const cookieObj : TCookie = { } ;
42- // 分割cookie字符串为各个属性
42+ const cookieObj : CookieEntity = { } ;
43+ // 分割 cookie 字符串为各个属性
4344 const parts = cookie . split ( ';' ) . map ( str => str . trim ( ) ) ;
4445
4546 // 第一个部分是name=value
@@ -79,11 +80,10 @@ export class AccountCookie {
7980 }
8081 }
8182
82- // Convert Map values to array
8383 return Array . from ( cookieMap . values ( ) ) ;
8484 }
8585
86- private stringify ( parsedCookie : TCookie [ ] ) : string {
86+ private stringify ( parsedCookie : CookieEntity [ ] ) : string {
8787 return parsedCookie
8888 . filter ( cookie => cookie . value && cookie . value !== 'EXPIRED' )
8989 . map ( cookie => `${ cookie . name } =${ cookie . value } ` )
@@ -94,17 +94,7 @@ export class AccountCookie {
9494// 所有用户的 cookie 仓库
9595class CookieStore {
9696 store ! : Map < string , AccountCookie > ;
97- private readonly cookieDumpFilePath : string ;
98-
9997 token ! : Map < string , string > ;
100- private readonly tokenDumpFilePath : string ;
101-
102- constructor ( ) {
103- this . cookieDumpFilePath = path . resolve ( root , '.data/cookies.json' ) ;
104- this . tokenDumpFilePath = path . resolve ( root , '.data/tokens.json' ) ;
105-
106- this . load ( ) ;
107- }
10898
10999 /**
110100 * 检索用户的cookie
@@ -126,7 +116,7 @@ class CookieStore {
126116 */
127117 setCookie ( authKey : string , cookie : string [ ] ) {
128118 this . store . set ( authKey , new AccountCookie ( cookie ) ) ;
129- this . dumpCookies ( ) ;
119+ this . dumpCookies ( ) . catch ( e => console . error ( e ) ) ;
130120 }
131121
132122 /**
@@ -137,23 +127,23 @@ class CookieStore {
137127 updateCookie ( authKey : string , newCookies : string [ ] ) {
138128 // Parse new cookies
139129 const newAccountCookie = new AccountCookie ( newCookies ) ;
140- const newCookieMap = new Map < string , TCookie > (
130+ const newCookieMap = new Map < string , CookieEntity > (
141131 newAccountCookie . toJSON ( ) . map ( cookie => [ cookie . name as string , cookie ] )
142132 ) ;
143133
144134 // Get existing cookies, if any
145135 const existingCookieObj = this . store . get ( authKey ) ;
146- let mergedCookies : TCookie [ ] = [ ] ;
136+ let mergedCookies : CookieEntity [ ] ;
147137
148138 if ( existingCookieObj ) {
149139 // Merge existing cookies with new ones, new cookies override duplicates
150140 const existingCookies = existingCookieObj . toJSON ( ) ;
151- const existingCookieMap = new Map < string , TCookie > (
141+ const existingCookieMap = new Map < string , CookieEntity > (
152142 existingCookies . map ( cookie => [ cookie . name as string , cookie ] )
153143 ) ;
154144
155145 // Keep all existing cookies, overwrite with new ones if they exist
156- mergedCookies = Array . from ( existingCookieMap . entries ( ) ) . reduce < TCookie [ ] > ( ( acc , [ name , cookie ] ) => {
146+ mergedCookies = Array . from ( existingCookieMap . entries ( ) ) . reduce < CookieEntity [ ] > ( ( acc , [ name , cookie ] ) => {
157147 if ( newCookieMap . has ( name ) ) {
158148 // Use new cookie if it exists
159149 acc . push ( newCookieMap . get ( name ) ! ) ;
@@ -185,7 +175,7 @@ class CookieStore {
185175
186176 // Update store with merged cookies
187177 this . store . set ( authKey , new AccountCookie ( mergedCookieStrings ) ) ;
188- this . dumpCookies ( ) ;
178+ this . dumpCookies ( ) . catch ( e => console . error ( e ) ) ;
189179 }
190180
191181 /**
@@ -203,38 +193,36 @@ class CookieStore {
203193 */
204194 bindToken ( authKey : string , token : string ) {
205195 this . token . set ( authKey , token ) ;
206- this . dumpTokens ( ) ;
196+ this . dumpTokens ( ) . catch ( e => console . error ( e ) ) ;
207197 }
208198
209199 /**
210200 * 转换为 json 格式,方便存储与传输
211201 * 返回一个对象,键为 uuid,值为解析后的 cookie 对象
212202 */
213- toJSON ( ) : Record < string , TCookie [ ] > {
214- const json : Record < string , TCookie [ ] > = { } ;
203+ toJSON ( ) : Record < string , CookieEntity [ ] > {
204+ const json : Record < string , CookieEntity [ ] > = { } ;
215205 for ( const [ authKey , cookieObj ] of this . store ) {
216206 json [ authKey ] = cookieObj . toJSON ( ) ;
217207 }
218208 return json ;
219209 }
220210
221211 // 从文件中加载
222- load ( ) : void {
223- this . loadCookies ( ) ;
224- this . loadTokens ( ) ;
212+ async load ( ) {
213+ await Promise . all ( [ this . loadCookies ( ) , this . loadTokens ( ) ] ) ;
225214 }
226215
227- loadCookies ( ) {
216+ async loadCookies ( ) {
228217 this . store = new Map < string , AccountCookie > ( ) ;
229218
230219 try {
231- if ( ! fs . existsSync ( this . cookieDumpFilePath ) ) {
220+ const data = await getMpCookie ( ) ;
221+ if ( ! data ) {
232222 return ;
233223 }
234224
235- const data = readFileSync ( this . cookieDumpFilePath , 'utf-8' ) ;
236- const json = JSON . parse ( data ) as Record < string , TCookie [ ] > ;
237- for ( const [ authKey , cookies ] of Object . entries ( json ) ) {
225+ for ( const [ authKey , cookies ] of Object . entries ( data ) ) {
238226 // Reconstruct cookie strings from parsed objects
239227 const cookieStrings = cookies . map ( cookie => {
240228 const parts = [ `${ cookie . name } =${ cookie . value } ` ] ;
@@ -252,44 +240,49 @@ class CookieStore {
252240 }
253241 }
254242
255- loadTokens ( ) {
243+ async loadTokens ( ) {
256244 this . token = new Map < string , string > ( ) ;
257245
258246 try {
259- if ( ! fs . existsSync ( this . tokenDumpFilePath ) ) {
247+ const data = await getMpToken ( ) ;
248+ if ( ! data ) {
260249 return ;
261250 }
262251
263- const data = readFileSync ( this . tokenDumpFilePath , 'utf-8' ) ;
264- const json = JSON . parse ( data ) as Record < string , string > ;
265- for ( const [ authKey , token ] of Object . entries ( json ) ) {
252+ for ( const [ authKey , token ] of Object . entries ( data ) ) {
266253 this . token . set ( authKey , token ) ;
267254 }
268255 } catch ( error ) {
269256 console . error ( 'Failed to load token store:' , error ) ;
270257 }
271258 }
272259
273- dumpCookies ( ) {
260+ async dumpCookies ( ) {
274261 try {
275- const json = JSON . stringify ( this . toJSON ( ) , null , 2 ) ;
276- writeFileSync ( this . cookieDumpFilePath , json , 'utf-8' ) ;
262+ await setMpCookie ( this . toJSON ( ) ) ;
277263 } catch ( error ) {
278264 console . error ( 'Failed to save cookie store:' , error ) ;
279265 }
280266 }
281267
282- dumpTokens ( ) {
268+ async dumpTokens ( ) {
283269 try {
284- const json = JSON . stringify ( Object . fromEntries ( this . token ) , null , 2 ) ;
285- writeFileSync ( this . tokenDumpFilePath , json , 'utf-8' ) ;
270+ await setMpToken ( Object . fromEntries ( this . token ) ) ;
286271 } catch ( error ) {
287272 console . error ( 'Failed to save token store:' , error ) ;
288273 }
289274 }
290275}
291276
292277export const cookieStore = new CookieStore ( ) ;
278+ cookieStore
279+ . load ( )
280+ . then ( ( ) => {
281+ console . log ( 'cookie store load success.' ) ;
282+ } )
283+ . catch ( e => {
284+ console . error ( 'cookie store load failed.' , e ) ;
285+ } ) ;
293286
294287/**
295288 * 从 CookieStore 中获取 cookie 字符串
0 commit comments