|
1 | | -import * as cheerio from "cheerio" |
| 1 | +import process from "node:process" |
2 | 2 | import type { NewsItem } from "@shared/types" |
3 | 3 |
|
| 4 | +const apiKey = process.env.PRODUCTHUNT_API_TOKEN |
| 5 | +const token = `Bearer ${apiKey}` |
4 | 6 | 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 | + |
9 | 37 | 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) { |
17 | 43 | 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}`, |
21 | 47 | extra: { |
22 | | - info: `△︎ ${vote}`, |
| 48 | + info: ` △︎ ${post.votesCount || 0}`, |
| 49 | + hover: post.tagline, |
23 | 50 | }, |
24 | 51 | }) |
25 | 52 | } |
26 | | - }) |
| 53 | + } |
| 54 | + |
27 | 55 | return news |
28 | 56 | }) |
0 commit comments