@skills-store/rednote 0.1.14 → 0.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -327
- package/dist/browser/connect-browser.js +59 -31
- package/dist/index.js +2 -2
- package/dist/rednote/checkLogin.js +6 -0
- package/dist/rednote/getMyProfile.js +139 -0
- package/dist/rednote/getProfile.js +145 -31
- package/dist/rednote/index.js +8 -2
- package/dist/rednote/interact.js +30 -7
- package/dist/rednote/login.js +15 -21
- package/dist/rednote/persistence.js +187 -1
- package/dist/rednote/status.js +4 -0
- package/dist/utils/browser-cli.js +1 -0
- package/package.json +1 -1
|
@@ -289,6 +289,96 @@ const rednotePostCommentSchema = new EntitySchema({
|
|
|
289
289
|
}
|
|
290
290
|
]
|
|
291
291
|
});
|
|
292
|
+
const rednoteProfileSchema = new EntitySchema({
|
|
293
|
+
name: 'RednoteProfileRecord',
|
|
294
|
+
tableName: 'rednote_profiles',
|
|
295
|
+
columns: {
|
|
296
|
+
id: {
|
|
297
|
+
type: String,
|
|
298
|
+
primary: true,
|
|
299
|
+
length: 16
|
|
300
|
+
},
|
|
301
|
+
userId: {
|
|
302
|
+
name: 'userid',
|
|
303
|
+
type: String
|
|
304
|
+
},
|
|
305
|
+
nickname: {
|
|
306
|
+
type: String,
|
|
307
|
+
nullable: true
|
|
308
|
+
},
|
|
309
|
+
desc: {
|
|
310
|
+
type: 'text',
|
|
311
|
+
nullable: true
|
|
312
|
+
},
|
|
313
|
+
avatar: {
|
|
314
|
+
type: String,
|
|
315
|
+
nullable: true
|
|
316
|
+
},
|
|
317
|
+
ipLocation: {
|
|
318
|
+
name: 'ip_location',
|
|
319
|
+
type: String,
|
|
320
|
+
nullable: true
|
|
321
|
+
},
|
|
322
|
+
gender: {
|
|
323
|
+
type: String,
|
|
324
|
+
nullable: true
|
|
325
|
+
},
|
|
326
|
+
follows: {
|
|
327
|
+
type: String,
|
|
328
|
+
nullable: true
|
|
329
|
+
},
|
|
330
|
+
fans: {
|
|
331
|
+
type: String,
|
|
332
|
+
nullable: true
|
|
333
|
+
},
|
|
334
|
+
interaction: {
|
|
335
|
+
type: String,
|
|
336
|
+
nullable: true
|
|
337
|
+
},
|
|
338
|
+
tags: {
|
|
339
|
+
type: 'simple-json',
|
|
340
|
+
nullable: true
|
|
341
|
+
},
|
|
342
|
+
fetchedAt: {
|
|
343
|
+
name: 'fetched_at',
|
|
344
|
+
type: Date
|
|
345
|
+
},
|
|
346
|
+
instanceName: {
|
|
347
|
+
name: 'instance_name',
|
|
348
|
+
type: String
|
|
349
|
+
},
|
|
350
|
+
raw: {
|
|
351
|
+
type: 'simple-json',
|
|
352
|
+
nullable: true
|
|
353
|
+
},
|
|
354
|
+
createdAt: {
|
|
355
|
+
name: 'created_at',
|
|
356
|
+
type: Date,
|
|
357
|
+
createDate: true
|
|
358
|
+
}
|
|
359
|
+
},
|
|
360
|
+
indices: [
|
|
361
|
+
{
|
|
362
|
+
name: 'IDX_rednote_profiles_userid_instance',
|
|
363
|
+
columns: [
|
|
364
|
+
'userId',
|
|
365
|
+
'instanceName'
|
|
366
|
+
]
|
|
367
|
+
},
|
|
368
|
+
{
|
|
369
|
+
name: 'IDX_rednote_profiles_fetched_at',
|
|
370
|
+
columns: [
|
|
371
|
+
'fetchedAt'
|
|
372
|
+
]
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
name: 'IDX_rednote_profiles_instance',
|
|
376
|
+
columns: [
|
|
377
|
+
'instanceName'
|
|
378
|
+
]
|
|
379
|
+
}
|
|
380
|
+
]
|
|
381
|
+
});
|
|
292
382
|
let dataSourcePromise = null;
|
|
293
383
|
function createRecordId() {
|
|
294
384
|
return nanoid(16);
|
|
@@ -360,7 +450,8 @@ async function initializeDataSource() {
|
|
|
360
450
|
entities: [
|
|
361
451
|
rednotePostSchema,
|
|
362
452
|
rednotePostDetailSchema,
|
|
363
|
-
rednotePostCommentSchema
|
|
453
|
+
rednotePostCommentSchema,
|
|
454
|
+
rednoteProfileSchema
|
|
364
455
|
],
|
|
365
456
|
synchronize: true,
|
|
366
457
|
logging: false,
|
|
@@ -576,3 +667,98 @@ export async function findPersistedPostUrlByRecordId(instanceName, id) {
|
|
|
576
667
|
});
|
|
577
668
|
return row?.url ?? null;
|
|
578
669
|
}
|
|
670
|
+
export async function persistProfile(input) {
|
|
671
|
+
const { instanceName, result } = input;
|
|
672
|
+
const { profile } = result;
|
|
673
|
+
const { user, notes, userId, url, fetchedAt } = profile;
|
|
674
|
+
const dataSource = await initializeRednoteDatabase();
|
|
675
|
+
await dataSource.transaction(async (manager)=>{
|
|
676
|
+
const profileRepository = manager.getRepository(rednoteProfileSchema);
|
|
677
|
+
const postRepository = manager.getRepository(rednotePostSchema);
|
|
678
|
+
await profileRepository.save(profileRepository.create({
|
|
679
|
+
id: createRecordId(),
|
|
680
|
+
userId,
|
|
681
|
+
nickname: user.nickname,
|
|
682
|
+
desc: user.desc,
|
|
683
|
+
avatar: user.avatar,
|
|
684
|
+
ipLocation: user.ipLocation,
|
|
685
|
+
gender: user.gender,
|
|
686
|
+
follows: toCountString(user.follows),
|
|
687
|
+
fans: toCountString(user.fans),
|
|
688
|
+
interaction: toCountString(user.interaction),
|
|
689
|
+
tags: user.tags,
|
|
690
|
+
fetchedAt: new Date(fetchedAt),
|
|
691
|
+
instanceName,
|
|
692
|
+
raw: user
|
|
693
|
+
}));
|
|
694
|
+
if (notes.length > 0) {
|
|
695
|
+
const noteIds = uniqueStrings(notes.map((note)=>note.id));
|
|
696
|
+
const existingRows = noteIds.length > 0 ? await postRepository.find({
|
|
697
|
+
where: {
|
|
698
|
+
instanceName,
|
|
699
|
+
noteId: In(noteIds)
|
|
700
|
+
}
|
|
701
|
+
}) : [];
|
|
702
|
+
const existingMap = new Map(existingRows.map((row)=>[
|
|
703
|
+
row.noteId,
|
|
704
|
+
row
|
|
705
|
+
]));
|
|
706
|
+
const entities = notes.map((post)=>{
|
|
707
|
+
const existing = existingMap.get(post.id);
|
|
708
|
+
const image = extractPrimaryImage(post);
|
|
709
|
+
const authorNickname = firstNonEmpty(post.noteCard.user.nickname, post.noteCard.user.nickName);
|
|
710
|
+
return postRepository.create({
|
|
711
|
+
id: existing?.id ?? createRecordId(),
|
|
712
|
+
noteId: post.id,
|
|
713
|
+
title: coalesceValue(post.noteCard.displayTitle, existing?.title),
|
|
714
|
+
url: coalesceValue(post.url, existing?.url),
|
|
715
|
+
image: coalesceValue(image, existing?.image),
|
|
716
|
+
likeCount: coalesceValue(toCountString(post.noteCard.interactInfo.likedCount), existing?.likeCount),
|
|
717
|
+
commentCount: coalesceValue(toCountString(post.noteCard.interactInfo.commentCount), existing?.commentCount),
|
|
718
|
+
collectedCount: coalesceValue(toCountString(post.noteCard.interactInfo.collectedCount), existing?.collectedCount),
|
|
719
|
+
sharedCount: coalesceValue(toCountString(post.noteCard.interactInfo.sharedCount), existing?.sharedCount),
|
|
720
|
+
authorId: coalesceValue(post.noteCard.user.userId, existing?.authorId),
|
|
721
|
+
authorNickname: coalesceValue(authorNickname, existing?.authorNickname),
|
|
722
|
+
modelType: coalesceValue(post.modelType, existing?.modelType),
|
|
723
|
+
xsecToken: coalesceValue(post.xsecToken, existing?.xsecToken),
|
|
724
|
+
instanceName,
|
|
725
|
+
raw: post,
|
|
726
|
+
...existing?.createdAt ? {
|
|
727
|
+
createdAt: existing.createdAt
|
|
728
|
+
} : {}
|
|
729
|
+
});
|
|
730
|
+
});
|
|
731
|
+
await postRepository.save(entities);
|
|
732
|
+
}
|
|
733
|
+
});
|
|
734
|
+
}
|
|
735
|
+
export async function getProfileHistory(instanceName, userId, options) {
|
|
736
|
+
const dataSource = await initializeRednoteDatabase();
|
|
737
|
+
const repository = dataSource.getRepository(rednoteProfileSchema);
|
|
738
|
+
const rows = await repository.find({
|
|
739
|
+
where: {
|
|
740
|
+
instanceName,
|
|
741
|
+
userId
|
|
742
|
+
},
|
|
743
|
+
order: {
|
|
744
|
+
fetchedAt: 'DESC'
|
|
745
|
+
},
|
|
746
|
+
take: options?.limit ?? 100
|
|
747
|
+
});
|
|
748
|
+
return rows.map((row)=>({
|
|
749
|
+
id: row.id,
|
|
750
|
+
userId: row.userId,
|
|
751
|
+
nickname: row.nickname,
|
|
752
|
+
desc: row.desc,
|
|
753
|
+
avatar: row.avatar,
|
|
754
|
+
ipLocation: row.ipLocation,
|
|
755
|
+
gender: row.gender,
|
|
756
|
+
follows: row.follows,
|
|
757
|
+
fans: row.fans,
|
|
758
|
+
interaction: row.interaction,
|
|
759
|
+
tags: row.tags,
|
|
760
|
+
fetchedAt: row.fetchedAt,
|
|
761
|
+
instanceName: row.instanceName,
|
|
762
|
+
createdAt: row.createdAt
|
|
763
|
+
}));
|
|
764
|
+
}
|
package/dist/rednote/status.js
CHANGED
|
@@ -23,6 +23,9 @@ Usage:
|
|
|
23
23
|
Options:
|
|
24
24
|
--instance NAME Show status for a custom instance or default browser instance
|
|
25
25
|
-h, --help Show this help
|
|
26
|
+
|
|
27
|
+
Notes:
|
|
28
|
+
When called without --instance, it uses the last connected instance from data.json (lastConnect).
|
|
26
29
|
`);
|
|
27
30
|
}
|
|
28
31
|
function toInstanceState(instance) {
|
|
@@ -136,6 +139,7 @@ export async function getRednoteStatus(target) {
|
|
|
136
139
|
checked
|
|
137
140
|
});
|
|
138
141
|
rednote = {
|
|
142
|
+
userId: checked.userId,
|
|
139
143
|
loginStatus: checked.loginStatus,
|
|
140
144
|
lastLoginAt: checked.lastLoginAt
|
|
141
145
|
};
|
|
@@ -103,6 +103,7 @@ Usage:
|
|
|
103
103
|
bun ./scripts/browser/connect-browser.ts [--instance NAME] [--browser chrome|edge|chromium|brave] [--user-data-dir PATH] [--force] [--port 9222]
|
|
104
104
|
|
|
105
105
|
Notes:
|
|
106
|
+
When called without --instance, it uses the last connected instance from data.json (lastConnect).
|
|
106
107
|
When using --instance without --port, the stored instance port from data.json is used.
|
|
107
108
|
If no stored port exists yet, a random free port is assigned and saved for next time.
|
|
108
109
|
`);
|