From ec0fca2324f6685c77d16a48bfa0b456c727de18 Mon Sep 17 00:00:00 2001 From: Ou Date: Fri, 25 Oct 2024 13:29:23 +0800 Subject: [PATCH] feat(source): add github treading and product hunt --- public/icons/github.png | Bin 0 -> 1116 bytes public/icons/producthunt.png | Bin 0 -> 18472 bytes server/glob.d.ts | 2 ++ server/sources/github.ts | 34 ++++++++++++++++++++++++++++++++++ server/sources/producthunt.ts | 28 ++++++++++++++++++++++++++++ shared/metadata.ts | 2 +- shared/sources.ts | 17 +++++++++++++++++ shared/types.ts | 12 ++++++------ 8 files changed, 88 insertions(+), 7 deletions(-) create mode 100644 public/icons/github.png create mode 100644 public/icons/producthunt.png create mode 100644 server/sources/github.ts create mode 100644 server/sources/producthunt.ts diff --git a/public/icons/github.png b/public/icons/github.png new file mode 100644 index 0000000000000000000000000000000000000000..ea51207183afa6b2efa3a383a0d2e80091c4dda0 GIT binary patch literal 1116 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
  • I|8MBj>JFNG6yCeo!-lYFF_i(&Tm(#eE)-)lMBWL1ATiX{ zeabnjZhLH9gGZbTaptL^A-<8M}HkMQ~PTsb}_-w&~?!vgQ6*Ei8_j+FHI{UKxL_r zK{*m~72UWLbUE+X)!TF0e%F8Jg_S6RL}2<1%Oy#w6!WE!&vkiLwAj}rv?@H+LE_K+ z%h~(R8k_hC*j$Yj5A0>YD$KNx%OWG=$G9JvxRHTJ9O$>5@hwPzwY+0)Ve= z_6P3Yy;twamt41Y+f^XzI+Qw^_Jrg$T7|rnY)`anfkJ)!paoj5Uwr1bdJ>5XupN>4 zar`DXR0oPhTSZgS(sfjQ0F%C!N5CsTow7swd9gsl#J0e1@As|SFCb6gj4Ns+sY}0G ziM$k_mM`4|Ak8Q(xap1yH}?!&JgNDUF7~v3+P)|)(nth2<9Oqi3W-}#3IIc-buMZ) z(*^Pxo4aN&_mX!dT#@8;oRsphKp^#hgm|^S0cvhMH(hql$+IWM?uI0u%O$apz(teM z@^w_vn9CPaKp>Z5ZpkU^7cmoaycTv84Gl+nK6}s&xBSNI(jIZMXospg&jPAAY>>kBZ}|yD=u8r7aP5+JC!&-Y#5B@j3t5FxmcEn`&0<*lyYjR#Z=Y6di#e*g595a z)AhIfy+lZD@v5x}Oww4O{M%*A0*igguMNh>FYieu0`#2Lyg3rsb(c5r?s+5plJ^!y zpjracngJO4Y{DNJ-x=;%b>`;`{0)=f0~qF>zZkomw0) zOhvc+Vm0%MAiq%Ka$RIr};#mPwIto^UQ{m<|ss~hI}-G-K& z(%gnA$cgg8HQ)Zjt3C7IzAN0d3iEm?+LmZbT_5tT%FUD ziw2MV?De-lD&7-`g}t5c9gzrc22jSlg)xn`d~IC5?AYGe1Zr-EzKzR99nhP-sz2c5?|83_DfA~5S~2i$n$Hp+WD zo>?F9N11{zC2-U7vYLQ(F!i^Lb^q*w3l`6bjogTB+Q%yv?K3V-;PTm9`ul3)I5XX5 zNLY3HIWMuXMbWV7KJv)!uI_V|-t_H_k1!S^zcK{Q_c=pgyIGy@qCK8?($O9fo^C8D zQ`aq7q8@V80iOt@Q(p-h#sPlA4Es&m7m;6>B!Q=kc)9QMF)#ZC)Gd)xb=qQ@^7%F; z)!>y6KE2`ROCNcJ6W95k*Q`2zT;=qAz5aR%KCcG6@7l>epVCT@kYO{TJ?XBM) zgEP$ZGi4<%Jwsahn(~bnYZR2gc+3rbFYN7jr-aUEqocq!p`E{jCQb-1fE_2DokMV6C|eAkBRMmJ}ks|c{~`taf`3}juY0b ziJgu-BkdTJJu7joLq6gXhVqJExtS&$h`S`PK%#^0);;$GUVh|(4~LB8*^y-Wq_C0n zqp!?-{D3Q-P*1tAH&1j>@*A9#d;*&^kE{BWgc>lTn)+}|^WT8wkH5s49M>^20GcvR z_w8c$5_!Fb^2Y1V`!3He37iK>=R9~bWBwmpcG*7+Bu1Cbj*ou?P3%y9>ZU1y-Ks#8 zImbUozUPP6;!kqZW9#=W5owWb*NGML`;Fm1&wmbu`ffaW_3FpmH?ZiCw4_{a7hB>W zw2r^VfAYu;oj)w}K)i77lE68DbmC7Ph34!_FC8#bd(QBujW21Iu{da?vFpjO0_Y}Z zH5QqB7ac*X1NWa zH?BY8d;Zk=P_I=IMl<1)qh{WZGO3NcsHHn5Nwq4F-NZI=}C~f3{+E zOm|pL_}Z)Fgx}RBOMGYF1vuGHGruH(Gg!<>8#ERMh|JHdx~wa*b^H`8)%;W>8D9dW zdvmajkspx?I@7#lj`1iRpf{o&-e@I##Ry!0Hh}+0?sgsY zPyM@kK=<$VUA`vnB@Yo-0Av%`?E<*Z#rtaRlEBrVCEaoaw(5Gs7~OtEAend{eA>u*F6!vz!PYaxOOmMT}j8Y<23z-|g zvTRU^rH%|5sdu3K91CfDB(#U@i_vYN3W( zn+nm>`o*(C6RE>Y(>e;B#>MCd9;%w@gS%4Z0!V8uY{Y%oa8aNyEqs~cy#RqtblGtp zF4i0S*|k^BM{Q><5g!RJ49-F5NIIk{5|yRy$*oGNpk?Mf0j8xQ%b zjtB@+3#p((vk0#A(0QL<(3_6$uceFy5W#yh#s)#Ad9csLeQ(?~Gz5cq9>xWw1^iCG z1>s2negYTm)|upY1-~r?d-2SzSg<&R`s5ANBSRQ)dLyl>Ta(?rFL&K|`!=|3wvhxb bkpur9j%FQ!tR|ts00000NkvXXu0mjfU15(I literal 0 HcmV?d00001 diff --git a/server/glob.d.ts b/server/glob.d.ts index 1efdb4b..9a6776e 100644 --- a/server/glob.d.ts +++ b/server/glob.d.ts @@ -8,8 +8,10 @@ declare module 'glob:./sources/{*.ts,**/index.ts}' { export const douyin: typeof import('./sources/douyin') export const fastbull: typeof import('./sources/fastbull') export const gelonghui: typeof import('./sources/gelonghui') + export const github: typeof import('./sources/github') export const hackernews: typeof import('./sources/hackernews') export const ithome: typeof import('./sources/ithome') + export const producthunt: typeof import('./sources/producthunt') export const solidot: typeof import('./sources/solidot') export const sputniknewscn: typeof import('./sources/sputniknewscn') export const thepaper: typeof import('./sources/thepaper') diff --git a/server/sources/github.ts b/server/sources/github.ts new file mode 100644 index 0000000..466b303 --- /dev/null +++ b/server/sources/github.ts @@ -0,0 +1,34 @@ +import * as cheerio from "cheerio" +import type { NewsItem } from "@shared/types" + +const trending = defineSource(async () => { + const baseURL = "https://github.com" + const html: any = await $fetch("https://github.com/trending?spoken_language_code=") + const $ = cheerio.load(html) + const $main = $("main .Box div[data-hpc] > article") + const news: NewsItem[] = [] + $main.each((_, el) => { + const a = $(el).find(">h2 a") + const title = a.text().replace(/\n+/g, "").trim() + const url = a.attr("href") + const star = $(el).find("[href$=stargazers]").text().replace(/\s+/g, "").trim() + const desc = $(el).find(">p").text().replace(/\n+/g, "").trim() + if (url && title) { + news.push({ + url: `${baseURL}${url}`, + title, + id: url, + extra: { + info: `✰ ${star}`, + hover: desc, + }, + }) + } + }) + return news +}) + +export default defineSource({ + "github": trending, + "github-trending-today": trending, +}) diff --git a/server/sources/producthunt.ts b/server/sources/producthunt.ts new file mode 100644 index 0000000..3826e25 --- /dev/null +++ b/server/sources/producthunt.ts @@ -0,0 +1,28 @@ +import * as cheerio from "cheerio" +import type { NewsItem } from "@shared/types" + +export default defineSource(async () => { + const baseURL = "https://www.producthunt.com/" + const html: any = await $fetch(baseURL) + const $ = cheerio.load(html) + const $main = $("[data-test^=post-item]") + const news: NewsItem[] = [] + $main.each((_, el) => { + const a = $(el).find("a").first() + const url = a.attr("href") + const title = $(el).find("a[data-test^=post-name]").text() + const id = $(el).attr("data-test")?.replace("post-item-", "") + const vote = $(el).find("[data-test=vote-button]").text() + if (url && id && title) { + news.push({ + url: `${baseURL}${url}`, + title, + id, + extra: { + info: `△︎ ${vote}`, + }, + }) + } + }) + return news +}) diff --git a/shared/metadata.ts b/shared/metadata.ts index 25816a6..897e68f 100644 --- a/shared/metadata.ts +++ b/shared/metadata.ts @@ -15,7 +15,7 @@ const originMetadata: Metadata = { }, tech: { name: "科技", - sources: ["hackernews", "v2ex", "ithome", "coolapk", "solidot"], + sources: ["hackernews", "producthunt", "github-trending-today", "v2ex", "ithome", "coolapk", "solidot"], }, finance: { name: "财经", diff --git a/shared/sources.ts b/shared/sources.ts index 93de7de..953e497 100644 --- a/shared/sources.ts +++ b/shared/sources.ts @@ -197,6 +197,23 @@ export const originSources = { type: "hottest", home: "https://news.ycombinator.com/", }, + "producthunt": { + name: "Product Hunt", + color: "orange", + type: "hottest", + home: "https://www.producthunt.com/", + }, + "github": { + name: "Github", + color: "gray", + home: "https://github.com/", + sub: { + "trending-today": { + title: "Today", + type: "hottest", + }, + }, + }, } as const satisfies Record export const sources = genSources() diff --git a/shared/types.ts b/shared/types.ts index 55e0aa6..a8d8ae5 100644 --- a/shared/types.ts +++ b/shared/types.ts @@ -15,12 +15,12 @@ export type SourceID = { }[keyof SubSource] | Key : Key; }[MainSourceID] -// export type AllSourceID = { -// [Key in MainSourceID]: ConstSources[Key] extends { sub?: infer SubSource } ? keyof { -// // @ts-expect-error >_< -// [SubKey in keyof SubSource as `${Key}-${SubKey}`]: never -// } | Key : Key -// }[MainSourceID] +export type AllSourceID = { + [Key in MainSourceID]: ConstSources[Key] extends { sub?: infer SubSource } ? keyof { + // @ts-expect-error >_< + [SubKey in keyof SubSource as `${Key}-${SubKey}`]: never + } | Key : Key +}[MainSourceID] // export type DisabledSourceID = Exclude