Skip to content

Commit 004c8af

Browse files
committed
feat: add like ranking
1 parent 91623af commit 004c8af

File tree

2 files changed

+95
-0
lines changed

2 files changed

+95
-0
lines changed

src/command/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { version } from './version'
44
import { user } from './user'
55
import { post } from './post'
66
import { msg } from './msg'
7+
import { likeRank } from './like-rank'
78

89
export function run() {
910
program
@@ -14,6 +15,7 @@ export function run() {
1415
.addCommand(user)
1516
.addCommand(post)
1617
.addCommand(msg)
18+
.addCommand(likeRank)
1719
.addCommand(version)
1820
.version(versionNumber)
1921
.parse()

src/command/like-rank.ts

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import { logger } from '@poppinss/cliui'
2+
import { createCommand } from 'commander'
3+
import { limit } from 'jike-sdk'
4+
import { createClient, displayUser, filterUsers } from '../utils/user'
5+
import { displayImage, renderDivider } from '../utils/terminal'
6+
import type { Entity } from 'jike-sdk'
7+
8+
interface LikeRankOptions {
9+
top: number
10+
count: number
11+
}
12+
13+
export const likeRank = createCommand('like-rank')
14+
.description('Like ranking')
15+
.alias('lr')
16+
.option('-t, --top <top count>', 'top count', '20')
17+
.option('-c, --count <post count>', 'post count, 0 for all', '0')
18+
.action(() => {
19+
const opts = likeRank.opts<LikeRankOptions>()
20+
likeRanking({
21+
top: +opts.top,
22+
count: +opts.count,
23+
})
24+
})
25+
26+
export const likeRanking = async ({ top, count }: LikeRankOptions) => {
27+
const [user] = filterUsers()
28+
29+
const spinner = logger.await('Fetching posts')
30+
31+
const client = createClient(user)
32+
const posts = await client.getSelf().queryPersonalUpdate({
33+
limit: count > 0 ? limit.limitMaxCount(count) : limit.limitNone(),
34+
})
35+
36+
const userMap: Record<string, { user: Entity.User; count: number }> = {}
37+
for (const [i, post] of posts.entries()) {
38+
spinner.update(`Fetching post (${i + 1} / ${posts.length})`)
39+
40+
const users = await post.listLikedUsers()
41+
for (const user of users) {
42+
const id = user.id
43+
if (!userMap[id]) userMap[id] = { user, count: 1 }
44+
else userMap[id].count++
45+
}
46+
}
47+
48+
const divider = renderDivider()
49+
50+
const countRanking = [
51+
...new Set(Object.values(userMap).map(({ count }) => count)),
52+
].sort((a, b) => b - a)
53+
const getRanking = (count: number) => countRanking.indexOf(count) + 1
54+
55+
const ranking = await Promise.all(
56+
Object.values(userMap)
57+
.sort((a, b) => b.count - a.count)
58+
.slice(0, top)
59+
.map(async ({ user, count }) => {
60+
const ranking = getRanking(count)
61+
let text = `${renderRanking(ranking)} ${displayUser(
62+
user
63+
)} 点赞 ${logger.colors.cyan(`${count}`)} 次,${(
64+
(count / posts.length) *
65+
100
66+
).toFixed(2)}%`
67+
68+
if (ranking <= 3) {
69+
text = `${
70+
(await displayImage(user.avatarImage.thumbnailUrl, 3)).result
71+
}\n${text}\n${divider}`
72+
}
73+
return text
74+
})
75+
)
76+
77+
spinner.stop()
78+
79+
process.stdout.write(ranking.join(`\n`))
80+
81+
function renderRanking(rank: number) {
82+
switch (rank) {
83+
case 1:
84+
return '🥇'
85+
case 2:
86+
return '🥈'
87+
case 3:
88+
return '🥉'
89+
default:
90+
return `${rank.toString().padStart(`${countRanking.length}`.length)}.`
91+
}
92+
}
93+
}

0 commit comments

Comments
 (0)