-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathfetch.ts
More file actions
70 lines (57 loc) · 2.23 KB
/
fetch.ts
File metadata and controls
70 lines (57 loc) · 2.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import type { User } from "@/api/discourse/user.ts";
import type { Topic } from "@/api/discourse/topic.ts";
import { Mutex } from "async-mutex";
const mutex = new Mutex();
export async function fetchDiscourseUsers(url: string, init: RequestInit = {}){
const parts = url.split('/')
return mutex.runExclusive(async ()=>fetch(`/api/discourse/${parts[parts.length -1]}`, init).then(async r=> {
if(r.status === 404) {
return []
}
const result = await r.json()
return (result?.users || []) as User[]
}))
}
export interface TopicSummary {
postCount: number;
recentAvatars: string[];
notice: string | null;
}
export async function fetchDiscourseTopic(url: string, init: RequestInit = {}, size: number = 48): Promise<TopicSummary | null> {
const parts = url.split('/')
return mutex.runExclusive(async () => {
const response = await fetch(`/api/discourse/${parts[parts.length - 1]}`, init)
if (response.status === 404) {
return null
}
const topic = await response.json() as Topic
// Get actual post count from the posts array length
const postCount = topic.post_stream.posts.length
// Get recent posts with avatars (sorted by creation date, most recent first)
const postsWithAvatars = topic.post_stream.posts
.filter(post => post.avatar_template)
.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime())
// Get unique avatars from the 5 most recent posts
const uniqueAvatars = new Set<string>()
const recentAvatars: string[] = []
for (const post of postsWithAvatars) {
if (recentAvatars.length >= 5) break
const avatarUrl = transformAvatarUrl(post.avatar_template, size)
if (!uniqueAvatars.has(avatarUrl)) {
uniqueAvatars.add(avatarUrl)
recentAvatars.push(avatarUrl)
}
}
return {
postCount,
recentAvatars,
notice: topic.post_stream.posts[0]?.notice?.cooked ?? null,
}
})
}
function transformAvatarUrl(avatarTemplate: string, size: number): string {
const parts = avatarTemplate.split('/')
const userId = parts[parts.length - 3]
const id = parts[parts.length - 1]
return `/api/discourse/avatar/${userId}/${size}/${id}`;
}