Skip to content

Commit a0941ef

Browse files
committed
fix(source): producthunt by offical api
1 parent 7e6805c commit a0941ef

3 files changed

Lines changed: 47 additions & 19 deletions

File tree

example.env.server

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ G_CLIENT_ID=
22
G_CLIENT_SECRET=
33
JWT_SECRET=
44
INIT_TABLE=true
5-
ENABLE_CACHE=true
5+
ENABLE_CACHE=true
6+
PRODUCTHUNT_API_TOKEN=

server/sources/douban.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ export default defineSource(async () => {
3535
Accept: "application/json, text/plain, */*",
3636
},
3737
})
38-
console.log(res)
3938
return res.items.map(movie => ({
4039
id: movie.id,
4140
title: movie.title,

server/sources/producthunt.ts

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,56 @@
1-
import * as cheerio from "cheerio"
1+
import process from "node:process"
22
import type { NewsItem } from "@shared/types"
33

4+
const apiKey = process.env.PRODUCTHUNT_API_TOKEN
5+
const token = `Bearer ${apiKey}`
46
export default defineSource(async () => {
5-
const baseURL = "https://www.producthunt.com"
6-
const html: any = await myFetch(baseURL)
7-
const $ = cheerio.load(html)
8-
const $main = $("[data-test=homepage-section-0] [data-test^=post-item]")
7+
if (!apiKey) {
8+
throw new Error("PRODUCTHUNT_API_TOKEN is not set")
9+
}
10+
const query = `
11+
query {
12+
posts(first: 30, order: VOTES) {
13+
edges {
14+
node {
15+
id
16+
name
17+
tagline
18+
votesCount
19+
url
20+
slug
21+
}
22+
}
23+
}
24+
}
25+
`
26+
27+
const response: any = await myFetch("https://api.producthunt.com/v2/api/graphql", {
28+
method: "POST",
29+
headers: {
30+
"Authorization": token,
31+
"Content-Type": "application/json",
32+
"Accept": "application/json",
33+
},
34+
body: JSON.stringify({ query }),
35+
})
36+
937
const news: NewsItem[] = []
10-
$main.each((_, el) => {
11-
const a = $(el).find("a").first()
12-
const url = a.attr("href")
13-
const title = $(el).find("a[data-test^=post-name]").text().replace(/^\d+\.\s*/, "")
14-
const id = $(el).attr("data-test")?.replace("post-item-", "")
15-
const vote = $(el).find("[data-test=vote-button]").text()
16-
if (url && id && title) {
38+
const posts = response?.data?.posts?.edges || []
39+
40+
for (const edge of posts) {
41+
const post = edge.node
42+
if (post.id && post.name) {
1743
news.push({
18-
url: `${baseURL}${url}`,
19-
title,
20-
id,
44+
id: post.id,
45+
title: post.name,
46+
url: post.url || `https://www.producthunt.com/posts/${post.slug}`,
2147
extra: {
22-
info: `△︎ ${vote}`,
48+
info: ` △︎ ${post.votesCount || 0}`,
49+
hover: post.tagline,
2350
},
2451
})
2552
}
26-
})
53+
}
54+
2755
return news
2856
})

0 commit comments

Comments
 (0)