mirror of
https://github.com/DIYgod/RSSHub.git
synced 2026-09-01 14:57:14 +08:00
feat: migrate deprecated routes (#23071)
* feat: migrate batch-0
* feat: migrate batch-a
batch-0
Migrated (3 routes)
┌────────────────────────────────┬───────────────────────┐
│ old path │ new path │
├────────────────────────────────┼───────────────────────┤
│ /755/user/:username │ /7gogo/user/:username │
├────────────────────────────────┼───────────────────────┤
│ /99percentinvisible/transcript │ unchanged │
├────────────────────────────────┼───────────────────────┤
│ /forum4399/:mtag │ /4399/forums/:mtag │
└────────────────────────────────┴───────────────────────┘
Not needed — already covered by an existing route (3 units, 6 files)
┌────────────────────────────────────────────────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ deleted │ covered by │
├────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ 10000link/news.js (/10000link/news/:category?) │ 10000link/info.ts → /10000link/info/newslists/My01 │
├────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ 199it/{index,category,tag,utils}.js │ 199it/index.tsx → /199it/:category{.+}?; │
├────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ 60s-science/transcript.js (/60s-science) │ scientificamerican/podcast.ts → /scientificamerican/podcast/:id? │
└────────────────────────────────────────────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Dropped (1) — (/12379)
batch-a
Migrated (12 routes, 26 new files) — acm/amturingaward, acwifi, allpoetry, aozora/newbook, archdaily, arxiv/:query, asahi, asml/press-releases, autotrader/:query, av01/actor, av01/tag, axis-studios/work.
Not needed — already covered (8 registrations)
┌─────────────────────────────────────────────────┬────────────────────────────────────────────────────────────┐
│ deleted │ covered by │
├─────────────────────────────────────────────────┼────────────────────────────────────────────────────────────┤
│ adquan/index.js (/adquan/:type?) │ adquan/index.ts → /adquan │
├─────────────────────────────────────────────────┼────────────────────────────────────────────────────────────┤
│ aflcio/blog.js │ aflcio/blog.ts │
├─────────────────────────────────────────────────┼────────────────────────────────────────────────────────────┤
│ amazfitwatchfaces/{fresh,updated,top,search}.js │ amazfitwatchfaces/index.ts → /:device/:sort/:searchParams? │
├─────────────────────────────────────────────────┼────────────────────────────────────────────────────────────┤
│ appsales/index.js │ app-sales/ namespace │
├─────────────────────────────────────────────────┼────────────────────────────────────────────────────────────┤
│ anytxt/release-notes.js │ anytxt/release-notes.ts │
├─────────────────────────────────────────────────┼────────────────────────────────────────────────────────────┤
│ aqicn/index.js │ aqicn/aqi.ts; │
└─────────────────────────────────────────────────┴────────────────────────────────────────────────────────────┘
Dropped (3) — algocasts/all.js (algocasts.io 404), aiyanxishe/home.js (api.yanxishe.com no longer resolves), amd/graphicsdrivers.js
* feat: migrate batch-b
Migrated (8 registrations, 14 new files)
┌─────────────────────────────────────────────────────────┬────────────────────────────────────────────────────────────────────┐
│ old path │ new path │
├─────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────┤
│ /babykingdom/:id/:order? │ /baby-kingdom/:id/:order? │
├─────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────┤
│ /bahamut/creation/:author/:category? │ /gamer/creation/:author/:folder? (param renamed category→folder) │
├─────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────┤
│ /bahamut/creation_index/:category?/:subcategory?/:type? │ /gamer/creation_index/... (unchanged shape) │
├─────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────┤
│ /banyuetan/byt/:time? │ unchanged — new byt.ts added into the existing banyuetan namespace │
├─────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────┤
│ /benedictevans │ /ben-evans │
├─────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────┤
│ /blow-studio │ /blowstudio │
├─────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────┤
│ /blur-studio │ /blur │
├─────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────┤
│ /booth.pm/shop/:subdomain │ unchanged (dir booth-pm → booth.pm) │
└─────────────────────────────────────────────────────────┴────────────────────────────────────────────────────────────────────┘
Not needed — already covered (3)
┌─────────────────────────────────────────────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ deleted │ covered by │
├─────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ banyuetan/index.js (/banyuetan/:name) │ existing banyuetan/index.ts → /banyuetan/:id? │
├─────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ bandisoft/index.js (/bandisoft/:id?/:lang?) │ existing bandisoft/history.ts → /bandisoft/history/:id?/:language? (same {lang}.bandisoft.com/{id}/history/ pages) │
├─────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ bookwalkertw/news.js (/bookwalkertw/news) │ existing bookwalker/search.tsx → /bookwalker/search/order=sell_desc&series_display=1&d=1 - the exact URL the deprecated route fetched │
└─────────────────────────────────────────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Dropped (2)
- bibgame/category.js (/bibgame/:category?/:type?) - bibgame.com is now a parked-domain lander.
- bsblog123/index.js (/bsblog123) - bsblog123.com no longer resolves.
* feat: migrate batch-c
Migrated (26)
cell/cell, cell/cover, centbrowser/history, cgtn/most, cgtn/opinions, chaoli, checkee, chicagotribune, chinafile, chocolatey/software, chouti, chouti/top, chsi/zszcgd, chuhaibiji, cninfo/announcement, coolbuy/newest, cowlevel/element, creaders/headline, csc/notice, ctei/news, ctfhub/search, ctfhub/upcoming.
Path changed (3):
┌───────────────────────────────────┬──────────────────────┐
│ old │ new │
├───────────────────────────────────┼──────────────────────┤
│ /checkra1n/releases │ /checkra.in/releases │
├───────────────────────────────────┼──────────────────────┤
│ /cnu/selected, /cnu/discovery/... │ /cnu.cc/... │
├───────────────────────────────────┼──────────────────────┤
│ /cpython/:pre? │ /python/:pre? │
└───────────────────────────────────┴──────────────────────┘
Not needed — already covered (3)
┌────────────────────────┬────────────────────────┐
│ deleted │ covered by │
├────────────────────────┼────────────────────────┤
│ cbndata/information.js │ cbndata/information.ts │
├────────────────────────┼────────────────────────┤
│ ccg/index.js │ ccg/index.ts │
├────────────────────────┼────────────────────────┤
│ chinadaily/english.js │ chinadaily/language.ts │
└────────────────────────┴────────────────────────┘
Dropped (3)
- cfan/news.js
- citavi/index.js
- clb/commentary.js
* feat: migrate batch-d
Migrated (18 units)
daodu, daxiaamu/home, dbaplus/activity, dcinside/board, dekudeals, deloitte/industries, dgtle ×5 (index, whale, whale-rank, trade, keyword), digitaling ×3, discuss, disqus/posts, dongmanmanhua/comic.
Moved to top-level namespaces:
┌────────────────────────────────────────────────┬───────────┐
│ old │ new │
├────────────────────────────────────────────────┼───────────┤
│ /dgut/xsc/:type? │ unchanged │
├────────────────────────────────────────────────┼───────────┤
│ /dlmu/news/:type, /dlmu/grs/zsgz/:type │ unchanged │
├────────────────────────────────────────────────┼───────────┤
│ /dlu/jiaowu/news │ unchanged │
├────────────────────────────────────────────────┼───────────┤
│ /dpu/jiaowu/news/:type?, /dpu/wlfw/news/:type? │ /dlpu/… │
└────────────────────────────────────────────────┴───────────┘
Not needed — already covered (6)
┌─────────────────────────────────────────────┬───────────────────────────────────────────────────────────────┐
│ deleted │ covered by │
├─────────────────────────────────────────────┼───────────────────────────────────────────────────────────────┤
│ dailyart/index.js (/dailyart/:language?) │ getdailyart/index.ts → /getdailyart/:language? (path changed) │
├─────────────────────────────────────────────┼───────────────────────────────────────────────────────────────┤
│ dbaplus/tab.js (/dbaplus/:tab?) │ dbaplus/rss.ts (/) + dbaplus/new.ts (/news/:id?) │
├─────────────────────────────────────────────┼───────────────────────────────────────────────────────────────┤
│ deepl/blog.js │ deepl/blog.ts — identical path │
├─────────────────────────────────────────────┼───────────────────────────────────────────────────────────────┤
│ dw/index.js (/dw/:lang?/:caty?) │ dw/news.ts + dw/rss.ts │
├─────────────────────────────────────────────┼───────────────────────────────────────────────────────────────┤
│ duozhi/index.js │ duozhi/index.ts │
├─────────────────────────────────────────────┼───────────────────────────────────────────────────────────────┤
│ universities/dgut/jwc.js (/dgut/jwc/:type?) │ dgut/jwb.ts → /dgut/jwb/:type?; │
└─────────────────────────────────────────────┴───────────────────────────────────────────────────────────────┘
Dropped (3 units, 6 registrations)
- ddrk
- dida365/habit-checkins.js
- ditto/changes.js
* feat: migrate batch-e
Migrated (11 units)
edrawsoft/mindmap, emi-nitta, etherscan/transactions, etoland/board, europapress, eztv/imdb, ebb, eeo.
Path changed (3):
┌──────────────────────┬───────────────────────┐
│ old │ new │
├──────────────────────┼───────────────────────┤
│ /eleme/open/announce │ /ele.me/open/announce │
├──────────────────────┼───────────────────────┤
│ /everything/changes │ /voidtools/changes │
├──────────────────────┼───────────────────────┤
│ /engadget/:lang? │ /engadget/ │
└──────────────────────┴───────────────────────┘
Not needed (1 unit, 2 registrations + 2 dangling)
/dytt and /dytt/index
Dropped (2 units, 4 registrations)
- enclavebooks/{category,user,collection}.js
* feat: migrate batch-f
┌────────────────────────────────────────────────────────────────────┬───────────────────────────────────────────────────────┐
│ old │ new │
├────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────┤
│ /fanfou │ unchanged │
├────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────┤
│ /fashionnetwork/news/:sectors?/:categories?/:language? │ /fashionnetwork/news/:sectors?/:categories?/:country? │
├────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────┤
│ /fashionnetwork/headline/:country? │ unchanged │
├────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────┤
│ /fgo/news │ /fate-go/news │
├────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────┤
│ /fnal/news/:category? │ unchanged │
└────────────────────────────────────────────────────────────────────┴───────────────────────────────────────────────────────┘
Universities (a-f)
- fzu/news-min.ts deleted
* feat: migrate batch-g
Migrated
gab/user, gameres, gitlab, gocomics, gushiwen, guat, guet, gwern, gzmtu, gdou, ngd, gov/caict, gov/cnca, gov/harbin/kjj, gov/mohrss/sbjm, gov/mohurd/policy, gov/shanxi/rst, gov/wuhan, gov/beijing/mhc.
/gdoujwc → /gdou/jwc;
/ngd
path changed (14)
┌─────────────────────────────────────────────────────────┬────────────────────────────────────────────┐
│ old │ new │
├─────────────────────────────────────────────────────────┼────────────────────────────────────────────┤
│ /geektime/column/:cid │ /geekbang/column/:cid │
├─────────────────────────────────────────────────────────┼────────────────────────────────────────────┤
│ /guardian/:type │ /theguardian │
├─────────────────────────────────────────────────────────┼────────────────────────────────────────────┤
│ /grandchallenge/ │ /grand-challenge/ │
├─────────────────────────────────────────────────────────┼────────────────────────────────────────────┤
│ /go.jp/mofa │ /mofa │
├─────────────────────────────────────────────────────────┼────────────────────────────────────────────┤
│ /gov/beijing/bjeea/:type │ /bjeea/:type │
├─────────────────────────────────────────────────────────┼────────────────────────────────────────────┤
│ /gov/hubei/hbsia/:caty │ /hbsea/:id │
├─────────────────────────────────────────────────────────┼────────────────────────────────────────────┤
│ /gov/guangdong/{edu,eea}/:caty │ /gov/gd/{edu,eea}/:caty │
├─────────────────────────────────────────────────────────┼────────────────────────────────────────────┤
│ /gov/hunan/notice/:type │ /gov/ccgp-hunan/notice/:type? │
├─────────────────────────────────────────────────────────┼────────────────────────────────────────────┤
│ /gov/veterans/:type │ /gov/mva/:type │
├─────────────────────────────────────────────────────────┼────────────────────────────────────────────┤
│ /gov/veterans/hebei/:type │ /gov/hebei/tyjrswt/:type │
├─────────────────────────────────────────────────────────┼────────────────────────────────────────────┤
│ /gov/taiwan/mnd │ /gov/mnd │
├─────────────────────────────────────────────────────────┼────────────────────────────────────────────┤
│ /gov/xinwen/tujie/:caty │ /gov/cn/xinwen/tujie/:caty │
├─────────────────────────────────────────────────────────┼────────────────────────────────────────────┤
│ /gov/city/:name/:category (nanjing-only dispatcher) │ /gov/nanjing/:category │
├─────────────────────────────────────────────────────────┼────────────────────────────────────────────┤
│ /gov/province/:name/:category (jiangsu-only dispatcher) │ /gov/jiangsu/:category │
└─────────────────────────────────────────────────────────┴────────────────────────────────────────────┘
gov/shanghai/sthj → gov/sh/sthj
gov/cppcc
Not needed (2)
- gnn/gnn.js - covered by batch-b's /gamer/gnn/:category?
- getdailyart - from batch-d
Dropped (8 units)
- galaxylab, guanggoo, gov/chongqing/ljxq
- gov/sapprft/7026 → gov/nppa
- gaoqing/latest
- gov/statecouncil/briefing
- gov/shuju
* refactor: cleanup
* feat: migrate batch-h
Migrated (12 units)
hackerone, hainanu/ssszs, hanime/video, hentaimama/videos, hexo, huya/live, hbut/news, henu/news, hfut/tzgg, hnust, hhu/libNews.
hdx -> /huodongxing/explore
Migrated - public path changed (3)
┌─────────────────────────────────┬───────────────────────────────────────────┐
│ old │ new │
├─────────────────────────────────┼───────────────────────────────────────────┤
│ /porn-images-xxx/:type?/:name? │ /hentai-cosplays-xxx/:type?/:name? │
├─────────────────────────────────┼───────────────────────────────────────────┤
│ /hatena/anonymous_diary/archive │ /hatelabo/anonymous_diary/archive │
├─────────────────────────────────┼───────────────────────────────────────────┤
│ /hbut/cs/:type │ /hbut/scs/:type (school renamed cs → scs) │
└─────────────────────────────────┴───────────────────────────────────────────┘
Not needed (2)
- hkej/index.js -> master's hkej/index.tsx
- /hubu/news.js -> hubu/index.ts
Dropped (3 units)
- haohaozhu
- hudongba
- hhu/libNewsc
* feat: migrate batch-i
Migrated (8 units)
┌───────────────┬────────────────────────────────┐
│ route │ path │
├───────────────┼────────────────────────────────┤
│ ichunqiu │ /ichunqiu │
├───────────────┼────────────────────────────────┤
│ iciba │ /iciba/:days?/:img_type? │
├───────────────┼────────────────────────────────┤
│ icity │ /icity/:id │
├───────────────┼────────────────────────────────┤
│ icourse163 │ /icourse163/newest │
├───────────────┼────────────────────────────────┤
│ idownloadblog │ /idownloadblog │
├───────────────┼────────────────────────────────┤
│ ifnews │ /ifnews/:cid │
├───────────────┼────────────────────────────────┤
│ im2maker │ /im2maker/:channel? │
├───────────────┼────────────────────────────────┤
│ itslaw │ /itslaw/judgements/:conditions │
└───────────────┴────────────────────────────────┘
Dropped (2 units)
- interesting-sky
- invisionapp/inside-design
* feat: migrate batch-j
Migrated (5 units)
┌────────────────────────────────────────────────┬────────────────────────────────────┐
│ old │ new │
├────────────────────────────────────────────────┼────────────────────────────────────┤
│ /jgsu/jwc │ unchanged │
├────────────────────────────────────────────────┼────────────────────────────────────┤
│ /jlbtc/:category?, /jlbtc/jwc/:id?, │ unchanged (jwc param now │
│ /jlbtc/kyc/:category? │ :category{.+}?) │
├────────────────────────────────────────────────┼────────────────────────────────────┤
│ /jnu/yw/:type? │ unchanged │
├────────────────────────────────────────────────┼────────────────────────────────────┤
│ /ju/jwc/:type? │ /jiangnan/jwc/:type? │
├────────────────────────────────────────────────┼────────────────────────────────────┤
│ /jx3/:caty? │ /xoyo/jx3/:caty? │
│ │ │
└────────────────────────────────────────────────┴────────────────────────────────────┘
Dropped (2)
- universities/jlu/oa.js (/jlu/oa)
- universities/jnu/xysx/index.js (/jnu/xysx/:type)
* feat: migrate batch-k
Migrated (7 units)
┌─────────────────────────────────────┬──────────────────┐
│ old │ new │
├─────────────────────────────────────┼──────────────────┤
│ /kaiyan/index │ /kaiyanapp/index │
├─────────────────────────────────────┼──────────────────┤
│ /kaoyan │ unchanged │
├─────────────────────────────────────┼──────────────────┤
│ /kchuhai │ /kchuhai/report │
├─────────────────────────────────────┼──────────────────┤
│ /kenshin/:category?/:type? │ unchanged │
├─────────────────────────────────────┼──────────────────┤
│ /keyakizaka46/{news,blog} │ unchanged │
├─────────────────────────────────────┼──────────────────┤
│ /kongfz/{people/:id,shop/:id/:cat?} │ unchanged │
├─────────────────────────────────────┼──────────────────┤
│ /kmust/jwc/:type? │ unchanged │
└─────────────────────────────────────┴──────────────────┘
Not needed (1)
- kuai/id.js (/kuai/:id) → merged into kuai/index.ts as /kuai/:category?
Dropped (3 units, 4 registrations)
- kingarthur (/kingarthur/:type)
- kmust/job/{careers,jobfairs}
- kotaku/story
* feat: migrate batch-l
law/* aggregate
┌───────────┬──────────────────────────────────────────────┐
│ old │ new │
├───────────┼──────────────────────────────────────────────┤
│ /law/dh │ dehenglaw │
├───────────┼──────────────────────────────────────────────┤
│ /law/jh │ junhe │
├───────────┼──────────────────────────────────────────────┤
│ /law/zl │ zhonglun │
├───────────┼──────────────────────────────────────────────┤
│ /law/gf │ /grandwaylaw │
├───────────┼──────────────────────────────────────────────┤
│ /law/hq │ /haiwen-law │
├───────────┼──────────────────────────────────────────────┤
│ /law/hw │ /glo │
├───────────┼──────────────────────────────────────────────┤
│ /law/jctd │ /jtn │
├───────────┼──────────────────────────────────────────────┤
│ /law/jtc │ /allbrightlaw │
├───────────┼──────────────────────────────────────────────┤
│ /law/ts │ /tongshang │
└───────────┴──────────────────────────────────────────────┘
Migrated - same public path (9 units)
lagou/jobs, latexstudio/home, letterboxd, lifetimes, lizhi/user, lwn/alerts, and lit, lntu/jwnews, lyu/news
Migrated - public path changed (3 units)
┌─────────────────────────────────────────┬────────────────────────────────────┐
│ old │ new │
├─────────────────────────────────────────┼────────────────────────────────────┤
│ /lastfm/{recent,loved}/:user, │ /last.fm/ │
│ /lastfm/top/:country? │ │
├─────────────────────────────────────────┼────────────────────────────────────┤
│ /liyuan-forums/threads[...] │ /liyuans/threads │
├─────────────────────────────────────────┼────────────────────────────────────┤
│ /lolapp/{recommend,article/:uuid} │ /qq/mlol/{recommend,article/:uuid} │
└─────────────────────────────────────────┴────────────────────────────────────┘
Dropped (1 unit,)
- laosiji
* feat: migrate batch-m
Migrated - same public path (20 units)
mafengwo, mamibuy, manictime/releases, maoyan, marginnote/tag, mathunion/fields-medal, meihua, meipai/user, meituan/open/announce, melon/chart, mihoyo, missevan, moxingfans, mubu/explore, muchong, monotype/article, mcdonalds, and mit/csail/news, mit/ocw-top.
Migrated - public path changed (5)
┌──────────────────────────────────────────────┬─────────────────────────────────────────────┐
│ old │ new │
├──────────────────────────────────────────────┼─────────────────────────────────────────────┤
│ /method-studios/:menu? │ /company3 │
├──────────────────────────────────────────────┼─────────────────────────────────────────────┤
│ /mhw/{update,news} │ /monsterhunter/{update,world-iceborne-news} │
├──────────────────────────────────────────────┼─────────────────────────────────────────────┤
│ /microsoft-store/updates/:productid/:market? │ /microsoft/store/updates/ │
├──────────────────────────────────────────────┼─────────────────────────────────────────────┤
│ /manxiaosi/book/:id │ /jjmhw/book/:id │
├──────────────────────────────────────────────┼─────────────────────────────────────────────┤
│ /mit/graduateadmissions/:type/:name │ /mit/oge/:type?/:name? │
└──────────────────────────────────────────────┴─────────────────────────────────────────────┘
Dropped (7 units)
magireco, mcbbs, micmicidol, rthk/mediadigest, manhuadb, mofish
* refactor: cleanup
* feat: migrate batch-n
Migrated - same public path (8)
nobelprize/:caty?, nosetime, noi, nchu/jwc, nciae, njfu/jwc, njtech/jwc.
Migrated - public path changed (2)
┌──────────────────────┬──────────────────────┐
│ old │ new │
├──────────────────────┼──────────────────────┤
│ /nace/blog/:sort? │ /naceweb/blog/:sort? │
├──────────────────────┼──────────────────────┤
│ /novel/uukanshu/:uid │ /uukanshu/:uid │
└──────────────────────┴──────────────────────┘
Not needed - already covered (3)
- novel/{biquge,biqugeinfo}.js → biquge
- nku/jwc → nankai/jwc.ts
- nudt/yjszs → nudt/yjszs.ts
Dropped (6)
navisec, noi/rg-news, now/rank, nwpu, nuc, nvidia/webdriverupdate
* feat: migrate batch-o
Migrated (3)
┌────────────┬─────────────────────┐
│ route │ path │
├────────────┼─────────────────────┤
│ ofweek │ /ofweek/news │
├────────────┼─────────────────────┤
│ onejav │ /onejav/:type/:key? │
├────────────┼─────────────────────┤
│ onenotegem │ /onenotegem/release │
└────────────┴─────────────────────┘
Not needed (2)
- one/index.js -> wufazhuce/one.ts
- ornl/news -> ornl/all-news
Dropped (1 units)
- owspace/read
* feat: migrate batch-p
Migrated - same public path (5 units)
patchwork.kernel.org/comments/:id, phrack, piapro, polimi/news/:language?, proletar/:type?/:id?.
Migrated - public path changed (2)
┌────────────────────────────┬───────────────────────────────┐
│ old │ new │
├────────────────────────────┼───────────────────────────────┤
│ /parcel/hermesuk/:tracking │ /evri/:tracking (rebrand) │
├────────────────────────────┼───────────────────────────────┤
│ /project-zero-issues │ /chromium/project-zero-issues │
└────────────────────────────┴───────────────────────────────┘
Not needed - already covered (1)
- potplayer/update.js → master daum/potplayer.ts
Dropped (3)
- paidai, pmcaff, ptpress/book
* feat: migrate batch-q
Migrated - same public path (5)
┌───────────┬─────────────────────────────┐
│ route │ path │
├───────────┼─────────────────────────────┤
│ qnap │ /qnap/release-notes/:id │
├───────────┼─────────────────────────────┤
│ qttabbar │ /qttabbar/change-log │
├───────────┼─────────────────────────────┤
│ queshu │ /queshu/{sale,book/:bookid} │
├───────────┼─────────────────────────────┤
│ qutoutiao │ /qutoutiao/category/:cid │
├───────────┼─────────────────────────────┤
│ qzcea │ /qzcea/:caty? │
└───────────┴─────────────────────────────┘
Migrated - public path changed (1)
- /qcloud/mlvb/changelog → /tencent/qcloud/mlvb/changelog
* feat: migrate batch-r
Migrated - same public path (3 units)
rescuetime/release-notes/:os?, ruby-china, rmlt/idea*.
/rmlt/idea/:category? -> new /rmlt/idea
Migrated - public path changed (4)
┌────────────────────────────┬────────────────────────────┐
│ old │ new │
├────────────────────────────┼────────────────────────────┤
│ /react/react-native-weekly │ /reactnativenewsletter │
├────────────────────────────┼────────────────────────────┤
│ /remote-work/:caty? │ /yuancheng.work/:caty? │
├────────────────────────────┼────────────────────────────┤
│ /rf/article │ /eefocus/rf/article │
├────────────────────────────┼────────────────────────────┤
│ /rthk-news/:lang/:category │ /rthk/news/:lang/:category │
└────────────────────────────┴────────────────────────────┘
* feat: migrate batch-t
Migrated - same public path (13)
samsungmembers, secshi, sesame/release_notes, sexinsex, simonsfoundation, simpread, sketch, socialbeta/home, soundcloud, ssydt/article, sznews/ranking, shanbay/checkin, scu, shanghaitech, shou/www, swufe/seie, swust, sctu/jwc.
Migrated - public path changed (7)
┌────────────────────────────────────────────┬───────────────────────────────────────────────────────────────┐
│ old │ new │
├────────────────────────────────────────────┼───────────────────────────────────────────────────────────────┤
│ /siren/news │ /hypergryph/siren/news │
├────────────────────────────────────────────┼───────────────────────────────────────────────────────────────┤
│ /socialclub/events/:game? │ /rockstargames/socialclub/events/:game? │
├────────────────────────────────────────────┼───────────────────────────────────────────────────────────────┤
│ /security/pulses │ /sec.today/pulses │
├────────────────────────────────────────────┼───────────────────────────────────────────────────────────────┤
│ /souyun/today │ /sou-yun/today │
├────────────────────────────────────────────┼───────────────────────────────────────────────────────────────┤
│ /soul/:id, /soul/posts/hot/:pid* │ /soulapp/:id, /soulapp/posts/tag/:tid │
├────────────────────────────────────────────┼───────────────────────────────────────────────────────────────┤
│ /shanbay/footprints/:category? │ /shanbay/news/:category? │
├────────────────────────────────────────────┼───────────────────────────────────────────────────────────────┤
│ /sctu/xgxy │ /sctu/it │
├────────────────────────────────────────────┼───────────────────────────────────────────────────────────────┤
│ /slu/ │ /lixin/ │
└────────────────────────────────────────────┴───────────────────────────────────────────────────────────────┘
Dropped (4)
- scboy/thread
- sznews/press
- steamgifts/discussions
- semiconductors/latest-news -> semiconductors/index
* feat: migrate batch-t
Migrated - same public path (7)
technologyreview, testerhome/newest, thunderbird/release, tianyancha/hot, touhougarakuta/:language/:type, trakt/collection, thu -> tsinghua/{career,info}.
Migrated - public path changed (7)
┌──────────────────────────────────────────────────────────┬──────────────────────────────────────┐
│ old │ new │
├──────────────────────────────────────────────────────────┼──────────────────────────────────────┤
│ /totalcommander/whatsnew │ /ghisler/whatsnew │
├──────────────────────────────────────────────────────────┼──────────────────────────────────────┤
│ /tingshen │ /gov/court │
├──────────────────────────────────────────────────────────┼──────────────────────────────────────┤
│ /tucaoqq/post/:project/:key │ /qq/txc/post/:project │
├──────────────────────────────────────────────────────────┼──────────────────────────────────────┤
│ /weixin/miniprogram/{framework,release,devtools,wxcloud} │ /qq/weixin/miniprogram/ │
├──────────────────────────────────────────────────────────┼──────────────────────────────────────┤
│ /wechat-open/pay/announce │ /qq/weixin/pay/announce │
├──────────────────────────────────────────────────────────┼──────────────────────────────────────┤
│ /tprtc/{news,cqzr,qyzc} │ /tpre/ │
├──────────────────────────────────────────────────────────┼──────────────────────────────────────┤
│ /topbook/{overview/:id?,today} │ /topbook/:id? │
└──────────────────────────────────────────────────────────┴──────────────────────────────────────┘
/tingdiantz/95598/:province/:city/:district? -> /sttcq/:province/:city/:district?
/tingdiantz/nanjing -> /sgcc/95598/blackoutNotice/:adcode
Dropped (4)
- tanchinese
- titsguru
- wechat-open/community/{announce,question} - login wall
sm2 benchmark
┌───────────────────────────┬────────┬─────────┬─────────┬───────┬──────────────────────┐
│ lib │ sm3 │ sm4 enc │ sm4 dec │ sm2 │ per request envelope │
├───────────────────────────┼────────┼─────────┼─────────┼───────┼──────────────────────┤
│ sm-crypto@0.5.6 │ 245k/s │ 166k/s │ 3.0k/s │ 72/s │ 14.3ms │
├───────────────────────────┼────────┼─────────┼─────────┼───────┼──────────────────────┤
│ sm-crypto-v2@1.15.1 │ 281k/s │ 130k/s │ 2.5k/s │ 343/s │ 3.3ms │
├───────────────────────────┼────────┼─────────┼─────────┼───────┼──────────────────────┤
│ gm-crypto@0.1.12 │ 265k/s │ 173k/s │ 2.6k/s │ 58/s │ 17.5ms │
└───────────────────────────┴────────┴─────────┴─────────┴───────┴──────────────────────┘
* refactor: cleanup
* feat: migrate batch-u
┌─────────────────────────────────────────────┬───────────────────────────────────────┐
│ old │ new │
├─────────────────────────────────────────────┼───────────────────────────────────────┤
│ /us/supremecourt/argument_audio/:year? │ /supremecourt/argument_audio/:year? │
├─────────────────────────────────────────────┼───────────────────────────────────────┤
│ /cia/foia-annual-report (handler under us/) │ /cia/foia-annual-report │
├─────────────────────────────────────────────┼───────────────────────────────────────┤
│ /treasury/press-releases/:category?/:title? │ unchanged │
├─────────────────────────────────────────────┼───────────────────────────────────────┤
│ /ustr/press-releases/:year?/:month? │ /ustr/press-releases │
└─────────────────────────────────────────────┴───────────────────────────────────────┘
Migrated - same public path (6 units)
uisdc/hangye/:caty?, un/scveto, unit-image/films/:type?, uwants/:fid, usst/jwc, utdallas/isso
Migrated - public path changed (1)
- /ui-cn/{article,user/:id} → /ui.cn/
* feat: migrate batch-v
Migrated - public path changed (4)
┌────────────────────────────┬──────────────────────────────────┐
│ old │ new │
├────────────────────────────┼──────────────────────────────────┤
│ /vgn/:platform? │ /vgnlab │
├────────────────────────────┼──────────────────────────────────┤
│ /voa/:language/:channel? │ /voanews/:language/:channel? │
├────────────────────────────┼──────────────────────────────────┤
│ /vol/:mode? │ /kzo.moe │
├────────────────────────────┼──────────────────────────────────┤
│ /vscode/marketplace/:type? │ /visualstudio/marketplace/:type? │
└────────────────────────────┴──────────────────────────────────┘
Migrated - same public path (1)
- /vulture/:tag/:excludetags?
Not needed - already covered (1)
- vocus/user.js
* feat: migrate batch-w
Migrated - same public path (7 units)
wegene, weidian/goods/:id, wenxuecity, whb/:category, wto/dispute-settlement/:year?, wzbc/:type?, webtoons/:lang/:category/:name/:id.
Migrated - public path changed (4)
┌─────────────────────────────────────┬───────────────────────────────────┐
│ old │ new │
├─────────────────────────────────────┼───────────────────────────────────┤
│ /watchface/:watch_type?/:list_type? │ /bandbbs/:watch_type?/:list_type? │
├─────────────────────────────────────┼───────────────────────────────────┤
│ /webtoons/naver/:id │ /naver/comic/:id │
├─────────────────────────────────────┼───────────────────────────────────┤
│ /worldhappiness/archive │ /worldhappiness/analysis │
├─────────────────────────────────────┼───────────────────────────────────┤
│ /worldhappiness/blog │ /worldhappiness/news │
└─────────────────────────────────────┴───────────────────────────────────┘
Not needed - already covered (1)
- wainao/index.js
Dropped (2 units)
- weexcn
- wikipedia/mainland
* feat: migrate batch-x
Migrated - same public path (8)
xclient/app/:name, xmind/mindmap/:lang?, xuangubao/subject/:subject_id, xyplorer/whatsnew, xynu/zkb/:category, xmu/aero/:type, xiachufang/popular/:timeframe?.
Migrated - reshaped (3)
┌────────────────────────────────────────────────────────────────────────────┬───────────────────────────────────────────────────────────────┐
│ old │ new │
├────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────┤
│ /xiachufang/user/{cooked,created}/:id │ /xiachufang/user/:id/:type? │
├────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────┤
│ /xuetangx/course/:cid/:type, /course/list/:mode/:credential/:status/:type? │ /course/:sign, /course/list/:classify?/:status?/:sellingType? │
├────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────┤
│ /xinwenlianbo/index │ /govopendata/xinwenlianbo │
└────────────────────────────────────────────────────────────────────────────┴───────────────────────────────────────────────────────────────┘
/xiaomieu/releases -> /xiaomi.eu/releases
No Need(1)
- x410/news
* feat: migrate batch-y
Migrated - same public path (7)
- yidoutang
- yinxiang
- ynnu
- ynu
- yzu
- youdao
- youzan
Migrated - path changed (1)
┌───────────────────────┬───────────────────────┐
│ old │ new │
├───────────────────────┼───────────────────────┤
│ /yahoo-author/:author │ /yahoo/author/:author │
└───────────────────────┴───────────────────────┘
Dropped - dead (1)
- yuzu-emu (/yuzu-emu/entry)
* feat: migrate batch-z
Migrated - same public path (6)
- zhimap
- zhishifenzi
- zimuku
- zsnews
- zjgsu
- zzuli
Migrated - reshaped (3)
┌───────────────────────────────────────────────────────┬───────────────────────────────────────────────────────┐
│ old │ new │
├───────────────────────────────────────────────────────┼───────────────────────────────────────────────────────┤
│ /zucc/news/latest, /zucc/cssearch/latest/:webVpn/:key │ /hzcu/news/latest, /hzcu/cssearch/latest/:webVpn/:key │
├───────────────────────────────────────────────────────┼───────────────────────────────────────────────────────┤
│ /zjut/:type, /zjut/design/:type │ /zjut/:type?, /zjut/design/:type │
├───────────────────────────────────────────────────────┼───────────────────────────────────────────────────────┤
│ /zzu/soft/news/:type │ /zzu/soft/news/:type? │
└───────────────────────────────────────────────────────┴───────────────────────────────────────────────────────┘
No Need (2)
- zongheng/chapter
- zzu/news
Dropped (1)
- zreading
* feat: migrate batch-z
* refactor: cleanup
* refactor: cleanup
* feat: remove router.js
* fix: increase timeout
* feat: fix author
jacky2001114 -> yangkghjh #288
Lava-Swimmer -> LandonLi #4393
xfangbao -> salviox #4756
* fix: exported utils name
* fix: codeql
* fix: remove fake date
* feat!: drop swust
* fix: update oxlint ignore
* fix: address review
* fix: remove dead comments
* fix: address review
* fix: address review
This commit is contained in:
@@ -110,6 +110,7 @@ type ConfigEnvKeys =
|
||||
| 'EH_STAR'
|
||||
| 'EH_IMG_PROXY'
|
||||
| `EMAIL_CONFIG_${string}`
|
||||
| 'ETHERSCAN_API_KEY'
|
||||
| 'F95ZONE_COOKIE'
|
||||
| 'FANBOX_SESSION_ID'
|
||||
| 'FANFOU_CONSUMER_KEY'
|
||||
@@ -420,6 +421,9 @@ export type Config = {
|
||||
email: {
|
||||
config: Record<string, string | undefined>;
|
||||
};
|
||||
etherscan: {
|
||||
apiKey?: string;
|
||||
};
|
||||
f95zone: {
|
||||
cookie?: string;
|
||||
};
|
||||
@@ -926,6 +930,9 @@ const calculateValue = () => {
|
||||
email: {
|
||||
config: email_config,
|
||||
},
|
||||
etherscan: {
|
||||
apiKey: envs.ETHERSCAN_API_KEY,
|
||||
},
|
||||
f95zone: {
|
||||
cookie: envs.F95ZONE_COOKIE,
|
||||
},
|
||||
|
||||
-1575
File diff suppressed because it is too large
Load Diff
@@ -1,59 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const url = require('url');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const category = ctx.params.category;
|
||||
const pageUrl = `http://info.10000link.com/newslists.aspx?chid=${category}`;
|
||||
const host = 'http://info.10000link.com';
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: pageUrl,
|
||||
});
|
||||
const $ = cheerio.load(response.data);
|
||||
const list = $('.l_newshot li').get();
|
||||
|
||||
const ProcessFeed = async (link) => {
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: link,
|
||||
});
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
return $('#news_body').html();
|
||||
};
|
||||
|
||||
const items = await Promise.all(
|
||||
list.map(async (item) => {
|
||||
const $ = cheerio.load(item);
|
||||
const $a = $('h1 a');
|
||||
const link = url.resolve(host, $a.attr('href'));
|
||||
|
||||
const cache = await ctx.cache.get(link);
|
||||
if (cache) {
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const description = await ProcessFeed(link);
|
||||
|
||||
const single = {
|
||||
title: $a.text(),
|
||||
description,
|
||||
link,
|
||||
pubDate: new Date($('.ymd_w').text()).toUTCString(),
|
||||
author: $('.day-lx span:first-child').text(),
|
||||
};
|
||||
|
||||
ctx.cache.set(link, JSON.stringify(single));
|
||||
return single;
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `万联网 ${$('.t-h2').text().replace(' |资讯频道', '')}`,
|
||||
link: pageUrl,
|
||||
description: $('meta[name="Description"]').attr('content'),
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,23 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const currentUrl = `http://www.12379.cn/data/index_map_all.html`;
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: currentUrl,
|
||||
});
|
||||
const data = JSON.parse(response.data.slice('var alertData ='.length, 'var alertData ='.length + response.data.length + 1));
|
||||
|
||||
const list = data.map((item) => ({
|
||||
title: item.headline,
|
||||
link: `http://www.12379.cn/html/new2018/alarmcontent.shtml?file=${item.identifier}.html`,
|
||||
description: item.description,
|
||||
pubDate: new Date(item.sendTime).toUTCString(),
|
||||
}));
|
||||
|
||||
ctx.state.data = {
|
||||
title: `当前生效预警 - 国家突发事件预警信息发布网`,
|
||||
link: currentUrl,
|
||||
item: list,
|
||||
};
|
||||
};
|
||||
@@ -1,10 +0,0 @@
|
||||
const utils = require('./utils');
|
||||
|
||||
const rootUrl = 'https://www.199it.com/archives/category';
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const keyword = ctx.params.caty.split('|').join('/');
|
||||
const currentUrl = `${rootUrl}/${keyword}`;
|
||||
|
||||
ctx.state.data = await utils(ctx, keyword, currentUrl);
|
||||
};
|
||||
@@ -1,31 +0,0 @@
|
||||
const cheerio = require('cheerio');
|
||||
const got = require('@/utils/got');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const url = `http://www.199it.com/newly`;
|
||||
|
||||
const res = await got.get(url);
|
||||
const $ = cheerio.load(res.data);
|
||||
const list = $('.entry-content').get();
|
||||
|
||||
const out = list.slice(0, 9).map((item) => {
|
||||
const $ = cheerio.load(item);
|
||||
const time = $('.post-time time').attr('datetime');
|
||||
const title = $('.entry-title a').attr('title');
|
||||
const partial = $('.entry-title a').attr('href');
|
||||
const address = partial;
|
||||
const single = {
|
||||
title,
|
||||
pubDate: new Date(time).toUTCString(),
|
||||
link: address,
|
||||
guid: address,
|
||||
};
|
||||
ctx.cache.set(address, JSON.stringify(single));
|
||||
return single;
|
||||
});
|
||||
ctx.state.data = {
|
||||
title: '199it',
|
||||
link: url,
|
||||
item: out,
|
||||
};
|
||||
};
|
||||
@@ -1,10 +0,0 @@
|
||||
const utils = require('./utils');
|
||||
|
||||
const rootUrl = 'https://www.199it.com/archives/tag';
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const keyword = ctx.params.tag.split('|').join('/');
|
||||
const currentUrl = `${rootUrl}/${keyword}`;
|
||||
|
||||
ctx.state.data = await utils(ctx, keyword, currentUrl);
|
||||
};
|
||||
@@ -1,44 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx, keyword, currentUrl) => {
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: currentUrl,
|
||||
});
|
||||
const $ = cheerio.load(response.data);
|
||||
const list = $('article.entry-list')
|
||||
.slice(0, 10)
|
||||
.map((_, item) => {
|
||||
item = $(item);
|
||||
const a = item.find('a[title]');
|
||||
return {
|
||||
title: a.text(),
|
||||
link: a.attr('href'),
|
||||
pubDate: new Date(item.find('time').attr('datetime')).toUTCString(),
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
const items = await Promise.all(
|
||||
list.map((item) =>
|
||||
ctx.cache.tryGet(item.link, async () => {
|
||||
const detailResponse = await got({
|
||||
method: 'get',
|
||||
url: `https:${item.link}`,
|
||||
});
|
||||
const content = cheerio.load(detailResponse.data);
|
||||
|
||||
item.description = content('div.entry-content').html();
|
||||
|
||||
return item;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
return {
|
||||
title: '199IT - ' + keyword,
|
||||
link: currentUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,60 +0,0 @@
|
||||
const cheerio = require('cheerio');
|
||||
const got = require('@/utils/got');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const url = `https://www.scientificamerican.com/podcast/60-second-science/`;
|
||||
const cover = `https://static.scientificamerican.com/sciam/cache/file/484FA146-8892-477F-B38D18775563CC9E_small.jpg`;
|
||||
|
||||
const res = await got.get(url);
|
||||
const $ = cheerio.load(res.data);
|
||||
const list = $('.underlined_text.t_small').get();
|
||||
|
||||
const out = await Promise.all(
|
||||
list.map(async (item) => {
|
||||
const $ = cheerio.load(item);
|
||||
const fullTitle = $(item).attr('aria-label');
|
||||
const title = fullTitle.substring(0, fullTitle.length - 11);
|
||||
const address = $(item).attr('href');
|
||||
const cache = await ctx.cache.get(address);
|
||||
if (cache) {
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
const res = await got.get(address);
|
||||
const capture = cheerio.load(res.data);
|
||||
|
||||
const tStr = '.article-header__divider > ul > li > span:nth-child(2)';
|
||||
const time = capture(tStr).text();
|
||||
const aStr = '.article-header__divider > ul > li > span:nth-child(1) > span';
|
||||
const author = capture(aStr).text();
|
||||
|
||||
capture('.transcript__close').remove();
|
||||
const intro = capture('.article-media__object').html() + '<br><br>';
|
||||
const contents =
|
||||
intro +
|
||||
capture('.transcript__inner')
|
||||
.html()
|
||||
.replaceAll(/<p>\[?<em>\(?The above text.*this podcast.*?em.*?p>/g, '');
|
||||
const track = capture('.podcasts__media > div > a').attr('href');
|
||||
const single = {
|
||||
title,
|
||||
description: contents,
|
||||
enclosure_url: track,
|
||||
enclosure_type: 'audio/mpeg',
|
||||
link: address,
|
||||
guid: address,
|
||||
author,
|
||||
pubDate: new Date(time).toUTCString(),
|
||||
};
|
||||
ctx.cache.set(address, JSON.stringify(single));
|
||||
return single;
|
||||
})
|
||||
);
|
||||
ctx.state.data = {
|
||||
itunes_author: 'Scientific American',
|
||||
itunes_category: 'Science',
|
||||
image: cover,
|
||||
title: '60-Second Science',
|
||||
link: url,
|
||||
item: out,
|
||||
};
|
||||
};
|
||||
@@ -1,71 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
|
||||
const postTypes = {
|
||||
1: '文字',
|
||||
2: '表情',
|
||||
3: '纯图片',
|
||||
4: '评论',
|
||||
5: '转发',
|
||||
6: '纯视频',
|
||||
7: '图片文字',
|
||||
8: '视频文字',
|
||||
};
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const username = ctx.params.username;
|
||||
|
||||
const url = `https://api.7gogo.jp/web/v2/talks/${username}/posts?talkId=${username}&direction=PREV`;
|
||||
|
||||
const response = await got.get(url);
|
||||
const list = response.data.data;
|
||||
|
||||
const user_display_name = list[0].user.name;
|
||||
const user_description = list[0].user.description;
|
||||
const user_image = list[0].user.coverImageUrl;
|
||||
|
||||
const GetContent = (post) =>
|
||||
post.body &&
|
||||
post.body
|
||||
.map((item) => {
|
||||
switch (item.bodyType) {
|
||||
case 1:
|
||||
return `<p>${item.text.replaceAll(/\n/gm, '<br/>')}</p>`;
|
||||
case 2:
|
||||
return `<img src="${item.image}">`;
|
||||
case 3:
|
||||
return `<img src="${item.image}">`;
|
||||
case 4:
|
||||
return `<blockquote>${item.comment.user.name}:<br/>${item.comment.comment.body.replaceAll(/\n/gm, '<br/>')}</blockquote>`;
|
||||
case 7:
|
||||
return `<blockquote>${item.talk.name}:<br/>${GetContent(item.post)}</blockquote>`;
|
||||
case 8:
|
||||
return `<video src="${item.movieUrlHq}" poster="${item.thumbnailUrl}" controls loop>Video</video>`;
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
})
|
||||
.join('');
|
||||
|
||||
const GetTitle = (post) => {
|
||||
const texts = post.body.filter((s) => s.bodyType === 1);
|
||||
const type_name = postTypes[post.postType];
|
||||
return texts.length === 0 ? type_name : texts[0].text.split('\n')[0];
|
||||
};
|
||||
|
||||
const ProcessFeed = (data) =>
|
||||
data.slice(0, 20).map((item) => ({
|
||||
title: GetTitle(item.post),
|
||||
author: user_display_name,
|
||||
description: GetContent(item.post),
|
||||
pubDate: new Date(item.post.time * 1000).toUTCString(),
|
||||
link: `https://7gogo.jp/${username}/${item.post.postId}`,
|
||||
}));
|
||||
|
||||
ctx.state.data = {
|
||||
title: `${user_display_name} - 755`,
|
||||
image: user_image,
|
||||
description: user_description,
|
||||
link: `https://7gogo.jp/${username}`,
|
||||
item: ProcessFeed(list),
|
||||
};
|
||||
};
|
||||
@@ -1,46 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const url = require('url');
|
||||
|
||||
const host = 'https://99percentinvisible.org/';
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const link = url.resolve(host, 'archives/');
|
||||
const response = await got.get(link);
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const list = $('.content .post-blocks a.post-image')
|
||||
.map((i, e) => $(e).attr('href'))
|
||||
.get();
|
||||
|
||||
const out = await Promise.all(
|
||||
list
|
||||
.filter((e) => e.startsWith(url.resolve(host, 'episode/')))
|
||||
.map(async (itemUrl) => {
|
||||
const cache = await ctx.cache.get(itemUrl);
|
||||
if (cache) {
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const response = await got.get(itemUrl);
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const single = {
|
||||
title: $('article header h1').text().trim(),
|
||||
link: itemUrl,
|
||||
author: '99% Invisible',
|
||||
description: $('article .page-content').html(),
|
||||
pubDate: new Date($('article header .entry-meta time').text()).toUTCString(),
|
||||
};
|
||||
ctx.cache.set(itemUrl, JSON.stringify(single));
|
||||
return single;
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: '99% Invisible Transcript',
|
||||
link,
|
||||
item: out,
|
||||
};
|
||||
};
|
||||
@@ -1,68 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const rootUrl = 'https://amturing.acm.org';
|
||||
const currentUrl = `${rootUrl}/byyear.cfm`;
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: currentUrl,
|
||||
});
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const items = await Promise.all(
|
||||
$('.award-winners-list li')
|
||||
.slice(0, 5)
|
||||
.map(async (_, item) => {
|
||||
item = $(item);
|
||||
|
||||
const year = item.find('span').text().replaceAll(/\(|\)/g, '');
|
||||
const pubDate = new Date(`${year}-12-31`).toUTCString();
|
||||
|
||||
const winnersUrls = [];
|
||||
let winnerResponses = [];
|
||||
|
||||
item.find('a').each(function () {
|
||||
winnersUrls.push(`${rootUrl}${$(this).attr('href')}`);
|
||||
});
|
||||
|
||||
winnerResponses = winnersUrls.map((url) =>
|
||||
got({
|
||||
method: 'get',
|
||||
url,
|
||||
})
|
||||
);
|
||||
|
||||
const description = await Promise.all(winnerResponses).then((winners) => {
|
||||
let winnerDescription = '';
|
||||
|
||||
for (const winner of winners) {
|
||||
const content = cheerio.load(winner.data);
|
||||
const image = content('.featured-photo').html();
|
||||
const column = content('#tertiary-navigation').parent();
|
||||
|
||||
content('#tertiary-navigation').remove();
|
||||
|
||||
winnerDescription += image + column.html();
|
||||
}
|
||||
|
||||
return winnerDescription;
|
||||
});
|
||||
|
||||
return {
|
||||
pubDate,
|
||||
description,
|
||||
title: year,
|
||||
link: currentUrl,
|
||||
};
|
||||
})
|
||||
.get()
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: 'A.M. Turing Award Winners',
|
||||
link: currentUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,48 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const baseUrl = 'https://www.acwifi.net/';
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: baseUrl,
|
||||
});
|
||||
const $ = cheerio.load(response.data);
|
||||
const list = $('div.widget.widget_recent_entries li').get();
|
||||
|
||||
const ProcessFeed = (data) => {
|
||||
const $ = cheerio.load(data);
|
||||
return {
|
||||
desc: $('article.article-content').html(),
|
||||
};
|
||||
};
|
||||
|
||||
const out = await Promise.all(
|
||||
list.map(async (item) => {
|
||||
const $ = cheerio.load(item);
|
||||
const $a = $('a');
|
||||
const link = $a.attr('href');
|
||||
|
||||
const cache = await ctx.cache.get(link);
|
||||
if (cache) {
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: link,
|
||||
});
|
||||
const feed = ProcessFeed(response.data);
|
||||
const description = feed.desc;
|
||||
|
||||
const single = {
|
||||
title: $a.text(),
|
||||
description,
|
||||
link,
|
||||
};
|
||||
ctx.cache.set(link, JSON.stringify(single));
|
||||
return single;
|
||||
})
|
||||
);
|
||||
ctx.state.data = { title: '路由器交流', link: baseUrl, item: out };
|
||||
};
|
||||
@@ -1,67 +0,0 @@
|
||||
const url = require('url');
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
const config = {
|
||||
index: {
|
||||
link: 'https://www.adquan.com/',
|
||||
title: '首页',
|
||||
},
|
||||
info: {
|
||||
link: 'https://www.adquan.com/info',
|
||||
title: '行业观察',
|
||||
},
|
||||
creative: {
|
||||
link: 'https://creative.adquan.com/',
|
||||
title: '案例库',
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const cfg = ctx.params.type ? config[ctx.params.type] : config.index;
|
||||
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: cfg.link,
|
||||
});
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
let where;
|
||||
switch (cfg.title) {
|
||||
case '首页':
|
||||
where = $('div.w_l_inner h2.wrok_l_title a');
|
||||
break;
|
||||
case '行业观察':
|
||||
where = $('div.article_rel div.rel_write a p').parent();
|
||||
break;
|
||||
case '案例库':
|
||||
where = $('#showcontent li h2 a');
|
||||
break;
|
||||
}
|
||||
|
||||
const list = where
|
||||
.map((_, item) => {
|
||||
item = $(item);
|
||||
return {
|
||||
title: item.text(),
|
||||
link: url.resolve(cfg.link, item.attr('href')),
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
ctx.state.data = {
|
||||
title: `广告网 - ${cfg.title}`,
|
||||
link: cfg.link,
|
||||
item: await Promise.all(
|
||||
list.map((item) =>
|
||||
ctx.cache.tryGet(item.link, async () => {
|
||||
const detailResponse = await got({ method: 'get', url: item.link });
|
||||
const content = cheerio.load(detailResponse.data);
|
||||
item.pubDate = new Date(content('p.text_time2 span').eq(0).text()).toUTCString();
|
||||
item.description = content('div.con_Text').html();
|
||||
return item;
|
||||
})
|
||||
)
|
||||
),
|
||||
};
|
||||
};
|
||||
@@ -1,48 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const rootUrl = 'https://aflcio.org';
|
||||
const currentUrl = `${rootUrl}/blog`;
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: currentUrl,
|
||||
});
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const list = $('article')
|
||||
.map((_, item) => {
|
||||
item = $(item);
|
||||
const title = item.find('h1 a');
|
||||
return {
|
||||
title: title.text(),
|
||||
link: `${rootUrl}${title.attr('href')}`,
|
||||
pubDate: new Date(item.find('time').attr('datetime')).toUTCString(),
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
const items = await Promise.all(
|
||||
list.map((item) =>
|
||||
ctx.cache.tryGet(item.link, async () => {
|
||||
const detailResponse = await got({
|
||||
method: 'get',
|
||||
url: item.link,
|
||||
});
|
||||
const content = cheerio.load(detailResponse.data);
|
||||
|
||||
item.description = content('.section-article-body').html();
|
||||
item.author = detailResponse.data.match(/entityName":"(.*)","entityType"/)[1];
|
||||
|
||||
return item;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: $('title').text(),
|
||||
link: currentUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,134 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const id = ctx.params.id;
|
||||
const sort = ctx.params.sort || 'new';
|
||||
|
||||
let url = 'https://api.yanxishe.com/api?page=1&size=30&parent_tag=';
|
||||
|
||||
url += id === 'all' ? '&tag=' : `&tag=${id}`;
|
||||
if (sort === 'hot') {
|
||||
url += '&is_hot=1&is_recommend=0';
|
||||
} else if (sort === 'recommend') {
|
||||
url += '&is_hot=0&is_recommend=1';
|
||||
} else {
|
||||
url += '&is_hot=0&is_recommend=0';
|
||||
}
|
||||
|
||||
const response = await got({
|
||||
method: 'GET',
|
||||
url,
|
||||
headers: {
|
||||
Referer: `https://www.yanxishe.com/`,
|
||||
},
|
||||
});
|
||||
|
||||
const ProcessFeed = (type, data, id) => {
|
||||
let description = '';
|
||||
let author = '';
|
||||
let link;
|
||||
switch (type) {
|
||||
case 'blog': // 博客
|
||||
description = data.content;
|
||||
author = data.user.nickname;
|
||||
link = data.relation_special ? `https://www.yanxishe.com/columnDetail/${id}` : `https://www.yanxishe.com/blogDetail/${id}`;
|
||||
break;
|
||||
case 'question': // 问答
|
||||
description = data.content;
|
||||
author = data.user.nickname;
|
||||
link = `https://www.yanxishe.com/questionDetail/${id}`;
|
||||
break;
|
||||
case 'article': // 翻译
|
||||
description = `<table><tr><td width="50%"> ${data.title} </td><td> ${data.zh_title} </td></tr>`;
|
||||
for (const element of data.paragraphs) {
|
||||
description += `<tr><td> ${element.content} </td><td> ${element.zh_content.content} </td></tr>`;
|
||||
}
|
||||
description += `</table>
|
||||
<style>
|
||||
table,
|
||||
table tr th,
|
||||
table tr td {
|
||||
border: 1px solid #000000;
|
||||
padding: 10px;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
</style>`;
|
||||
author = data.user.nickname;
|
||||
link = `https://www.yanxishe.com/TextTranslation/${id}`;
|
||||
break;
|
||||
case 'paper': // 论文
|
||||
description = `<h3>标题</h3><p> ${data.paper.title} </p>`;
|
||||
description += `<h3>作者</h3><p> ${data.paper.author.toString()} </p>`;
|
||||
description += `<h3>下载地址</h3><p><a href=" ${data.paper.url} ">${data.paper.url}</a></p>`;
|
||||
description += `<h3>发布时间</h3><p> ${data.paper.publish_time} </p>`;
|
||||
description += `<h3>摘要</h3><p> ${data.paper.description} </p>`;
|
||||
description += `<h3>推荐理由</h3><p><b> ${data.paper.userInfo.nickname} </b>: ${data.paper.recommend_reason} </p>`;
|
||||
author = data.paper.userInfo.nickname;
|
||||
link = `https://paper.yanxishe.com/review/${id}`;
|
||||
break;
|
||||
default:
|
||||
description = '暂不支持此类型,请到 https://github.com/DIYgod/RSSHub/issues 反馈';
|
||||
break;
|
||||
}
|
||||
|
||||
// 提取内容
|
||||
return { author, description, link };
|
||||
};
|
||||
|
||||
const items = await Promise.all(
|
||||
response.data.data.all.map(async (item) => {
|
||||
let itemUrl = `https://api.yanxishe.com/api/sthread/${item.id}?token=null`;
|
||||
|
||||
switch (item.type) {
|
||||
case 'blog':
|
||||
itemUrl += '&type=null';
|
||||
|
||||
break;
|
||||
|
||||
case 'article':
|
||||
itemUrl = `https://api.yanxishe.com/api/stranslate/article/${item.id}?token=null&type=null`;
|
||||
|
||||
break;
|
||||
|
||||
case 'paper':
|
||||
itemUrl = `https://api.yanxishe.com/api/spaper/detail?token=null&id=${item.id}`;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error(`Unknown type: ${item.type}`);
|
||||
}
|
||||
|
||||
const cache = await ctx.cache.get(itemUrl);
|
||||
if (cache) {
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: itemUrl,
|
||||
});
|
||||
|
||||
const result = ProcessFeed(item.type, response.data.data, item.id);
|
||||
|
||||
const single = {
|
||||
title: item.zh_title,
|
||||
description: result.description,
|
||||
pubDate: new Date(Number.parseFloat(item.published_time + '000')).toUTCString(),
|
||||
link: result.link,
|
||||
author: result.author,
|
||||
};
|
||||
ctx.cache.set(itemUrl, JSON.stringify(single));
|
||||
return single;
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `AI研习社`,
|
||||
link: `https://ai.yanxishe.com/`,
|
||||
description: '专注AI技术发展与AI工程师成长的求知平台',
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,93 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
const getCacheParsed = async (ctx, key) => {
|
||||
const value = await ctx.cache.get(key);
|
||||
if (value) {
|
||||
return JSON.parse(value);
|
||||
}
|
||||
};
|
||||
|
||||
const generateResponse = (items) => ({
|
||||
// 源标题
|
||||
title: 'AlgoCasts',
|
||||
// 源链接
|
||||
link: `https://www.algocasts.com`,
|
||||
// 源说明
|
||||
description: `AlgoCasts 旨在用心做好每一个算法讲解视频。每个视频包含两个部分:题目的剖析讲解以及编码,力求在讲解清楚到位的基础上,尽可能地保持视频精简短小,让大家可以在碎片时间里进行学习,并收获这些算法题背后的思想与乐趣。`,
|
||||
item: items.map((item) => ({
|
||||
// 文章标题
|
||||
title: `${item.title} | AlgoCasts 视频更新`,
|
||||
// 文章正文
|
||||
description: item.description || '',
|
||||
// 文章链接
|
||||
link: item.link,
|
||||
})),
|
||||
});
|
||||
|
||||
const makeFull = (ctx, infos) => {
|
||||
const limit = 10; // 仅获取最近十条信息(避免无意义请求)
|
||||
infos = infos.slice(0, limit);
|
||||
|
||||
return Promise.all(
|
||||
infos.map(async (item) => {
|
||||
const cacheKey = `episode-${item.episode}`;
|
||||
|
||||
// 尝试从缓存查找相关数据
|
||||
let info = await getCacheParsed(ctx, cacheKey);
|
||||
// console.log(info);
|
||||
if (info) {
|
||||
// 找到 -> 直接返回
|
||||
return info;
|
||||
} else {
|
||||
// 未找到 -> 返回
|
||||
info = item;
|
||||
}
|
||||
// 抓取详细信息
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: info.link,
|
||||
});
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const badges = [];
|
||||
$('.badge').each((index, badge) => {
|
||||
const text = $(badge).text();
|
||||
|
||||
if (text !== '讨论') {
|
||||
badges.push(text);
|
||||
}
|
||||
});
|
||||
|
||||
info.description = `<h1>${info.title}</h1><div>${badges.join(' | ')}</div><div>${$('#my-content p').html()}</div>`;
|
||||
ctx.cache.set(cacheKey, info);
|
||||
|
||||
// console.log(info);
|
||||
|
||||
return info;
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: 'http://algocasts.io/episodes',
|
||||
});
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
const infos = [];
|
||||
|
||||
$('tr')
|
||||
.slice(1)
|
||||
.each((i, e) => {
|
||||
const id = $(e).find('th').text();
|
||||
const titleLabel = $(e).find('td a');
|
||||
const title = `${id}. ${titleLabel.text()}`;
|
||||
const episode = titleLabel.attr('href').trim().split('/')[2];
|
||||
const link = `http://algocasts.io/episodes/${episode}`;
|
||||
|
||||
infos.push({ id, title, episode, link });
|
||||
});
|
||||
ctx.state.data = generateResponse(await makeFull(ctx, infos));
|
||||
};
|
||||
@@ -1,42 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const url = require('url');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const { order = 'best' } = ctx.params;
|
||||
const link = `https://allpoetry.com/poems/about/spotlight-oldpoem?order=${order}}`;
|
||||
const host = 'https://allpoetry.com/';
|
||||
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: link,
|
||||
});
|
||||
|
||||
const data = response.data;
|
||||
|
||||
const $ = cheerio.load(data);
|
||||
|
||||
const items = $('.sub')
|
||||
.get()
|
||||
.map((e) => {
|
||||
let itemUrl = $(e).find('h1.title > a').attr('href');
|
||||
|
||||
itemUrl = url.resolve(host, itemUrl);
|
||||
|
||||
const single = {
|
||||
title: $(e).find('h1.title > a').text(),
|
||||
description: $(e).find('div.poem_body').html(),
|
||||
link: itemUrl,
|
||||
author: $(e).find('div.bio >a ').attr('data-name'),
|
||||
guid: itemUrl,
|
||||
};
|
||||
|
||||
return single;
|
||||
});
|
||||
|
||||
ctx.state.data = {
|
||||
title: `All Poetry - ${order.toUpperCase() + order.slice(1)}`,
|
||||
link,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,7 +0,0 @@
|
||||
const utils = require('./utils');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const currentUrl = `${ctx.params.model}/fresh?${ctx.params.lang ? 'lang=' + ctx.params.lang : ''}${ctx.params.type ? '&compatible=' + ctx.params.type : ''}`;
|
||||
|
||||
ctx.state.data = await utils(ctx, currentUrl);
|
||||
};
|
||||
@@ -1,7 +0,0 @@
|
||||
const utils = require('./utils');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const currentUrl = `search/${ctx.params.model}/tags/${ctx.params.keyword ?? ''}${ctx.params.sortBy ? '?sortby=' + ctx.params.sortBy : ''}`;
|
||||
|
||||
ctx.state.data = await utils(ctx, currentUrl);
|
||||
};
|
||||
@@ -1,9 +0,0 @@
|
||||
const utils = require('./utils');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const currentUrl = `${ctx.params.model}/top?${ctx.params.lang ? 'lang=' + ctx.params.lang : ''}${ctx.params.type ? '&compatible=' + ctx.params.type : ''}${ctx.params.sortBy ? '&sortby=' + ctx.params.sortBy : ''}${
|
||||
ctx.params.time ? '&topof=' + ctx.params.time : ''
|
||||
}`;
|
||||
|
||||
ctx.state.data = await utils(ctx, currentUrl);
|
||||
};
|
||||
@@ -1,7 +0,0 @@
|
||||
const utils = require('./utils');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const currentUrl = `${ctx.params.model}/updated?${ctx.params.lang ? 'lang=' + ctx.params.lang : ''}${ctx.params.type ? '&compatible=' + ctx.params.type : ''}`;
|
||||
|
||||
ctx.state.data = await utils(ctx, currentUrl);
|
||||
};
|
||||
@@ -1,45 +0,0 @@
|
||||
const url = require('url');
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx, currentUrl) => {
|
||||
const rootUrl = `https://amazfitwatchfaces.com/`;
|
||||
currentUrl = `${rootUrl}${currentUrl}`;
|
||||
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: currentUrl,
|
||||
});
|
||||
const $ = cheerio.load(response.data);
|
||||
const list = $('#wf-row div.col-md-3')
|
||||
.slice(0, 10)
|
||||
.map((_, item) => {
|
||||
item = $(item);
|
||||
return {
|
||||
link: url.resolve(rootUrl, $(item).find('a.wf-act').attr('href')),
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
const items = await Promise.all(
|
||||
list.map((item) =>
|
||||
ctx.cache.tryGet(item.link, async () => {
|
||||
const detailResponse = await got({ method: 'get', url: item.link });
|
||||
const content = cheerio.load(detailResponse.data);
|
||||
const date = content('i.fa-calendar').parent().find('span').text();
|
||||
const ymd = date.split(' ')[0];
|
||||
|
||||
item.title = `[${content('code').text()}] ${content('title').text().split(' - ')[0]}`;
|
||||
item.description = `<img src="${content('#watchface-preview').attr('src')}"><br>${content('div.unicodebidi').text()}`;
|
||||
item.pubDate = new Date(`${ymd.split('.')[2]}-${ymd.split('.')[1]}-${ymd.split('.')[0]} ${date.split(' ')[1]}`).toUTCString();
|
||||
return item;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
return {
|
||||
title: `${$('title').text().split('|')[0]} | Amazfit Watch Faces`,
|
||||
link: currentUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,114 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const config = require('@/config').value;
|
||||
const cheerio = require('cheerio');
|
||||
const url = 'https://download.amd.com/drivers/xml/driver_09_us.xml';
|
||||
|
||||
// 06/10/2020 -> Wed Jun 10 2020 00:00:00
|
||||
function convertDate(dateStr) {
|
||||
const [month, day, year] = dateStr.split('/').map((x) => Number.parseInt(x, 10));
|
||||
const date = new Date();
|
||||
date.setFullYear(year, month - 1, day);
|
||||
date.setHours(0, 0, 0, 0);
|
||||
return date;
|
||||
}
|
||||
|
||||
function versionToRss(info, isBeta) {
|
||||
const date = convertDate(info.releaseDate);
|
||||
return {
|
||||
title: `Radeon Software ${info.edition} Edition ${info.version}` + (isBeta ? ' Beta' : ''),
|
||||
description: `内部版本: ${info.internal}<br>发布时间: ${date.getFullYear()}-${date.getMonth() + 1}-${date.getDay()}`,
|
||||
pubDate: date.toUTCString(),
|
||||
link: info.releaseNotes,
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
let data = await ctx.cache.get(url, false);
|
||||
if (!data) {
|
||||
const res = await got.get(url);
|
||||
data = res.data;
|
||||
ctx.cache.set(url, data, config.cache.contentExpire);
|
||||
}
|
||||
|
||||
const $ = cheerio.load(data, { xmlMode: true });
|
||||
const productfamily = $('driverSelector > platform > productfamily')[0];
|
||||
|
||||
let product;
|
||||
for (const node of productfamily.childNodes) {
|
||||
if (node.tagName !== 'product') {
|
||||
continue;
|
||||
}
|
||||
|
||||
const ids = node.attribs.ids.split(', ');
|
||||
if (!ids.includes(ctx.params.id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ctx.params.rid && node.attribs.rid !== ctx.params.rid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
product = node;
|
||||
break;
|
||||
}
|
||||
|
||||
if (product) {
|
||||
let latestWHQL = '';
|
||||
let latestBeta = '';
|
||||
let whql, beta;
|
||||
for (const node of product.childNodes) {
|
||||
if (node.tagName !== 'version') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (node.attribs.number > latestWHQL) {
|
||||
latestWHQL = node.attribs.number;
|
||||
whql = {
|
||||
version: node.attribs.number,
|
||||
internal: node.attribs.internal,
|
||||
edition: node.attribs.WHQLEdition,
|
||||
releaseDate: node.attribs.whqlreleasedate,
|
||||
releaseNotes: node.attribs.rnoteswin,
|
||||
};
|
||||
}
|
||||
|
||||
if (node.attribs.betaname > latestBeta) {
|
||||
latestBeta = node.attribs.betaname;
|
||||
beta = {
|
||||
version: node.attribs.betaname,
|
||||
internal: node.attribs.beta,
|
||||
edition: node.attribs.BETAEdition,
|
||||
releaseDate: node.attribs.betareleasedate,
|
||||
releaseNotes: node.attribs.betarnoteswin,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const item = [];
|
||||
if (whql || beta) {
|
||||
if (whql) {
|
||||
try {
|
||||
item.push(versionToRss(whql, false));
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
if (beta) {
|
||||
try {
|
||||
item.push(versionToRss(beta, true));
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx.state.data = {
|
||||
title: `${product.attribs.label} (ids:${product.attribs.ids} rid:${product.attribs.rid})`,
|
||||
link: 'https://www.amd.com/zh-hans/support',
|
||||
allowEmpty: true,
|
||||
item,
|
||||
};
|
||||
} else {
|
||||
ctx.throw(404, 'Product Not Found');
|
||||
}
|
||||
};
|
||||
@@ -1,33 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const rootUrl = 'https://anytxt.net';
|
||||
const currentUrl = `${rootUrl}/download`;
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: currentUrl,
|
||||
});
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const items = $('.has-medium-font-size')
|
||||
.map((_, item) => {
|
||||
item = $(item);
|
||||
const date = item.text().replace(':', '');
|
||||
|
||||
return {
|
||||
title: date,
|
||||
link: currentUrl,
|
||||
pubDate: new Date(date).toUTCString(),
|
||||
description: `<ol>${item.next().html()}</ol>`,
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
ctx.state.data = {
|
||||
title: 'Release Notes - AnyTXT',
|
||||
link: currentUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,93 +0,0 @@
|
||||
// Warning: The author knows nothing about javascript!
|
||||
|
||||
// params:
|
||||
// count? : count of new-books
|
||||
|
||||
const got = require('@/utils/got'); // get web content
|
||||
const cheerio = require('cheerio'); // html parser
|
||||
const entities = require('entities');
|
||||
|
||||
const base_url = 'https://www.aozora.gr.jp/index_pages/';
|
||||
module.exports = async (ctx) => {
|
||||
// get the update list
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: base_url + 'whatsnew1.html',
|
||||
});
|
||||
const data = response.data; // content is html format
|
||||
|
||||
const $ = cheerio.load(data);
|
||||
const list = $('table.list tr');
|
||||
|
||||
// get how many new-books. amount in this page is 50
|
||||
let count = Number.parseInt(ctx.params.count);
|
||||
if (Number.isNaN(count) || count < 1) {
|
||||
count = 10; // default count of new-book list
|
||||
} else if (count > 50) {
|
||||
count = 50;
|
||||
}
|
||||
|
||||
// parse book urls
|
||||
const detail_urls = [];
|
||||
for (let i = 1; i < count + 1; ++i) {
|
||||
// i = 1: first tr is table title, ignore
|
||||
const link = base_url + $(list[i]).find('a').attr('href');
|
||||
detail_urls.push(link);
|
||||
}
|
||||
|
||||
// get book-cards
|
||||
const responses = await Promise.all(detail_urls.map((url) => got(url)));
|
||||
const cards = responses.map(({ data }) => data);
|
||||
|
||||
// get real data to feed
|
||||
const book_list = [];
|
||||
for (let i = 0; i < count; ++i) {
|
||||
const $ = cheerio.load(cards[i]);
|
||||
const link = $('meta[property="og:url"]').attr('content');
|
||||
const link_dir = link.replaceAll(/\/[^/]*$/g, '/');
|
||||
const title_info = $('table[summary="タイトルデータ"] > tbody > tr');
|
||||
let author = '';
|
||||
let title = '';
|
||||
let title_sub = '';
|
||||
for (const element of title_info) {
|
||||
const tmp = entities.decodeXML($(element).html()); // should convert from escaped to unicode
|
||||
if (tmp.includes('作品名:')) {
|
||||
title = $(element).find('td:nth-child(2)').text();
|
||||
}
|
||||
if (tmp.includes('副題:')) {
|
||||
title_sub = $(element).find('td:nth-child(2)').text();
|
||||
}
|
||||
if (tmp.includes('著者名:')) {
|
||||
author = $(element).find('td:nth-child(2)').text();
|
||||
}
|
||||
}
|
||||
if (title_sub !== '') {
|
||||
title += ' —— ' + title_sub;
|
||||
}
|
||||
const pub_date_raw = $('table[summary="底本データ"] > tbody > tr:nth-child(3) > td:nth-child(2)').text();
|
||||
const pub_date_num = pub_date_raw.replaceAll(/(.*)|日/g, '').replaceAll(/[年月]/g, '-');
|
||||
const pub_date = new Date(pub_date_num).toUTCString();
|
||||
const full_text_relative_link = $('table.download > tbody > tr:nth-child(3) > td:nth-child(3) > a').attr('href');
|
||||
const full_text_link = link_dir + full_text_relative_link;
|
||||
const full_text_link_html = '<a href="' + full_text_link + '">いますぐXHTML版で読む</a><br>';
|
||||
const summury = $('table[summary="作品データ"]')
|
||||
.html()
|
||||
.replaceAll('href="', 'href="' + link_dir);
|
||||
|
||||
const item = {
|
||||
title,
|
||||
author,
|
||||
pubDate: pub_date,
|
||||
link,
|
||||
description: full_text_link_html + summury,
|
||||
};
|
||||
book_list.push(item);
|
||||
}
|
||||
|
||||
// feed the data
|
||||
ctx.state.data = {
|
||||
title: '青空文庫新着リスト',
|
||||
link: base_url + 'whatsnew1.html',
|
||||
item: book_list,
|
||||
};
|
||||
};
|
||||
@@ -1,66 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
ctx.params.caty = ctx.params.caty || 'highlights';
|
||||
ctx.params.time = ctx.params.time || '24h';
|
||||
|
||||
const times = ['24h', 'week', 'alltime'];
|
||||
const rootUrl = `https://www.app-sales.net/${ctx.params.caty}/#!`;
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: rootUrl,
|
||||
});
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
if (ctx.params.caty === 'mostwanted') {
|
||||
for (const i of times) {
|
||||
if (i !== ctx.params.time) {
|
||||
$(`#charts-${i}`).remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$('i,img.play-icon-small').remove();
|
||||
|
||||
const items = $('div.sale-list-item')
|
||||
.map((_, item) => {
|
||||
item = $(item);
|
||||
|
||||
const icon = item.find('div.app-icon').html();
|
||||
const name = item.find('p.app-name').text();
|
||||
const developer = item.find('p.app-dev').text();
|
||||
const oldPrice = item.find('div.price-old').text();
|
||||
const newPrice = item.find('div.price-new').text();
|
||||
const discount = item.find('div.price-disco').text();
|
||||
const rating = item.find('p.rating').text();
|
||||
const downloads = item.find('p.downloads').text();
|
||||
const bookmarks = item.find('p.bookmarks').text();
|
||||
|
||||
const description =
|
||||
`${icon}<p>${name}</p><table cellspacing="5">` +
|
||||
`<tr><td> Developer </td><td> ${developer} </td></tr>` +
|
||||
`<tr><td> Bookmarks </td><td> ${bookmarks} </td></tr>` +
|
||||
(rating ? `<tr><td> Rating </td><td> ${rating} </td></tr>` : '') +
|
||||
(downloads ? `<tr><td> Downloads </td><td> ${downloads} </td></tr>` : '') +
|
||||
(discount ? `<tr><td> Discount </td><td> ${discount} </td></tr>` : '') +
|
||||
(oldPrice ? `<tr><td> Old Price </td><td> ${oldPrice} </td></tr>` : '') +
|
||||
(newPrice ? `<tr><td> New Price </td><td> ${newPrice} </td></tr>` : '') +
|
||||
'</table>';
|
||||
|
||||
return {
|
||||
title: `${name} ${newPrice ? '[' + newPrice + ']' : ''}`,
|
||||
link: item.find('a.waves-effect').attr('href'),
|
||||
description,
|
||||
author: developer,
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
ctx.state.data = {
|
||||
title: $('title').text(),
|
||||
link: rootUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,46 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const city = ctx.params.city;
|
||||
const pollution = ctx.params.pollution || [];
|
||||
const pollutionType = {
|
||||
so2: 'so2',
|
||||
no2: 'no2',
|
||||
co: 'co',
|
||||
o3: 'O3',
|
||||
pm25: 'PM2.5',
|
||||
pm10: 'PM10',
|
||||
};
|
||||
const area = isNaN(city) ? city : `@${city}`;
|
||||
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: `http://aqicn.org/aqicn/json/android/${area}/json`,
|
||||
});
|
||||
const data = response.data;
|
||||
|
||||
const pollutionDetailed =
|
||||
pollution.length === 0
|
||||
? ''
|
||||
: pollution.split(',').reduce((result, item) => {
|
||||
result += `${pollutionType[item].toUpperCase()}:<b>${
|
||||
typeof data.historic[pollutionType[item]] === 'object' ? data.historic[pollutionType[item]][Object.keys(data.historic[pollutionType[item]])[0]] : data.historic[pollutionType[item]][0]
|
||||
}</b><br>`;
|
||||
return result;
|
||||
}, '');
|
||||
|
||||
ctx.state.data = {
|
||||
title: `${data.namena}AQI`,
|
||||
link: `https://aqicn.org/city/${data.ids.path}`,
|
||||
description: `${data.namena}AQI-aqicn.org`,
|
||||
item: [
|
||||
{
|
||||
title: `${data.namena}实时空气质量(AQI)${data.utimecn}`,
|
||||
description: `${data.infocn}<br>风力:<b>${data.cwind[0]}</b>级<br>AQI:<b>${data.aqi}</b><br>${pollutionDetailed}<img src="${data.wgt}">`,
|
||||
pubDate: new Date(data.time * 1000).toUTCString(),
|
||||
guid: data.time,
|
||||
link: `https://aqicn.org/city/${data.ids.path}`,
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
||||
@@ -1,47 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const parser = require('@/utils/rss-parser');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const feed = await parser.parseURL('https://feeds.feedburner.com/ArchdailyCN');
|
||||
|
||||
const ProcessFeed = async (link) => {
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: link,
|
||||
});
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
// 提取内容
|
||||
return $('#single-content').html();
|
||||
};
|
||||
|
||||
const items = await Promise.all(
|
||||
feed.items.map(async (item) => {
|
||||
const cache = await ctx.cache.get(item.link);
|
||||
if (cache) {
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const description = await ProcessFeed(item.link);
|
||||
|
||||
const single = {
|
||||
title: item.title,
|
||||
description,
|
||||
pubDate: item.pubDate,
|
||||
link: item.link,
|
||||
author: item.author,
|
||||
};
|
||||
ctx.cache.set(item.link, JSON.stringify(single));
|
||||
return single;
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: feed.title,
|
||||
link: feed.link,
|
||||
description: feed.description,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,28 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const currentUrl = `http://export.arxiv.org/api/query?${ctx.params.query}`;
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: currentUrl,
|
||||
});
|
||||
const $ = cheerio.load(response.data);
|
||||
const list = $('entry')
|
||||
.map((_, item) => {
|
||||
item = $(item);
|
||||
return {
|
||||
title: item.find('title').text(),
|
||||
link: item.find('link[type="text/html"]').attr('href'),
|
||||
pubDate: new Date(item.find('published').text()).toUTCString(),
|
||||
description: item.find('summary').text(),
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
ctx.state.data = {
|
||||
title: 'arXiv (' + ctx.params.query + ')',
|
||||
link: currentUrl,
|
||||
item: list,
|
||||
};
|
||||
};
|
||||
@@ -1,90 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
const categories = {
|
||||
obituaries: '/obituaries',
|
||||
yoron: '/politics/yoron',
|
||||
baseball: '/sports/baseball',
|
||||
soccer: '/sports/soccer',
|
||||
sumo: '/sports/sumo',
|
||||
winter_figureskate: '/sports/winter/figureskate',
|
||||
golf: '/sports/golf',
|
||||
general: '/sports/general',
|
||||
olympics: '/olympics',
|
||||
paralympics: '/paralympics',
|
||||
eco: '/eco',
|
||||
igo: '/igo',
|
||||
shougi: '/shougi',
|
||||
eldercare: '/national/eldercare',
|
||||
hataraku: '/special/hataraku',
|
||||
food: '/culture/food',
|
||||
gassho: '/edu/gassho',
|
||||
suisogaku: '/edu/suisogaku',
|
||||
hagukumu: '/edu/hagukumu',
|
||||
msta: '/msta',
|
||||
};
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const genre = ctx.params.genre || '';
|
||||
const category = ctx.params.category || '';
|
||||
|
||||
const rootUrl = 'https://www.asahi.com';
|
||||
let currentUrl;
|
||||
if (genre) {
|
||||
if (category) {
|
||||
currentUrl = category in categories ? `${rootUrl}${categories[category]}` : `${rootUrl}/${genre}/list/${category}.html`;
|
||||
} else {
|
||||
currentUrl = `${rootUrl}/${genre}`;
|
||||
}
|
||||
} else {
|
||||
currentUrl = `${rootUrl}${'/news/history.html'}`;
|
||||
}
|
||||
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: currentUrl,
|
||||
});
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
$('.Time').remove();
|
||||
|
||||
const list = $('#MainInner .Section .List li a')
|
||||
.slice(0, 6)
|
||||
.map((_, item) => {
|
||||
item = $(item);
|
||||
const link = item.attr('href');
|
||||
|
||||
return {
|
||||
link: link.includes('//') ? `https:${link}` : `${rootUrl}${link}`,
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
const items = await Promise.all(
|
||||
list.map((item) =>
|
||||
ctx.cache.tryGet(item.link, async () => {
|
||||
const detailResponse = await got({
|
||||
method: 'get',
|
||||
url: item.link,
|
||||
});
|
||||
const content = cheerio.load(detailResponse.data);
|
||||
|
||||
content('._30SFw, .-Oj2D, .notPrint').remove();
|
||||
|
||||
item.description = content('._3YqJ1').html();
|
||||
item.title = content('meta[name="TITLE"]').attr('content');
|
||||
item.pubDate = Date.parse(content('meta[name="pubdate"]').attr('content'));
|
||||
|
||||
return item;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: $('title').text(),
|
||||
link: currentUrl,
|
||||
item: items,
|
||||
description: '朝日新聞社のニュースサイト、朝日新聞デジタルの社会ニュースについてのページです',
|
||||
};
|
||||
};
|
||||
@@ -1,39 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const rootUrl = 'https://www.asml.com';
|
||||
const currentUrl = `${rootUrl}/en/news/press-releases`;
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: currentUrl,
|
||||
});
|
||||
|
||||
const list = response.data.match(/<a class="results-list__listitem" href="(.*)">/g).map((item) => ({
|
||||
link: `${rootUrl}${item.split('href="')[1].replace('">', '')}`,
|
||||
}));
|
||||
|
||||
const items = await Promise.all(
|
||||
list.map((item) =>
|
||||
ctx.cache.tryGet(item.link, async () => {
|
||||
const detailResponse = await got({
|
||||
method: 'get',
|
||||
url: item.link,
|
||||
});
|
||||
const content = cheerio.load(detailResponse.data);
|
||||
|
||||
item.title = content('title').text().replace('| ASML', '');
|
||||
item.description = content('.longcopy').html();
|
||||
item.pubDate = new Date(detailResponse.data.match(/"datePublished": "(.*)",/)[1]).toUTCString();
|
||||
|
||||
return item;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: 'Press releases | ASML',
|
||||
link: currentUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,69 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const link = `https://www.autotrader.co.uk/results-car-search?${ctx.params.query}`;
|
||||
const response = await got.get(link);
|
||||
|
||||
const $ = cheerio.load(response.data.html);
|
||||
|
||||
const idList = $('li.search-page__result').slice(0, 10).get();
|
||||
|
||||
const items = await Promise.all(
|
||||
idList.map(async (item) => {
|
||||
const link = `https://www.autotrader.co.uk/classified/advert/${item.attribs.id}`;
|
||||
|
||||
const cache = await ctx.cache.get(link);
|
||||
|
||||
if (cache) {
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const response = await got.get(link);
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
let keyFacts = '<table><tr>';
|
||||
$('.keyFacts__list .keyFacts__label').each((i, e) => {
|
||||
keyFacts += `<td>${$(e).text()}</td>`;
|
||||
if ((i + 1) % 4 === 0) {
|
||||
keyFacts += '</tr><tr>';
|
||||
}
|
||||
});
|
||||
keyFacts += '</tr><tr>';
|
||||
|
||||
$('.fpaSpecifications__economy .fpaSpecifications__listItem').each((i, e) => {
|
||||
keyFacts += `<td>${$(e).find('.fpaSpecifications__term').text()}: ${$(e).find('.fpaSpecifications__description').text()}</td>`;
|
||||
if ((i + 1) % 4 === 0) {
|
||||
keyFacts += '</tr><tr>';
|
||||
}
|
||||
});
|
||||
|
||||
keyFacts += '</tr></table><br/>';
|
||||
|
||||
let images = '';
|
||||
|
||||
$('.fpa-image-overlay img').each((i, e) => {
|
||||
images += `<img src='${$(e).attr('data-src')}'/><br/>`;
|
||||
});
|
||||
|
||||
const description = keyFacts + images + $('meta[name="og:description"]').attr('content');
|
||||
|
||||
const title = `「${$('.fpaGallery__priceLabel').text()}」${$('meta[name="og:title"]').attr('content')}`;
|
||||
|
||||
const single = {
|
||||
title,
|
||||
description,
|
||||
pubDate: new Date().toISOString(),
|
||||
link,
|
||||
};
|
||||
ctx.cache.set(link, JSON.stringify(single));
|
||||
return single;
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: 'Auto Trader',
|
||||
link,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,36 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const name = ctx.params.name;
|
||||
const url = ctx.params.type ? `https://www.av01.tv/actor/${name}&o=${ctx.params.type}` : `https://www.av01.tv/actor/${name}`;
|
||||
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url,
|
||||
});
|
||||
|
||||
const data = response.data;
|
||||
|
||||
const $ = cheerio.load(data);
|
||||
const list = $('div.col-sm-6.col-md-4.col-lg-4');
|
||||
|
||||
ctx.state.data = {
|
||||
title: `${name}的影片`,
|
||||
description: `${name}的影片`,
|
||||
link: `https://www.av01.tv/actor/${name}`,
|
||||
item:
|
||||
list &&
|
||||
list
|
||||
.map((index, item) => {
|
||||
item = $(item);
|
||||
const itemPicUrl = item.find('img').attr('data-src');
|
||||
return {
|
||||
title: item.find('span.video-title.title-truncate.m-t-5').text(),
|
||||
description: `翻译${item.find('div.video-added.title-truncate').text()}<br><img src="${itemPicUrl}">`,
|
||||
link: `https://www.av01.tv/${item.find('a').attr('href')}`,
|
||||
};
|
||||
})
|
||||
.get(),
|
||||
};
|
||||
};
|
||||
@@ -1,36 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const name = ctx.params.name;
|
||||
const url = ctx.params.type ? `https://www.av01.tv/tag/${name}&o=${ctx.params.type}` : `https://www.av01.tv/tag/${name}`;
|
||||
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url,
|
||||
});
|
||||
|
||||
const data = response.data;
|
||||
|
||||
const $ = cheerio.load(data);
|
||||
const list = $('div.col-sm-6.col-md-4.col-lg-4');
|
||||
|
||||
ctx.state.data = {
|
||||
title: `${name}类型的影片`,
|
||||
description: `${name}类型的影片`,
|
||||
link: `https://www.av01.tv/tag/${name}`,
|
||||
item:
|
||||
list &&
|
||||
list
|
||||
.map((index, item) => {
|
||||
item = $(item);
|
||||
const itemPicUrl = item.find('img').attr('data-src');
|
||||
return {
|
||||
title: item.find('span.video-title.title-truncate.m-t-5').text(),
|
||||
description: `翻译${item.find('div.video-added.title-truncate').text()}<br><img src="${itemPicUrl}">`,
|
||||
link: `https://www.av01.tv/${item.find('a').attr('href')}`,
|
||||
};
|
||||
})
|
||||
.get(),
|
||||
};
|
||||
};
|
||||
@@ -1,75 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const { type, tag } = ctx.params || '';
|
||||
const response = await got(`https://axisstudiosgroup.com/${type}/${tag}`);
|
||||
const data = response.data;
|
||||
const $ = cheerio.load(data); // 使用 cheerio 加载返回的 HTML
|
||||
const list = $('a.overlay-link')
|
||||
.toArray()
|
||||
.map((item) => {
|
||||
item = $(item);
|
||||
return {
|
||||
title: item.find('h2').text().trim(),
|
||||
link: new URL(item.attr('href'), 'https://axisstudiosgroup.com').href,
|
||||
};
|
||||
});
|
||||
|
||||
const items = await Promise.all(
|
||||
list.map((item) =>
|
||||
ctx.cache.tryGet(item.link, async () => {
|
||||
const response2 = await got(item.link);
|
||||
|
||||
const $2 = cheerio.load(response2.data);
|
||||
|
||||
$2('.slider-nav').remove(); // 图片导航
|
||||
$2('.social-wrapper').remove(); // 社交按钮
|
||||
$2('source').remove(); // 莫名其妙的图片
|
||||
$2('video').remove(); // 视频标签
|
||||
$2('button').remove(); // 按钮
|
||||
$2('div.modal.fade').remove(); // 莫名奇妙的图片
|
||||
$2('i').remove();
|
||||
$2('*')
|
||||
.contents()
|
||||
.filter((_, el) => el.type === 'comment')
|
||||
.remove();
|
||||
|
||||
const mcdrPlaylistControl = $2('.mcdr.playlist-control a');
|
||||
const youtube = mcdrPlaylistControl.data('video-type') === 'video/youtube' ? mcdrPlaylistControl.data('video-url').replace('https://www.youtube.com/watch?v=', '') : '';
|
||||
const mp4 = mcdrPlaylistControl.data('video-type') === 'video/mp4' ? mcdrPlaylistControl.data('video-url') : '';
|
||||
|
||||
const content = $2('.container-fluid>div:nth-child(2)');
|
||||
content.find('video').attr('controls', 'controls');
|
||||
content.find('picture').each((_, el) => {
|
||||
el = $2(el);
|
||||
el.replaceWith(el.html());
|
||||
});
|
||||
content.find('div').each((_, el) => {
|
||||
el = $2(el);
|
||||
if (el.children().length) {
|
||||
el.replaceWith(el.children());
|
||||
}
|
||||
});
|
||||
|
||||
let video = '';
|
||||
if (mp4) {
|
||||
video = `<video width="100%" controls="controls" width="640" height="360" source src="${mp4}" type="video/mp4"></video><br>`;
|
||||
}
|
||||
if (youtube) {
|
||||
video = `<iframe id="ytplayer" type="text/html" width="640" height="360" src='https://www.youtube-nocookie.com/embed/${youtube}' frameborder='0' webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe><br>`;
|
||||
}
|
||||
|
||||
item.description = video + content.html();
|
||||
return item;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `Axis Studios | ${type} ${tag ?? ''}`,
|
||||
link: 'http://axisstudiosgroup.com',
|
||||
description: $('description').text(),
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,64 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const url = require('url');
|
||||
|
||||
const host = 'https://www.baby-kingdom.com';
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const id = ctx.params.id;
|
||||
const order = ctx.params.order;
|
||||
|
||||
let link = `https://www.baby-kingdom.com/forum.php?mod=forumdisplay&fid=${id}`;
|
||||
|
||||
switch (order) {
|
||||
case 'dateline':
|
||||
link += '&filter=author&orderby=dateline';
|
||||
|
||||
break;
|
||||
|
||||
case 'reply':
|
||||
link += '&filter=reply&orderby=replies';
|
||||
|
||||
break;
|
||||
|
||||
case 'view':
|
||||
link += '&filter=reply&orderby=views';
|
||||
|
||||
break;
|
||||
|
||||
case 'lastpost':
|
||||
link += '&filter=lastpost&orderby=lastpost';
|
||||
|
||||
break;
|
||||
|
||||
case 'heat':
|
||||
link += '&filter=heat&orderby=heats';
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
const response = await got.get(link);
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const title = $('h1.xs2 a').text();
|
||||
const out = $('tbody[id^="normalthread"]')
|
||||
.slice(0, 10)
|
||||
.map(function () {
|
||||
const info = {
|
||||
title: $(this).find('td:nth-child(2) > a:nth-child(1)').text(),
|
||||
link: url.resolve(host, $(this).find('td:nth-child(2) > a:nth-child(1)').attr('href')),
|
||||
author: $(this).find('td.by.by_author cite a').text(),
|
||||
};
|
||||
return info;
|
||||
})
|
||||
.get();
|
||||
|
||||
ctx.state.data = {
|
||||
title: `${title}-親子王國`,
|
||||
link,
|
||||
item: out,
|
||||
};
|
||||
};
|
||||
@@ -1,73 +0,0 @@
|
||||
const utils = require('./utils');
|
||||
|
||||
const type_map = {
|
||||
0: '達人專欄',
|
||||
1: '達人專欄',
|
||||
2: '最新創作',
|
||||
3: '最新推薦',
|
||||
4: '熱門創作',
|
||||
5: '精選閣樓',
|
||||
};
|
||||
|
||||
const category_map = {
|
||||
0: '不限',
|
||||
1: '日誌',
|
||||
2: '小說',
|
||||
3: '繪圖',
|
||||
4: 'Cosplay',
|
||||
5: '同人商品',
|
||||
};
|
||||
|
||||
const subcategory_map = {
|
||||
0: '不限',
|
||||
1: 'ACG相關',
|
||||
2: '生活休閒',
|
||||
3: '巴哈相關',
|
||||
4: '歡樂惡搞',
|
||||
5: '心情日記',
|
||||
6: '模型/公仔',
|
||||
7: '視聽娛樂',
|
||||
8: '興趣嗜好',
|
||||
9: '其他',
|
||||
10: '愛情',
|
||||
11: '奇幻',
|
||||
12: '科幻',
|
||||
13: '武俠',
|
||||
14: '推理驚悚',
|
||||
15: '歡樂惡搞',
|
||||
16: 'BL/GL',
|
||||
17: '輕小說',
|
||||
18: '其他',
|
||||
19: '紙上塗鴉',
|
||||
20: '草稿/線稿',
|
||||
21: '單色人物',
|
||||
22: '彩色人物',
|
||||
23: '完稿作品',
|
||||
24: '漫畫',
|
||||
25: '勇者造型',
|
||||
26: '其他',
|
||||
27: 'ACG相關',
|
||||
28: '特攝',
|
||||
29: '布袋戲',
|
||||
30: '電影',
|
||||
31: '其他',
|
||||
32: '男性向',
|
||||
33: '女性向',
|
||||
34: '其他',
|
||||
};
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const type = ctx.params.type ?? '1';
|
||||
const category = ctx.params.category ?? '0';
|
||||
const subcategory = ctx.params.subcategory ?? '0';
|
||||
|
||||
const url = `https://home.gamer.com.tw/index.php?k1=${category}&k2=${subcategory}&vt=${type}&sm=3`;
|
||||
|
||||
const { items } = await utils.ProcessFeed(url, ctx);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `巴哈姆特创作大厅${category === '0' ? '' : ' - ' + category_map[category]}${subcategory === '0' ? '' : ' - ' + subcategory_map[subcategory]} - ${type_map[type]}`,
|
||||
link: url,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,15 +0,0 @@
|
||||
const utils = require('./utils');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const author = ctx.params.author;
|
||||
|
||||
const url = ctx.params.category ? `https://home.gamer.com.tw/creationCategory.php?owner=${author}&c=${ctx.params.category}` : `https://home.gamer.com.tw/creation.php?owner=${author}`;
|
||||
|
||||
const { title, items } = await utils.ProcessFeed(url, ctx);
|
||||
|
||||
ctx.state.data = {
|
||||
title,
|
||||
link: url,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,65 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
const base = 'https://home.gamer.com.tw/';
|
||||
|
||||
module.exports = {
|
||||
ProcessFeed: async (url, ctx) => {
|
||||
const response = await got.get(url);
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const title = $('title').text();
|
||||
const list = $('.BH-lbox > .HOME-mainbox1').toArray();
|
||||
|
||||
const parseContent = (htmlString) => {
|
||||
const $ = cheerio.load(htmlString);
|
||||
const content = $('.MSG-list8C');
|
||||
|
||||
const images = $('img');
|
||||
for (const image of images) {
|
||||
$(image).attr('src', $(image).attr('data-src'));
|
||||
}
|
||||
|
||||
return {
|
||||
description: content.html(),
|
||||
};
|
||||
};
|
||||
|
||||
const items = await Promise.all(
|
||||
list.map(async (item) => {
|
||||
const $ = cheerio.load(item);
|
||||
const title = $('.HOME-mainbox1b > h1 > a');
|
||||
const link = base + title.attr('href');
|
||||
const author = $('.HOME-mainbox1b > .ST1 > a').text();
|
||||
const time = $('.HOME-mainbox1b > .ST1').text().split('│')[1];
|
||||
|
||||
const cache = await ctx.cache.get(link);
|
||||
if (cache) {
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const topic = {
|
||||
title: title.text().trim(),
|
||||
link,
|
||||
author,
|
||||
pubDate: new Date(time),
|
||||
};
|
||||
|
||||
try {
|
||||
const detail_response = await got.get(link);
|
||||
const result = parseContent(detail_response.data);
|
||||
if (!result.description) {
|
||||
return '';
|
||||
}
|
||||
topic.description = result.description;
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
ctx.cache.set(link, JSON.stringify(topic));
|
||||
return topic;
|
||||
})
|
||||
);
|
||||
|
||||
return { title, items };
|
||||
},
|
||||
};
|
||||
@@ -1,42 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const { isValidHost } = require('@/utils/valid-host');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const lang = ctx.params.lang || 'en';
|
||||
const id = ctx.params.id || 'bandizip';
|
||||
if (!isValidHost(lang)) {
|
||||
throw new Error('Invalid language code');
|
||||
}
|
||||
|
||||
const rootUrl = `https://${lang}.bandisoft.com`;
|
||||
const currentUrl = `${rootUrl}/${id}/history/`;
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: currentUrl,
|
||||
});
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const items = $('h2')
|
||||
.map((_, item) => {
|
||||
item = $(item);
|
||||
|
||||
const title = item.text();
|
||||
item.children('font').remove();
|
||||
|
||||
return {
|
||||
title,
|
||||
link: currentUrl,
|
||||
description: item.next().html(),
|
||||
pubDate: new Date(item.text()).toUTCString(),
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
ctx.state.data = {
|
||||
title: $('title').text(),
|
||||
link: currentUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,50 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const time = ctx.params.time || 'shishidashiku';
|
||||
|
||||
const rootUrl = 'http://www.banyuetan.org';
|
||||
const currentUrl = `${rootUrl}/byt/${time}/index.html`;
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: currentUrl,
|
||||
});
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const list = $('.byt_mian_image_list_con ul li a')
|
||||
.slice(0, 10)
|
||||
.map((_, item) => {
|
||||
item = $(item);
|
||||
return {
|
||||
link: item.attr('href'),
|
||||
title: item.attr('title'),
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
const items = await Promise.all(
|
||||
list.map((item) =>
|
||||
ctx.cache.tryGet(item.link, async () => {
|
||||
const detailResponse = await got({
|
||||
method: 'get',
|
||||
url: item.link,
|
||||
});
|
||||
const content = cheerio.load(detailResponse.data);
|
||||
|
||||
item.description = content('#detail_content').html();
|
||||
item.author = content('.detail_tit_source').text().replace('来源:', '');
|
||||
item.pubDate = new Date(content('meta[property="og:release_date"]').attr('content')).toUTCString();
|
||||
|
||||
return item;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: $('title').text(),
|
||||
link: currentUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,56 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const name = ctx.params.name;
|
||||
|
||||
const link = `http://www.banyuetan.org/byt/${name}/index.html`;
|
||||
const response = await got.get(link);
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const list = $('ul.clearFix li')
|
||||
.slice(0, 10)
|
||||
.map(function () {
|
||||
const info = {
|
||||
title: $(this).find('h3 a').text(),
|
||||
link: $(this).find('h3 a').attr('href'),
|
||||
date: $(this).find('span.tag3').text(),
|
||||
};
|
||||
return info;
|
||||
})
|
||||
.get();
|
||||
|
||||
const out = await Promise.all(
|
||||
list.map(async (info) => {
|
||||
const title = info.title;
|
||||
const date = info.date;
|
||||
const itemUrl = info.link;
|
||||
|
||||
const cache = await ctx.cache.get(itemUrl);
|
||||
if (cache) {
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const response = await got.get(itemUrl);
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
const description = $('div.detail_content').html() || '文章已被删除';
|
||||
|
||||
const single = {
|
||||
title,
|
||||
link: itemUrl,
|
||||
description,
|
||||
pubDate: new Date(date).toUTCString(),
|
||||
};
|
||||
ctx.cache.set(itemUrl, JSON.stringify(single));
|
||||
return single;
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `${name}-半月谈`,
|
||||
link,
|
||||
item: out,
|
||||
};
|
||||
};
|
||||
@@ -1,41 +0,0 @@
|
||||
const cheerio = require('cheerio');
|
||||
const got = require('@/utils/got');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const url = `https://www.ben-evans.com/benedictevans/`;
|
||||
|
||||
const res = await got.get(url);
|
||||
const $ = cheerio.load(res.data);
|
||||
const list = $('section > article').get();
|
||||
|
||||
const out = await Promise.all(
|
||||
list.map(async (item) => {
|
||||
const $ = cheerio.load(item);
|
||||
const title = $('.BlogList-item-title').text();
|
||||
const address = 'https://www.ben-evans.com' + $('.BlogList-item-title').attr('href');
|
||||
const time = $('.Blog-meta-item--date').text();
|
||||
const cache = await ctx.cache.get(address);
|
||||
if (cache) {
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
const res = await got.get(address);
|
||||
const capture = cheerio.load(res.data);
|
||||
const contents = capture('.col.sqs-col-12.span-12').html();
|
||||
const single = {
|
||||
title,
|
||||
author: 'Benedict Evans',
|
||||
description: contents,
|
||||
link: address,
|
||||
guid: address,
|
||||
pubDate: new Date(time).toUTCString(),
|
||||
};
|
||||
ctx.cache.set(address, JSON.stringify(single));
|
||||
return single;
|
||||
})
|
||||
);
|
||||
ctx.state.data = {
|
||||
title: `Benedict Evans`,
|
||||
link: url,
|
||||
item: out,
|
||||
};
|
||||
};
|
||||
@@ -1,56 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const timezone = require('@/utils/timezone');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const category = ctx.params.category || 'pcgame';
|
||||
const type = ctx.params.type || '';
|
||||
|
||||
const rootUrl = 'https://www.bibgame.com';
|
||||
const currentUrl = `${rootUrl}/${category}/${type}`;
|
||||
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: currentUrl,
|
||||
});
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const list = $('.info_box a')
|
||||
.slice(0, 15)
|
||||
.map((_, item) => {
|
||||
item = $(item);
|
||||
const link = item.attr('href');
|
||||
|
||||
return {
|
||||
title: item.text(),
|
||||
link: link.includes('http') ? link : `${rootUrl}${link}`,
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
const items = await Promise.all(
|
||||
list.map((item) =>
|
||||
ctx.cache.tryGet(item.link, async () => {
|
||||
const detailResponse = await got({
|
||||
method: 'get',
|
||||
url: item.link,
|
||||
});
|
||||
const content = cheerio.load(detailResponse.data);
|
||||
|
||||
content('#comment').parent().remove();
|
||||
|
||||
item.description = content('.abstract').html();
|
||||
item.pubDate = timezone(new Date(content('.time_box').text().trim()), +8);
|
||||
|
||||
return item;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: $('title').text(),
|
||||
link: currentUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,31 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const url = 'https://jingwei.link/';
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url,
|
||||
});
|
||||
const $ = cheerio.load(response.data);
|
||||
const resultItem = $("article[class='article-item']")
|
||||
.map((index, elem) => {
|
||||
elem = $(elem);
|
||||
|
||||
const $esction = elem.find('section[class="post-preview"]');
|
||||
|
||||
return {
|
||||
title: $esction.find('h2').text(),
|
||||
description: $esction.find('h3').text(),
|
||||
link: $esction.find('a').attr('href'),
|
||||
author: '敬维',
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
ctx.state.data = {
|
||||
title: '敬维-以认真的态度做完美的事情',
|
||||
link: url,
|
||||
item: resultItem,
|
||||
};
|
||||
};
|
||||
@@ -1,30 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const url = 'https://leemeng.tw/blog.html';
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url,
|
||||
});
|
||||
const $ = cheerio.load(response.data);
|
||||
const resultItem = $('article')
|
||||
.map((index, elem) => {
|
||||
elem = $(elem);
|
||||
const $link = elem.find('[rel="bookmark"]');
|
||||
const title = $link.text();
|
||||
const link = $link.attr('href');
|
||||
|
||||
return {
|
||||
title,
|
||||
link,
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
ctx.state.data = {
|
||||
title: 'LeeMeng - 部落格',
|
||||
link: url,
|
||||
item: resultItem,
|
||||
};
|
||||
};
|
||||
@@ -1,24 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const id = ctx.params.id || 2020;
|
||||
const url = `https://wangwusiwj.blogspot.com/${id}`;
|
||||
const response = await got({ method: 'get', url });
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const list = $('div.post')
|
||||
.map((i, e) => ({
|
||||
title: $(e).find('h3 > a').text(),
|
||||
description: $(e).find('.post-body').html(),
|
||||
link: $(e).find('h3 > a').attr('href'),
|
||||
author: '王五四',
|
||||
}))
|
||||
.get();
|
||||
|
||||
ctx.state.data = {
|
||||
title: '王五四文集',
|
||||
link: url,
|
||||
item: list,
|
||||
};
|
||||
};
|
||||
@@ -1,50 +0,0 @@
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const url = 'https://www.yinwang.org';
|
||||
const response = await got({ method: 'get', url });
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const list = $("li[class='list-group-item title']")
|
||||
.map((i, e) => {
|
||||
const element = $(e);
|
||||
const title = element.find('a').text();
|
||||
const link = url + element.find('a').attr('href');
|
||||
const dateraw = /\d{4}(?:\/\d{2}){2}/.exec(link)[0];
|
||||
|
||||
return {
|
||||
title,
|
||||
description: '',
|
||||
link,
|
||||
author: '王垠',
|
||||
pubDate: parseDate(dateraw, 'YYYY/MM/DD'),
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
const result = await Promise.all(
|
||||
list.map(async (item) => {
|
||||
const link = item.link;
|
||||
|
||||
const cache = await ctx.cache.get(link);
|
||||
if (cache) {
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const itemReponse = await got.get(link);
|
||||
const itemElement = cheerio.load(itemReponse.data);
|
||||
item.description = itemElement('.inner').html();
|
||||
|
||||
ctx.cache.set(link, JSON.stringify(item));
|
||||
return item;
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: '王垠的博客 - 当然我在扯淡',
|
||||
link: url,
|
||||
item: result,
|
||||
};
|
||||
};
|
||||
@@ -1,71 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: `https://www.blowstudio.es/work/`,
|
||||
});
|
||||
const data = response.data;
|
||||
const $ = cheerio.load(data); // 使用 cheerio 加载返回的 HTML
|
||||
const list = $('.portfolios.normal > ul > li').get().slice(0, 10);
|
||||
const articledata = await Promise.all(
|
||||
list.map(async (item) => {
|
||||
const link = `https://www.blowstudio.es${$(item).find('a').attr('href')}/`;
|
||||
|
||||
const cache = await ctx.cache.get(link);
|
||||
if (cache) {
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const response2 = await got({
|
||||
method: 'get',
|
||||
url: link,
|
||||
});
|
||||
|
||||
const articleHtml = response2.data;
|
||||
const $2 = cheerio.load(articleHtml);
|
||||
const imglist = $2('div.attachment-grid img').get();
|
||||
const mainvideo = $2('.single-page-vimeo-div').attr('data-video-id');
|
||||
|
||||
const img = imglist.map((item) => ({
|
||||
img: $2(item).attr('src'),
|
||||
}));
|
||||
const single = {
|
||||
mainvideo,
|
||||
describe: $2('div.portfolio-content > div:nth-child(2)').html(),
|
||||
title: $2('div.portfolio-content > div:nth-child(1)').text(),
|
||||
images: img,
|
||||
link,
|
||||
};
|
||||
ctx.cache.set(link, JSON.stringify(single));
|
||||
return single;
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: 'Blow Studio',
|
||||
link: 'http://blowstudio.es',
|
||||
description: $('description').text(),
|
||||
item: list.map((item, index) => {
|
||||
let content = '';
|
||||
const videostyle = `width="640" height="360"`;
|
||||
const imgstyle = `style="max-width: 650px; height: auto; object-fit: contain; flex: 0 0 auto;"`;
|
||||
|
||||
content += `<iframe ${videostyle} src='https://player.vimeo.com/video/${articledata[index].mainvideo}' frameborder='0' webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe><br>`;
|
||||
content += articledata[index].describe;
|
||||
|
||||
if (articledata[index].images) {
|
||||
for (let p = 0; p < articledata[index].images.length; p++) {
|
||||
content += `<img ${imgstyle} src="${articledata[index].images[p].img}"><br>`;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
title: articledata[index].title,
|
||||
description: content,
|
||||
link: articledata[index].link,
|
||||
};
|
||||
}),
|
||||
};
|
||||
};
|
||||
@@ -1,79 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: `http://blur.com`,
|
||||
});
|
||||
const data = response.data;
|
||||
const $ = cheerio.load(data); // 使用 cheerio 加载返回的 HTML
|
||||
const list = $('.page-title a').get();
|
||||
const articledata = await Promise.all(
|
||||
list.map(async (item) => {
|
||||
const link = $(item).attr('href');
|
||||
const cache = await ctx.cache.get(link);
|
||||
if (cache) {
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
const response2 = await got({
|
||||
method: 'get',
|
||||
url: link,
|
||||
});
|
||||
|
||||
const articleHtml = response2.data;
|
||||
const $2 = cheerio.load(articleHtml);
|
||||
const imglist = $2('.gridded img').get();
|
||||
const videolist = $2('.gridded iframe').get();
|
||||
const img = imglist.map((item) => ({
|
||||
img: $2(item).attr('src'),
|
||||
}));
|
||||
const video = videolist.map((item) => ({
|
||||
video: $2(item).attr('src'),
|
||||
}));
|
||||
const single = {
|
||||
mainvideo: $2('div.project-title').attr('data-video'),
|
||||
describe: $2('p').text(),
|
||||
title: $2('h1.page-title').text(),
|
||||
client: $2('div.client').text(),
|
||||
images: img,
|
||||
video,
|
||||
link,
|
||||
};
|
||||
ctx.cache.set(link, JSON.stringify(single));
|
||||
return single;
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: 'Blur Studio',
|
||||
link: 'http://blur.com',
|
||||
description: $('description').text(),
|
||||
item: list.map((item, index) => {
|
||||
const Num = /\d+/;
|
||||
let content = '';
|
||||
const videostyle = `width="640" height="360"`;
|
||||
const imgstyle = `style="max-width: 650px; height: auto; object-fit: contain; flex: 0 0 auto;"`;
|
||||
content += `Client:${articledata[index].client}<br>${articledata[index].describe}`;
|
||||
content += Num.test(articledata[index].mainvideo)
|
||||
? `<iframe ${videostyle} src='https://player.vimeo.com/video/${articledata[index].mainvideo}' frameborder='0' webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe><br>`
|
||||
: `<iframe ${videostyle} src='https://youtube.com/embed/${articledata[index].mainvideo}' frameborder='0' webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe><br>`;
|
||||
if (articledata[index].images) {
|
||||
for (let p = 0; p < articledata[index].images.length; p++) {
|
||||
content += `<img ${imgstyle} src="${articledata[index].images[p].img}"><br>`;
|
||||
}
|
||||
}
|
||||
if (articledata[index].video) {
|
||||
for (let v = 0; v < articledata[index].video.length; v++) {
|
||||
content += `<iframe ${videostyle} src='${articledata[index].video[v].video}' frameborder='0' webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe><br>`;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
title: articledata[index].title,
|
||||
description: content,
|
||||
link: articledata[index].link,
|
||||
};
|
||||
}),
|
||||
};
|
||||
};
|
||||
@@ -1,32 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: 'https://www.bookwalker.com.tw/search?order=sell_desc&series_display=1&d=1',
|
||||
});
|
||||
|
||||
const data = response.data;
|
||||
|
||||
const $ = cheerio.load(data);
|
||||
const list = $('div[class="bwbookitem"]');
|
||||
let bookid;
|
||||
ctx.state.data = {
|
||||
title: 'BOOKWALKERTW热门新书',
|
||||
link: 'https://www.bookwalker.com.tw/search?order=sell_desc&series_display=1&d=1',
|
||||
item:
|
||||
list &&
|
||||
list
|
||||
.map((index, item) => {
|
||||
item = $(item);
|
||||
bookid = item.find('img').attr('data-src').split('/')[4];
|
||||
return {
|
||||
title: item.find('.bookname').text(),
|
||||
description: `${item.find('.booknamesub').text()} | ${item.find('.bprice').text()}<br><img src="https://taiwan-image.bookwalker.com.tw/product/${bookid}/zoom_big_${bookid}.jpg">`,
|
||||
link: item.find('a').attr('href'),
|
||||
};
|
||||
})
|
||||
.get(),
|
||||
};
|
||||
};
|
||||
@@ -1,58 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const { isValidHost } = require('@/utils/valid-host');
|
||||
const maxPages = 5;
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const { subdomain } = ctx.params;
|
||||
if (!isValidHost(subdomain)) {
|
||||
throw new Error('Invalid subdomain');
|
||||
}
|
||||
const shopUrl = `https://${subdomain}.booth.pm`;
|
||||
|
||||
let shopName;
|
||||
const items = [];
|
||||
for (let page = 1; page <= maxPages; page++) {
|
||||
const pageUrl = `${shopUrl}/items?page=${page}`;
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: pageUrl,
|
||||
});
|
||||
|
||||
const data = response.data;
|
||||
|
||||
const $ = cheerio.load(data);
|
||||
shopName = $('div.shop-name > span').text();
|
||||
const pageItems = $('li.item');
|
||||
|
||||
if (pageItems.length === 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (const pageItem of pageItems) {
|
||||
// extract item name
|
||||
const itemName = $('h2.item-name > a', pageItem).text();
|
||||
|
||||
// extract item url
|
||||
const itemUrl = shopUrl + $('h2.item-name > a', pageItem).attr('href');
|
||||
|
||||
// extract item preview url
|
||||
const itemPreviewUrl = $('div.swap-image > img', pageItem).attr('src');
|
||||
|
||||
items.push({
|
||||
title: itemName,
|
||||
description: `<img src='${itemPreviewUrl}'/>`,
|
||||
link: itemUrl,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ctx.state.data = {
|
||||
title: shopName,
|
||||
link: shopUrl,
|
||||
description: shopName,
|
||||
allowEmpty: true,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,29 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const baseUrl = 'https://bsblog123.com/';
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: baseUrl,
|
||||
});
|
||||
const $ = cheerio.load(response.data); // 使用 cheerio 加载返回的 HTML
|
||||
const list = $('div[class="whitebg bloglist"] li');
|
||||
ctx.state.data = {
|
||||
title: `冰山博客 ~ 资讯`,
|
||||
link: `https://bsblog123.com`,
|
||||
description: '冰山博客 ~ 资讯',
|
||||
item:
|
||||
list &&
|
||||
list
|
||||
.map((index, item) => {
|
||||
item = $(item);
|
||||
return {
|
||||
title: $('h3.blogtitle', item).text(),
|
||||
link: $('h3 a', item).attr('href'),
|
||||
description: $('p', item).text(),
|
||||
};
|
||||
})
|
||||
.get(),
|
||||
};
|
||||
};
|
||||
@@ -1,52 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const category = ctx.params.category || '';
|
||||
|
||||
const rootUrl = 'https://www.cbndata.com';
|
||||
const apiUrl = `${rootUrl}/api/v3/informations?page=1&per_page=10${category ? `&tag_id=${category}` : ''}`;
|
||||
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: apiUrl,
|
||||
});
|
||||
|
||||
const list = response.data.data.map((item) => ({
|
||||
title: item.id,
|
||||
link: `${rootUrl}/api/v3/informations/show?id=${item.id}`,
|
||||
pubDate: Date.parse(item.date),
|
||||
}));
|
||||
|
||||
const items = await Promise.all(
|
||||
list.map((item) =>
|
||||
ctx.cache.tryGet(item.link, async () => {
|
||||
const detailResponse = await got({
|
||||
method: 'get',
|
||||
url: item.link,
|
||||
});
|
||||
|
||||
item.link = `${rootUrl}/information/${item.title}`;
|
||||
|
||||
item.title = detailResponse.data.data.title;
|
||||
item.author = detailResponse.data.data.author;
|
||||
item.description = detailResponse.data.data.content;
|
||||
|
||||
return item;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
let title = '看点';
|
||||
|
||||
for (const tag of response.data.home_tags) {
|
||||
if (tag.id.toString() === category) {
|
||||
title = tag.name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ctx.state.data = {
|
||||
title: `${title} - CBNData消费站`,
|
||||
link: `${rootUrl}/information${category ? `?tag_id=${category}` : ''}`,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,49 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const category = ctx.params.category || 'news';
|
||||
|
||||
const rootUrl = 'http://www.ccg.org.cn';
|
||||
const currentUrl = `${rootUrl}/${category}`;
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: currentUrl,
|
||||
});
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const list = $('.huodong-list li a')
|
||||
.slice(0, 10)
|
||||
.map((_, item) => {
|
||||
item = $(item);
|
||||
return {
|
||||
link: item.attr('href'),
|
||||
title: item.find('h5').text(),
|
||||
pubDate: new Date(item.find('span').text().replaceAll(/年|月/g, '-').replace(/日/, '')).toUTCString(),
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
const items = await Promise.all(
|
||||
list.map((item) =>
|
||||
ctx.cache.tryGet(item.link, async () => {
|
||||
const detailResponse = await got({
|
||||
method: 'get',
|
||||
url: item.link,
|
||||
});
|
||||
const content = cheerio.load(detailResponse.data);
|
||||
|
||||
item.description = content('.pinpai-page').html();
|
||||
|
||||
return item;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `${$('title').text()} - 全球化智库`,
|
||||
link: currentUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,113 +0,0 @@
|
||||
// cell.com is extremely slow, and redirect too many times.
|
||||
// Thus, the content page are replaced by www.sciencedirect.com.
|
||||
|
||||
const cheerio = require('cheerio');
|
||||
const got = require('@/utils/got');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const baseURL = 'https://www.cell.com';
|
||||
const category = ctx.params.category;
|
||||
let pageURL = `${baseURL}/cell/current.rss`;
|
||||
let categoryTitle = 'Latest issue';
|
||||
if (category === 'inpress') {
|
||||
pageURL = `${baseURL}/cell/inpress.rss`;
|
||||
categoryTitle = 'Articles in press';
|
||||
}
|
||||
|
||||
const alternativeURL = 'https://www.sciencedirect.com/science/article/pii/';
|
||||
const pageResponse = await got.get(pageURL);
|
||||
const pageCapture = cheerio.load(pageResponse.data);
|
||||
|
||||
const list = pageCapture('item')
|
||||
.get()
|
||||
.filter((item) => {
|
||||
const $ = cheerio.load(item);
|
||||
const section = $('prism\\:section').text();
|
||||
|
||||
return ['Article', 'Resource'].includes(section);
|
||||
});
|
||||
|
||||
const out = await Promise.all(
|
||||
list.map(async (item) => {
|
||||
const $ = cheerio.load(item);
|
||||
const section = $('prism\\:section').text();
|
||||
const address = alternativeURL + $('item').attr('rdf:about').replace('?rss=yes', '').split('/').pop();
|
||||
const title = $('dc\\:title').text();
|
||||
const author = $('dc\\:creator').text();
|
||||
const pubDate = new Date($('dc\\:date').text()).toUTCString();
|
||||
const cache = await ctx.cache.get(address);
|
||||
if (cache) {
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
const itemPage = await got.get(address);
|
||||
const itemCapture = cheerio.load(itemPage.data);
|
||||
// section + keywords content
|
||||
const keywords = itemCapture('div.keywords-section > div.keyword')
|
||||
.map((i, el) => $(el).text())
|
||||
.get()
|
||||
.join('; ');
|
||||
const sectionContents = `
|
||||
<div id="content-section">
|
||||
<span style="color: #007dbc; text-transform: uppercase; font-weight: 700;">${section}</span>
|
||||
<br>
|
||||
<p style="color: grey; font-weight: 700;">[${keywords}]</p>
|
||||
</div>
|
||||
`;
|
||||
// graphical content
|
||||
const brief = $('description').text();
|
||||
const graphical = itemCapture('div.abstract.graphical').find('img').attr('src');
|
||||
let graphicalContents = '';
|
||||
if (graphical !== '') {
|
||||
graphicalContents = `
|
||||
<div id="content-graphical">
|
||||
<h2 style="color: #007dbc; font-weight: 700;">Graphical Abstract</h2>
|
||||
<center>
|
||||
<figure>
|
||||
<img src="${graphical}" height="400" alt="">
|
||||
</figure>
|
||||
</center>
|
||||
<span>${brief}</span>
|
||||
</div>`;
|
||||
}
|
||||
// highlight content
|
||||
const highlight = itemCapture('div.abstract.author-highlights dl').html();
|
||||
let highlightContents = '';
|
||||
if (highlight !== '') {
|
||||
highlightContents = `
|
||||
<div id="content-highlight">
|
||||
<h2 style="color: #007dbc; font-weight: 700;">Highlights</h2>
|
||||
${highlight}
|
||||
</div>`;
|
||||
}
|
||||
// summary content
|
||||
const summary = itemCapture('div.abstract.author p').html();
|
||||
let summaryContents = '';
|
||||
if (summary !== '') {
|
||||
summaryContents = `
|
||||
<div id="content-summary">
|
||||
<h2 style="color: #007dbc; font-weight: 700;">Summary</h2>
|
||||
${summary}
|
||||
</div>`;
|
||||
}
|
||||
const contents = sectionContents + graphicalContents + highlightContents + summaryContents;
|
||||
|
||||
const single = {
|
||||
title,
|
||||
author,
|
||||
description: contents,
|
||||
link: address,
|
||||
guid: address,
|
||||
doi: $('dc\\:identifier').text(),
|
||||
pubDate,
|
||||
};
|
||||
ctx.cache.set(address, JSON.stringify(single));
|
||||
return single;
|
||||
})
|
||||
);
|
||||
ctx.state.data = {
|
||||
title: `Cell | ${categoryTitle}`,
|
||||
description: `Cell, a research journal`,
|
||||
link: baseURL,
|
||||
item: out,
|
||||
};
|
||||
};
|
||||
@@ -1,106 +0,0 @@
|
||||
// The content is generateed by undocumentated resource of Cell journals
|
||||
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const url = require('url');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const baseURL = 'https://www.cell.com';
|
||||
const journals = [
|
||||
'cell',
|
||||
'cancer-cell',
|
||||
'cell-chemical-biology',
|
||||
'cell-host-microbe',
|
||||
'cell-metabolism',
|
||||
'cell-reports',
|
||||
'cell-reports-physical-science',
|
||||
'cell-stem-cell',
|
||||
'cell-systems',
|
||||
'chem',
|
||||
'current-biology',
|
||||
'developmental-cell',
|
||||
'immunity',
|
||||
'joule',
|
||||
'matter',
|
||||
'molecular-cell',
|
||||
'neuron',
|
||||
'one-earth',
|
||||
'structure',
|
||||
];
|
||||
const out = await Promise.all(
|
||||
journals.map(async (journal) => {
|
||||
// get the lastest volumn and issue id
|
||||
const pageURL = `${baseURL}/${journal}/current`;
|
||||
|
||||
const pageMeta = await ctx.cache.tryGet(
|
||||
pageURL,
|
||||
async () => {
|
||||
const cookieData = await got
|
||||
.extend({
|
||||
followRedirect: false,
|
||||
})
|
||||
.get(`https://secure.jbs.elsevierhealth.com/action/getSharedSiteSession?redirect=${encodeURI(pageURL)}`)
|
||||
.then((response) => {
|
||||
const cookieString = response.headers['set-cookie'].join(' ');
|
||||
const server = cookieString.match(/SERVER=(\S+);/)[1];
|
||||
const jsession = cookieString.match(/JSESSIONID=(\S+);/)[1];
|
||||
return `SERVER=${server}; JSESSIONID=${jsession};`;
|
||||
});
|
||||
|
||||
const pageResponse = await got.get(pageURL, {
|
||||
headers: {
|
||||
cookie: cookieData,
|
||||
},
|
||||
followRedirect: false,
|
||||
});
|
||||
|
||||
const $ = cheerio.load(pageResponse.data);
|
||||
const coverImg = url.resolve('https://', $('#fullCover > img').attr('src'));
|
||||
const coverDescription = $('#fullCover > img').attr('alt');
|
||||
const issueDate = $('h1.toc-header__issue-date').text();
|
||||
const issueNum = $('.toc-header__details span')
|
||||
.contents()
|
||||
.map(function () {
|
||||
return this.type === 'text' ? $(this).text() : '';
|
||||
})
|
||||
.get()
|
||||
.slice(0, 2)
|
||||
.join(', ');
|
||||
const issueName = $('meta[name="name"]').attr('content').replace('Issue: ', '') || `Cell ...`;
|
||||
const m = $('meta[name="pbContext"]')
|
||||
.attr('content')
|
||||
.match(/issue:issue:pii\\:(S\d{4})(\d{4})(\d{2})(X\d{4})(\w)/);
|
||||
const issueID = `${m[1]}-${m[2]}(${m[3]})${m[4]}-${m[5]}`;
|
||||
return {
|
||||
coverImg,
|
||||
coverDescription,
|
||||
issueName,
|
||||
issueDate,
|
||||
issueNum,
|
||||
issueID,
|
||||
};
|
||||
},
|
||||
12 * 60 * 60 // set cache timeout to 12h
|
||||
);
|
||||
const address = `${baseURL}/${journal}/issue?pii=${pageMeta.issueID}`;
|
||||
const contents = `<div align="center"><img src="${pageMeta.coverImg}" alt="${pageMeta.coverDescription}"></div>`;
|
||||
|
||||
const single = {
|
||||
title: `${pageMeta.issueName} | ${pageMeta.issueNum} (${pageMeta.issueDate})`,
|
||||
author: '@y9c',
|
||||
description: contents,
|
||||
link: address,
|
||||
guid: address,
|
||||
pubDate: new Date(pageMeta.issueDate).toUTCString(),
|
||||
};
|
||||
ctx.cache.set(address, JSON.stringify(single));
|
||||
return single;
|
||||
})
|
||||
);
|
||||
ctx.state.data = {
|
||||
title: 'Cell Covers Story',
|
||||
description: 'Find out the cover story of some Cell journals.',
|
||||
link: baseURL,
|
||||
item: out,
|
||||
};
|
||||
};
|
||||
@@ -1,31 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const url = 'http://centbrowser.cn/history.html';
|
||||
|
||||
const response = await got.get(url);
|
||||
const $ = cheerio.load(response.data);
|
||||
const list = $('.list').toArray();
|
||||
|
||||
ctx.state.data = {
|
||||
title: 'Cent Browser 更新日志',
|
||||
link: url,
|
||||
item: list.map((update) => {
|
||||
update = $(update);
|
||||
const version = update.find('p').first().attr('id');
|
||||
const date = update
|
||||
.find('p > i')
|
||||
.text()
|
||||
.match(/\d+-\d+-\d+/)[0];
|
||||
update.find('p').remove();
|
||||
return {
|
||||
title: version,
|
||||
author: 'Cent Browser',
|
||||
description: update.html(),
|
||||
link: `${url}#${date}`,
|
||||
pubDate: new Date(date),
|
||||
};
|
||||
}),
|
||||
};
|
||||
};
|
||||
@@ -1,49 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const pageUrl = 'http://www.cfan.com.cn/news/';
|
||||
const response = await got.get(pageUrl);
|
||||
const $ = cheerio.load(response.data);
|
||||
const list = $('.ui-video-list').get();
|
||||
|
||||
const ProcessFeed = async (link) => {
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: link,
|
||||
});
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
return $('.maincontent').html() || '文章已被删除';
|
||||
};
|
||||
|
||||
const items = await Promise.all(
|
||||
list.map(async (item) => {
|
||||
const $ = cheerio.load(item);
|
||||
const link = $('.left-post a').attr('href');
|
||||
|
||||
const cache = await ctx.cache.get(link);
|
||||
if (cache) {
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const description = await ProcessFeed(link);
|
||||
|
||||
const single = {
|
||||
title: $('.left-post-title').text(),
|
||||
description,
|
||||
link,
|
||||
pubDate: new Date($('.left-post-date').text()).toUTCString(),
|
||||
};
|
||||
|
||||
ctx.cache.set(link, JSON.stringify(single));
|
||||
return single;
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: $('title').text(),
|
||||
link: pageUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,48 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
ctx.params.type = ctx.params.type || 'read';
|
||||
ctx.params.time = ctx.params.time || 'all';
|
||||
|
||||
const rootUrl = `https://www.cgtn.com/most-${ctx.params.type}`;
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: rootUrl,
|
||||
});
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
const list = $(`#${ctx.params.time}Items div.most-read-item-box div.cg-title`)
|
||||
.map((_, item) => {
|
||||
item = $(item);
|
||||
const a = item.find('a');
|
||||
return {
|
||||
title: a.text(),
|
||||
link: a.attr('href'),
|
||||
pubDate: new Date(Number.parseInt(a.attr('data-time'))).toUTCString(),
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
const items = await Promise.all(
|
||||
list.map((item) =>
|
||||
ctx.cache.tryGet(item.link, async () => {
|
||||
const detailResponse = await got({
|
||||
method: 'get',
|
||||
url: item.link,
|
||||
});
|
||||
const content = cheerio.load(detailResponse.data);
|
||||
|
||||
item.description = content('#cmsMainContent').html();
|
||||
|
||||
return item;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `CGTN - Most ${ctx.params.type}`,
|
||||
link: rootUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,50 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const rootUrl = `https://www.cgtn.com/opinions`;
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: rootUrl,
|
||||
});
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
$('.cg-pic').parent().remove();
|
||||
|
||||
const list = $(`.cg-title h4`)
|
||||
.slice(0, 15)
|
||||
.map((_, item) => {
|
||||
item = $(item);
|
||||
const a = item.find('a');
|
||||
return {
|
||||
title: a.text(),
|
||||
link: a.attr('href'),
|
||||
pubDate: new Date(Number.parseInt(a.attr('data-time'))).toUTCString(),
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
const items = await Promise.all(
|
||||
list.map((item) =>
|
||||
ctx.cache.tryGet(item.link, async () => {
|
||||
const detailResponse = await got({
|
||||
method: 'get',
|
||||
url: item.link,
|
||||
});
|
||||
const content = cheerio.load(detailResponse.data);
|
||||
|
||||
item.author = content('.news-author-name').text();
|
||||
item.description = content('#cmsMainContent').html();
|
||||
|
||||
return item;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: 'CGTN - Opinions',
|
||||
link: rootUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,50 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const channel = ctx.params.channel || 'all';
|
||||
|
||||
const rootUrl = 'https://chaoli.club';
|
||||
const currentUrl = `${rootUrl}/index.php/conversations/${channel}`;
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: currentUrl,
|
||||
});
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const list = $('.title a')
|
||||
.slice(0, 10)
|
||||
.map((_, item) => {
|
||||
item = $(item);
|
||||
return {
|
||||
title: item.text(),
|
||||
link: `${rootUrl}${item.attr('href')}`,
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
const items = await Promise.all(
|
||||
list.map((item) =>
|
||||
ctx.cache.tryGet(item.link, async () => {
|
||||
const detailResponse = await got({
|
||||
method: 'get',
|
||||
url: item.link,
|
||||
});
|
||||
const content = cheerio.load(detailResponse.data);
|
||||
|
||||
item.author = content('.info h3').eq(0).text();
|
||||
item.description = content('.postBody').eq(0).html();
|
||||
item.pubDate = new Date(Number.parseInt(content('.info .time').attr('data-timestamp')) * 1000).toUTCString();
|
||||
|
||||
return item;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: $('title').text(),
|
||||
link: currentUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,57 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const url = require('url');
|
||||
const { parseRelativeDate } = require('@/utils/parse-date');
|
||||
const timezone = require('@/utils/timezone');
|
||||
|
||||
const host = 'https://www.checkee.info';
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const dispdate = ctx.params.dispdate;
|
||||
|
||||
const link = `https://www.checkee.info/main.php?dispdate=${dispdate}`;
|
||||
const response = await got.get(link);
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const list = $(':nth-child(11) tbody tr')
|
||||
.map(function () {
|
||||
return {
|
||||
id: $(this).find(':nth-child(2)').text(),
|
||||
visaType: $(this).find(':nth-child(3)').text(),
|
||||
visaEntry: $(this).find(':nth-child(4)').text(),
|
||||
usConsulate: $(this).find(':nth-child(5)').text(),
|
||||
major: $(this).find(':nth-child(6)').text(),
|
||||
status: $(this).find(':nth-child(7)').text(),
|
||||
checkDate: $(this).find(':nth-child(8)').text(),
|
||||
completeDate: $(this).find(':nth-child(9)').text() === '0000-00-00' ? 'Not Completed' : $(this).find(':nth-child(9)').text(),
|
||||
link: $(this).find(':nth-child(11) a').attr('href'),
|
||||
note: $(this).find(':nth-child(11) a').attr('title') || '',
|
||||
};
|
||||
})
|
||||
.get();
|
||||
list.shift();
|
||||
|
||||
const out = list.map((item) => {
|
||||
const title =
|
||||
`${item.visaType} ${item.visaEntry}, ${item.usConsulate}, ` +
|
||||
`Major ${item.major}, ${item.status}. Check date: ${item.checkDate}` +
|
||||
(item.completeDate === 'Not Completed' ? '' : `, Complete: ${item.completeDate}`) +
|
||||
` | ID: ${item.id}`;
|
||||
const itemUrl = url.resolve(host, item.link);
|
||||
const date_value = item.checkDate;
|
||||
const description = item.note === '' ? title : item.note;
|
||||
|
||||
return {
|
||||
title,
|
||||
link: itemUrl,
|
||||
description,
|
||||
pubDate: timezone(parseRelativeDate(date_value), 8),
|
||||
};
|
||||
});
|
||||
|
||||
ctx.state.data = {
|
||||
title: `Check Reporter Results: ${dispdate}`,
|
||||
link,
|
||||
item: out,
|
||||
};
|
||||
};
|
||||
@@ -1,32 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const homepage = 'https://checkra.in/releases/';
|
||||
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: homepage,
|
||||
});
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
const releases = $('.release');
|
||||
|
||||
ctx.state.data = {
|
||||
title: `Checkra1n All Releases`,
|
||||
link: homepage,
|
||||
item: releases
|
||||
.map((i, item) => {
|
||||
const $item = $(item);
|
||||
const address = 'https://checkra.in' + $item.find('a').attr('href');
|
||||
|
||||
return {
|
||||
title: $item.find('h3').first().text(),
|
||||
description: $item.find('.changelog').html(),
|
||||
link: address,
|
||||
guid: address,
|
||||
};
|
||||
})
|
||||
.get(),
|
||||
};
|
||||
};
|
||||
@@ -1,77 +0,0 @@
|
||||
const cheerio = require('cheerio');
|
||||
const parser = require('@/utils/rss-parser');
|
||||
const got = require('@/utils/got');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const category = ctx.params.category;
|
||||
const subcategory = ctx.params.subcategory;
|
||||
const rssUrl = subcategory
|
||||
? `https://www.chicagotribune.com/arcio/rss/category/${category}/${subcategory}/?query=display_date:%5Bnow-2d+TO+now%5D+AND+revision.published:true&sort=display_date:desc#nt=instory-link`
|
||||
: `https://www.chicagotribune.com/arcio/rss/category/${category}/?query=display_date:%5Bnow-2d+TO+now%5D+AND+revision.published:true&sort=display_date:desc#nt=instory-link`;
|
||||
const feed = await parser.parseURL(rssUrl);
|
||||
|
||||
const items = await Promise.all(
|
||||
feed.items.map((item) =>
|
||||
ctx.cache.tryGet(item.link, async () => {
|
||||
const response = await got({
|
||||
url: item.link,
|
||||
method: 'get',
|
||||
});
|
||||
const html = response.body;
|
||||
const $ = cheerio.load(html);
|
||||
const content = $('article > main > section#left');
|
||||
|
||||
const categories = $('meta[property="article:section"]')
|
||||
.attr('content')
|
||||
.split(',')
|
||||
.map((e) => e.trim())
|
||||
.filter((e) => e !== '');
|
||||
|
||||
// Disable image lazyloading
|
||||
content.find('img').each((i, e) => {
|
||||
e = $(e);
|
||||
e.attr('src', e.attr('data-src'));
|
||||
});
|
||||
|
||||
// Remove unwanted DOMs
|
||||
const unwanted_element_selectors = [
|
||||
'[data-pb-name="Recommender"]',
|
||||
'.inline-ad',
|
||||
'[data-type="newsletter-promo-card"]',
|
||||
'[data-type="interstitial_link"]',
|
||||
'[data-type="recommender"]',
|
||||
'.recommender',
|
||||
'[class*="pb-f-ads-"]',
|
||||
];
|
||||
for (const selector of unwanted_element_selectors) {
|
||||
content.find(selector).each((i, e) => {
|
||||
$(e).remove();
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
title: item.title.trim(),
|
||||
id: item.guid,
|
||||
pubDate: new Date(item.pubDate).toUTCString(),
|
||||
author: item.creator.trim(),
|
||||
link: item.link,
|
||||
summary: item.content.trim(),
|
||||
description: content.html(),
|
||||
category: categories,
|
||||
icon: 'https://www.chicagotribune.com/pb/resources/images/ct_icons/144-iTunesArtwork.png',
|
||||
logo: 'https://upload.wikimedia.org/wikipedia/commons/c/c4/Chicago_Tribune_Logo.svg',
|
||||
};
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: feed.title,
|
||||
link: feed.link,
|
||||
description: feed.description,
|
||||
item: items,
|
||||
language: 'en-us',
|
||||
icon: 'https://www.chicagotribune.com/pb/resources/images/ct_icons/144-iTunesArtwork.png',
|
||||
logo: 'https://upload.wikimedia.org/wikipedia/commons/c/c4/Chicago_Tribune_Logo.svg',
|
||||
};
|
||||
};
|
||||
@@ -1,33 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const { category } = ctx.params;
|
||||
const baseUrl = 'https://language.chinadaily.com.cn';
|
||||
const url = `${baseUrl}/${category}`;
|
||||
const response = await got(url);
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const categoryName = $('.CT_title').first().text();
|
||||
const items = $('.gy_box')
|
||||
.map((_, ele) => {
|
||||
const $item = cheerio.load(ele);
|
||||
const link = $item('.gy_box_img').attr('href');
|
||||
const imgUrl = $item('.gy_box_img img').attr('src');
|
||||
const realImgUrl = imgUrl.includes('http') ? imgUrl : `https:${imgUrl}`;
|
||||
const title = $item('.gy_box_txt2').text();
|
||||
const desc = $item('.gy_box_txt3').text();
|
||||
return {
|
||||
title,
|
||||
link: link.trim().replace(/^\/\//, 'https://'),
|
||||
description: [`<img src="${realImgUrl}"/>`, desc].join('<br/>'),
|
||||
};
|
||||
})
|
||||
.get();
|
||||
ctx.state.data = {
|
||||
title: `中国日报 - ${categoryName}`,
|
||||
description: `中国日报 - ${categoryName}`,
|
||||
link: url,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,71 +0,0 @@
|
||||
const Parser = require('rss-parser');
|
||||
const cheerio = require('cheerio');
|
||||
const got = require('@/utils/got');
|
||||
const dayjs = require('dayjs');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const category = ctx.params.category || 'all';
|
||||
const rssUrl = `https://feeds.feedburner.com/chinafile/${category}`;
|
||||
|
||||
// The custom UA in @/utils/parser (mimic browser) results in a HTML page
|
||||
// which cannot be parsed
|
||||
const parser = new Parser();
|
||||
const feed = await parser.parseURL(rssUrl);
|
||||
|
||||
const items = await Promise.all(
|
||||
feed.items.map((item) =>
|
||||
ctx.cache.tryGet(item.link, async () => {
|
||||
let url = item.link;
|
||||
const response = await got({ url });
|
||||
const html = response.body;
|
||||
const $ = cheerio.load(html);
|
||||
const content = $('article');
|
||||
|
||||
// Cover
|
||||
const cover = $('.view-featured-photo');
|
||||
|
||||
if (cover.length > 0) {
|
||||
cover.insertBefore(content[0].childNodes[0]);
|
||||
$(cover).remove();
|
||||
}
|
||||
|
||||
// Summary
|
||||
const summary = $('meta[name="description"]').attr('content');
|
||||
const updatedAt = $('meta[name="og:updated_time"]').attr('content');
|
||||
|
||||
const categories = $('meta[name="news_keywords"]')
|
||||
.attr('content')
|
||||
.split(',')
|
||||
.map((c) => c.trim());
|
||||
|
||||
url = $('link[rel="canonical"]').attr('href');
|
||||
|
||||
const pubDate = dayjs(item.pubDate.replace(' - ', ' ').replace('am', ' am').replace('pm', ' pm'));
|
||||
|
||||
return {
|
||||
title: item.title,
|
||||
id: item.guid,
|
||||
pubDate,
|
||||
updated: updatedAt,
|
||||
author: item.creator,
|
||||
link: url,
|
||||
summary,
|
||||
description: content.html(),
|
||||
category: categories,
|
||||
icon: 'https://www.chinafile.com/sites/default/files/chinafile_favicon.png',
|
||||
logo: 'https://www.chinafile.com/sites/all/themes/cftwo/assets/images/logos/logo-large.png',
|
||||
};
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: feed.title,
|
||||
link: feed.link,
|
||||
description: feed.description,
|
||||
item: items,
|
||||
language: 'en-us',
|
||||
icon: 'https://www.chinafile.com/sites/default/files/chinafile_favicon.png',
|
||||
logo: 'https://www.chinafile.com/sites/all/themes/cftwo/assets/images/logos/logo-large.png',
|
||||
};
|
||||
};
|
||||
@@ -1,55 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
async function get_software_raw_html(link) {
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: link,
|
||||
});
|
||||
return response.body;
|
||||
}
|
||||
|
||||
function pick_versions(raw_html) {
|
||||
const $ = cheerio.load(raw_html);
|
||||
const items = [];
|
||||
$('#versionhistory table tbody tr').each((_row_index, row) => {
|
||||
const software = {};
|
||||
$('td', row).each((col_index, col) => {
|
||||
if ($(col).hasClass('version')) {
|
||||
const href = $('a', col).attr('href');
|
||||
let version = '';
|
||||
if (href) {
|
||||
version = href.split('/').at(-1);
|
||||
}
|
||||
software.version = version;
|
||||
}
|
||||
if (col_index === 0) {
|
||||
software.software = $(col).text().trim();
|
||||
}
|
||||
if (col_index === 2) {
|
||||
software.time = $(col).text();
|
||||
}
|
||||
});
|
||||
items.push(software);
|
||||
});
|
||||
return items;
|
||||
}
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const software_name = ctx.params.name;
|
||||
|
||||
const software_link = `https://chocolatey.org/packages/${software_name}`;
|
||||
const raw = await get_software_raw_html(software_link);
|
||||
const items = pick_versions(raw);
|
||||
|
||||
const rsshub_object = {
|
||||
title: software_name,
|
||||
link: software_link,
|
||||
item: items.map((i) => {
|
||||
const link = `https://chocolatey.org/packages/${software_name}/${i.version}`;
|
||||
const ret = { title: i.software, link, description: `update_time: ${i.time}` };
|
||||
return ret;
|
||||
}),
|
||||
};
|
||||
ctx.state.data = rsshub_object;
|
||||
};
|
||||
@@ -1,35 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const subject = ctx.params.subject || 'hot';
|
||||
const host = 'https://m.chouti.com';
|
||||
let api = `${host}/api/m/zone/${subject}?afterTime=0`;
|
||||
let pageUrl = `https://m.chouti.com/zone/${subject}`;
|
||||
if (subject === 'hot') {
|
||||
api = `${host}/api/m/link/hot?afterTime=0`;
|
||||
pageUrl = `https://m.chouti.com/all/hot`;
|
||||
}
|
||||
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: api,
|
||||
headers: {
|
||||
Referer: host,
|
||||
},
|
||||
});
|
||||
|
||||
const resultItem = response.data.data.map((item) => ({
|
||||
title: item.title,
|
||||
author: item.nick,
|
||||
description: `${item.title}<br><img src="${item.originalImgUrl || item.imgUrl || item.original_img_url || item.img_url}" /><br><a href="${host}/link/${item.id}">评论</a>`,
|
||||
link: item.url,
|
||||
pubDate: new Date(item.created_time / 1000).toUTCString(),
|
||||
}));
|
||||
|
||||
ctx.state.data = {
|
||||
title: '抽屉新热榜',
|
||||
description: '抽屉新热榜,汇聚每日搞笑段子、热门图片、有趣新闻。它将微博、门户、社区、bbs、社交网站等海量内容聚合在一起,通过用户推荐生成最热榜单。看抽屉新热榜,每日热门、有趣资讯尽收眼底。',
|
||||
link: pageUrl,
|
||||
item: resultItem,
|
||||
};
|
||||
};
|
||||
@@ -1,28 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const hour = ctx.params.hour || '24';
|
||||
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: `https://dig.chouti.com/top/${hour}hr?_=${Date.now()}`,
|
||||
headers: {
|
||||
Referer: 'https://dig.chouti.com/',
|
||||
},
|
||||
});
|
||||
|
||||
const resultItem = response.data.data.map((item) => ({
|
||||
title: item.title,
|
||||
author: item.nick,
|
||||
description: `${item.title}<br><img src="${item.originalImgUrl || item.imgUrl || item.original_img_url || item.img_url}" /><br><a href="https://dig.chouti.com/link/${item.id}">评论</a>`,
|
||||
link: item.url,
|
||||
pubDate: new Date(item.created_time / 1000).toUTCString(),
|
||||
}));
|
||||
|
||||
ctx.state.data = {
|
||||
title: `抽屉新热榜-${hour}小时最热榜`,
|
||||
description: '抽屉新热榜,汇聚每日搞笑段子、热门图片、有趣新闻。它将微博、门户、社区、bbs、社交网站等海量内容聚合在一起,通过用户推荐生成最热榜单。看抽屉新热榜,每日热门、有趣资讯尽收眼底。',
|
||||
link: 'https://dig.chouti.com/',
|
||||
item: resultItem,
|
||||
};
|
||||
};
|
||||
@@ -1,51 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const category = ctx.params.category || 'dnzszc';
|
||||
|
||||
const rootUrl = 'https://gaokao.chsi.com.cn';
|
||||
const currentUrl = `${rootUrl}/gkxx/zszcgd/${category}`;
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: currentUrl,
|
||||
});
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const list = $('.list ul li a')
|
||||
.slice(0, 15)
|
||||
.map((_, item) => {
|
||||
item = $(item);
|
||||
const link = item.attr('href');
|
||||
|
||||
return {
|
||||
title: item.text(),
|
||||
pubDate: new Date(item.prev().text()).toUTCString(),
|
||||
link: link.includes('http') ? link : `${rootUrl}${link}`,
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
const items = await Promise.all(
|
||||
list.map((item) =>
|
||||
ctx.cache.tryGet(item.link, async () => {
|
||||
const detailResponse = await got({
|
||||
method: 'get',
|
||||
url: item.link,
|
||||
});
|
||||
const content = cheerio.load(detailResponse.data);
|
||||
|
||||
item.description = content('.list').html();
|
||||
|
||||
return item;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `${$('.backb').text()} - 教育部阳光高考信息公开平台`,
|
||||
link: currentUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,30 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const baseUrl = 'https://www.chuhaibiji.com/';
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: baseUrl,
|
||||
});
|
||||
const $ = cheerio.load(response.data); // 使用 cheerio 加载返回的 HTML
|
||||
const list = $('ul[class="post-loop post-loop-default tab-wrap clearfix active"] li[class="item"]');
|
||||
ctx.state.data = {
|
||||
title: `出海笔记 ~ 资讯`,
|
||||
link: `https://www.secshi.com/`,
|
||||
description: '出海笔记 ~ 资讯',
|
||||
item:
|
||||
list &&
|
||||
list
|
||||
.map((index, item) => {
|
||||
item = $(item);
|
||||
return {
|
||||
title: $('h2 a', item).text(),
|
||||
link: $('h2 a', item).attr('href'),
|
||||
description: $('p', item).text(),
|
||||
pubDate: new Date($('span[class="item-meta-li date"]', item).text()).toUTCString(),
|
||||
};
|
||||
})
|
||||
.get(),
|
||||
};
|
||||
};
|
||||
@@ -1,52 +0,0 @@
|
||||
const url = require('url');
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const { parseRelativeDate } = require('@/utils/parse-date');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
ctx.params.caty = ctx.params.caty || '';
|
||||
ctx.params.caty = ctx.params.caty === '' ? '' : `/navi/${ctx.params.caty}`;
|
||||
|
||||
const rootUrl = 'http://forum.softhead-citavi.com';
|
||||
const currentUrl = `${rootUrl}${ctx.params.caty}`;
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: currentUrl,
|
||||
});
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const list = $('h5.media-heading a')
|
||||
.slice(0, 10)
|
||||
.map((_, item) => {
|
||||
item = $(item);
|
||||
return {
|
||||
title: item.text(),
|
||||
link: url.resolve(currentUrl, item.attr('href')),
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
const items = await Promise.all(
|
||||
list.map((item) =>
|
||||
ctx.cache.tryGet(item.link, async () => {
|
||||
const detailResponse = await got({
|
||||
method: 'get',
|
||||
url: item.link,
|
||||
});
|
||||
const content = cheerio.load(detailResponse.data);
|
||||
|
||||
item.description = content('div.panel-body').html();
|
||||
item.pubDate = parseRelativeDate(content('small.gray').eq(0).text().split(' • ')[1]);
|
||||
|
||||
return item;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `${$('a.current').text()} - Citavi 中文网站论坛`,
|
||||
link: currentUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,48 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const lang = ctx.params.lang || '';
|
||||
|
||||
const rootUrl = 'https://clb.org.hk';
|
||||
const currentUrl = `${rootUrl}/${lang === '' ? '/zh-hans/section/%E8%AF%84%E8%AE%BA%E4%B8%8E%E7%89%B9%E5%86%99' : 'commentary-and-analysis'}`;
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: currentUrl,
|
||||
});
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const list = $('.field-content a')
|
||||
.slice(0, 10)
|
||||
.map((_, item) => {
|
||||
item = $(item);
|
||||
return {
|
||||
title: item.text(),
|
||||
link: `${rootUrl}${item.attr('href')}`,
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
const items = await Promise.all(
|
||||
list.map((item) =>
|
||||
ctx.cache.tryGet(item.link, async () => {
|
||||
const detailResponse = await got({
|
||||
method: 'get',
|
||||
url: item.link,
|
||||
});
|
||||
const content = cheerio.load(detailResponse.data);
|
||||
|
||||
item.description = content('.field-name-body').html();
|
||||
item.pubDate = new Date(content('meta[property="article:published_time"]').attr('content')).toUTCString();
|
||||
|
||||
return item;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: $('title').text(),
|
||||
link: currentUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,73 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const column = ctx.params.column; // szse 深圳证券交易所; sse 上海证券交易所; hke 港股; fund 基金
|
||||
const code = ctx.params.code; // 股票代码
|
||||
const orgId = ctx.params.orgId;
|
||||
const category = ctx.params.category || 'all'; // 分类
|
||||
const searchKey = ctx.params.search || ''; // 标题关键字
|
||||
let plate = '';
|
||||
|
||||
const url = `http://www.cninfo.com.cn/new/disclosure/stock?stockCode=${code}&orgId=${orgId}`;
|
||||
const apiUrl = `http://www.cninfo.com.cn/new/hisAnnouncement/query`;
|
||||
switch (column) {
|
||||
case 'szse':
|
||||
plate = 'sz';
|
||||
break;
|
||||
case 'sse':
|
||||
plate = 'sh';
|
||||
break;
|
||||
case 'third':
|
||||
plate = 'neeq';
|
||||
break;
|
||||
case 'hke':
|
||||
plate = 'hke';
|
||||
break;
|
||||
case 'fund':
|
||||
plate = 'fund';
|
||||
break;
|
||||
}
|
||||
const response = await got.post(apiUrl, {
|
||||
headers: {
|
||||
Referer: url,
|
||||
},
|
||||
form: {
|
||||
stock: `${code},${orgId}`,
|
||||
tabName: 'fulltext',
|
||||
pageSize: 30,
|
||||
pageNum: 1,
|
||||
column,
|
||||
category: category === 'all' ? '' : category,
|
||||
plate,
|
||||
seDate: '',
|
||||
searchkey: searchKey,
|
||||
secid: '',
|
||||
sortName: '',
|
||||
sortType: '',
|
||||
isHLtitle: true,
|
||||
},
|
||||
});
|
||||
const announcementsList = response.data.announcements;
|
||||
|
||||
let name = '';
|
||||
const out = announcementsList.map((item) => {
|
||||
const title = item.announcementTitle;
|
||||
const date = item.announcementTime;
|
||||
const announcementTime = new Date(item.announcementTime).toISOString().slice(0, 10);
|
||||
const link = 'http://www.cninfo.com.cn/new/disclosure/detail' + `?plate=${plate}` + `&orgId=${orgId}` + `&stockCode=${code}` + `&announcementId=${item.announcementId}` + `&announcementTime=${announcementTime}`;
|
||||
name = item.secName;
|
||||
|
||||
const single = {
|
||||
title,
|
||||
link,
|
||||
pubDate: new Date(date).toUTCString(),
|
||||
};
|
||||
|
||||
return single;
|
||||
});
|
||||
ctx.state.data = {
|
||||
title: `${name}公告-巨潮资讯`,
|
||||
link: url,
|
||||
item: out,
|
||||
};
|
||||
};
|
||||
@@ -1,59 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const utils = require('./utils');
|
||||
|
||||
const types = {
|
||||
hot: '热门',
|
||||
recommend: '推荐',
|
||||
recent: '最新',
|
||||
};
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const type = ctx.params.type ?? 'hot';
|
||||
const category = ctx.params.category ?? '0';
|
||||
const category_name = category === '0' ? '全部' : category;
|
||||
|
||||
const url = `http://www.cnu.cc/discoveryPage/${type}-${encodeURIComponent(category)}`;
|
||||
|
||||
const list_response = await got.get(url);
|
||||
const $ = cheerio.load(list_response.data);
|
||||
|
||||
const list = $('.grid-item.work-thumbnail').toArray();
|
||||
|
||||
const out = await Promise.all(
|
||||
list.map(async (item) => {
|
||||
const $ = cheerio.load(item);
|
||||
const title = $('.title');
|
||||
const link = $('a.thumbnail').attr('href');
|
||||
|
||||
const cache = await ctx.cache.get(link);
|
||||
if (cache) {
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const rssitem = {
|
||||
title: title.text().trim(),
|
||||
link,
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await got.get(link);
|
||||
const result = utils.parseContent(response.data);
|
||||
|
||||
rssitem.author = result.author;
|
||||
rssitem.description = result.description;
|
||||
rssitem.pubDate = result.pubDate;
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
ctx.cache.set(link, JSON.stringify(rssitem));
|
||||
return rssitem;
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `CNU视觉联盟 - ${types[type]} - ${category_name}`,
|
||||
link: url,
|
||||
item: out.filter((item) => item !== ''),
|
||||
};
|
||||
};
|
||||
@@ -1,52 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const utils = require('./utils');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const url = 'http://www.cnu.cc/selectedPage';
|
||||
|
||||
const list_response = await got.get(url);
|
||||
const $ = cheerio.load(list_response.data);
|
||||
|
||||
const list = $('.selectedUL > .bannerLi').toArray();
|
||||
|
||||
const out = await Promise.all(
|
||||
list.map(async (item) => {
|
||||
const $ = cheerio.load(item);
|
||||
const title = $('.workTitle');
|
||||
const link = title.parent().attr('href');
|
||||
|
||||
const cache = await ctx.cache.get(link);
|
||||
if (cache) {
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const rssitem = {
|
||||
title: title.text().trim(),
|
||||
link,
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await got.get(link);
|
||||
const result = utils.parseContent(response.data);
|
||||
if (!result.description) {
|
||||
return '';
|
||||
}
|
||||
|
||||
rssitem.author = result.author;
|
||||
rssitem.description = result.description;
|
||||
rssitem.pubDate = result.pubDate;
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
ctx.cache.set(link, JSON.stringify(rssitem));
|
||||
return rssitem;
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `CNU视觉联盟 - 每日精选`,
|
||||
link: url,
|
||||
item: out.filter((item) => item !== ''),
|
||||
};
|
||||
};
|
||||
@@ -1,28 +0,0 @@
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
const pic_base_url = 'http://imgoss.cnu.cc/';
|
||||
|
||||
const parseContent = (htmlString) => {
|
||||
const $ = cheerio.load(htmlString);
|
||||
|
||||
const author = $('.author-info > a');
|
||||
const time = $('.author-info > .timeago');
|
||||
const content = $('#work_body');
|
||||
|
||||
const imgs_json = JSON.parse($('#imgs_json').text());
|
||||
for (const element of imgs_json) {
|
||||
content.append(`<img src="${pic_base_url}${element.img}" />`);
|
||||
content.append(`<div class='img_description'>${element.content}</div>`);
|
||||
content.append(`<p>${element.text}</p>`);
|
||||
}
|
||||
|
||||
return {
|
||||
author: author.text().trim(),
|
||||
description: content.html(),
|
||||
pubDate: new Date(time.text().trim()),
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
parseContent,
|
||||
};
|
||||
@@ -1,26 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: 'https://coolbuy.com/api/v1.4/product_preview/?order_by=-id&limit=20&page=0&offset=0',
|
||||
});
|
||||
|
||||
const data = response.data.objects;
|
||||
|
||||
ctx.state.data = {
|
||||
title: '玩物志-最新',
|
||||
link: 'https://coolbuy.com/',
|
||||
description: '值得买的未来生活',
|
||||
item: data.map((item) => ({
|
||||
title: item.title,
|
||||
link: item.visit_url,
|
||||
description: `
|
||||
<img src="${item.cover_image}"><br>
|
||||
<img src="${item.display_image}"><br><br>
|
||||
${item.summary}<br>
|
||||
价格: ${item.price}元
|
||||
`,
|
||||
})),
|
||||
};
|
||||
};
|
||||
@@ -1,30 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const id = ctx.params.id;
|
||||
|
||||
const url = `https://cowlevel.net/element/${id}/article`;
|
||||
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: `https://cowlevel.net/search/article-search?tag_id=${id}&game_url_slug=&per_page=10&page=1&q=&sort=&sort_type=desc&is_rich_content=1&url_slug=`,
|
||||
headers: {
|
||||
Referer: url,
|
||||
},
|
||||
});
|
||||
|
||||
const element_name = response.data.data.aggs.tags[0].tag.name;
|
||||
const list = response.data.data.list;
|
||||
|
||||
ctx.state.data = {
|
||||
title: `奶牛关 - ${element_name}`,
|
||||
link: url,
|
||||
item: list.map((item) => ({
|
||||
title: item.title,
|
||||
author: item.user.name,
|
||||
description: item.content,
|
||||
pubDate: new Date(item.update_time * 1000),
|
||||
link: `https://cowlevel.net/article/${item.id}`,
|
||||
})),
|
||||
};
|
||||
};
|
||||
@@ -1,30 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const dayjs = require('dayjs');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const includePreRelease = ctx.params.pre;
|
||||
const response = await got(`https://www.python.org/downloads`);
|
||||
const $ = cheerio.load(response.data);
|
||||
const items = [];
|
||||
$('.list-row-container.menu li').each(function () {
|
||||
const $listElement = $(this);
|
||||
const title = $listElement.find('span.release-number').text();
|
||||
if (title) {
|
||||
if (!includePreRelease && title.includes('rc')) {
|
||||
return;
|
||||
}
|
||||
items.push({
|
||||
title: $listElement.find('span.release-number').text(),
|
||||
description: title,
|
||||
link: $listElement.find('.release-enhancements a').attr('href'),
|
||||
pubDate: dayjs($listElement.find('.release-date').text()),
|
||||
});
|
||||
}
|
||||
});
|
||||
ctx.state.data = {
|
||||
title: 'cpython',
|
||||
link: 'https://www.python.org/',
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,45 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const iconv = require('iconv-lite');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const currentUrl = 'http://news.creaders.net/headline/';
|
||||
|
||||
const response = await got.get(currentUrl, {
|
||||
responseType: 'buffer',
|
||||
});
|
||||
|
||||
const $ = cheerio.load(iconv.decode(response.data, 'gbk'));
|
||||
const list = $('ul.newslist li')
|
||||
.slice(0, 10)
|
||||
.map((_, item) => {
|
||||
item = $(item);
|
||||
const a = item.find('a').eq(1);
|
||||
return {
|
||||
title: a.text(),
|
||||
link: a.attr('href'),
|
||||
pubDate: new Date(item.find('time').text() + ' GMT+8').toUTCString(),
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
const items = await Promise.all(
|
||||
list.map((item) =>
|
||||
ctx.cache.tryGet(item.link, async () => {
|
||||
const res = await got.get(item.link, {
|
||||
responseType: 'buffer',
|
||||
});
|
||||
const content = cheerio.load(iconv.decode(res.data, 'gbk'));
|
||||
|
||||
item.description = content('#newsContent').html();
|
||||
return item;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: '万维读者 - 焦点新闻',
|
||||
link: currentUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,99 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const url = require('url');
|
||||
const iconv = require('iconv-lite');
|
||||
|
||||
const baseUrl = 'https://www.csc.edu.cn';
|
||||
|
||||
const typeMap = {
|
||||
lxtz: {
|
||||
name: '遴选通知',
|
||||
url: '/chuguo/list/24',
|
||||
},
|
||||
xmzl: {
|
||||
name: '综合项目专栏',
|
||||
url: '/chuguo/list/26',
|
||||
},
|
||||
wtjd: {
|
||||
name: '常见问题解答',
|
||||
url: '/chuguo/list/27',
|
||||
},
|
||||
lqgg: {
|
||||
name: '录取公告',
|
||||
url: '/chuguo/list/28',
|
||||
},
|
||||
xwzx: {
|
||||
name: '新闻资讯',
|
||||
url: '/news',
|
||||
},
|
||||
xwgg: {
|
||||
name: '新闻公告',
|
||||
url: '/news/gonggao',
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const type = ctx.params.type || 'jjyw';
|
||||
const link = baseUrl + typeMap[type].url;
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: link,
|
||||
headers: {
|
||||
Referer: baseUrl,
|
||||
},
|
||||
responseType: 'buffer',
|
||||
});
|
||||
const responseHtml = iconv.decode(response.data, 'gbk');
|
||||
const $ = cheerio.load(responseHtml);
|
||||
|
||||
const urlList = $('.list-a li')
|
||||
.slice(0, 10)
|
||||
.map((i, e) => $('a', e).attr('href'))
|
||||
.get();
|
||||
|
||||
const titleList = $('.list-a li')
|
||||
.slice(0, 10)
|
||||
.map((i, e) => $('a', e).attr('title'))
|
||||
.get();
|
||||
|
||||
const dateList = $('.list-a li')
|
||||
.slice(0, 10)
|
||||
.map((i, e) => $('span', e).text())
|
||||
.get();
|
||||
|
||||
const out = await Promise.all(
|
||||
urlList.map(async (itemUrl, index) => {
|
||||
itemUrl = url.resolve(baseUrl, itemUrl);
|
||||
|
||||
const cache = await ctx.cache.get(itemUrl);
|
||||
if (cache) {
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: itemUrl,
|
||||
responseType: 'buffer',
|
||||
});
|
||||
const responseHtmlItem = iconv.decode(response.data, 'gbk');
|
||||
const $ = cheerio.load(responseHtmlItem);
|
||||
const single = {
|
||||
title: titleList[index],
|
||||
link: itemUrl,
|
||||
description: $('.contents')
|
||||
.html()
|
||||
.replaceAll('src="/', `src="${url.resolve(baseUrl, '.')}`)
|
||||
.replaceAll('href="/', `href="${url.resolve(baseUrl, '.')}`)
|
||||
.trim(),
|
||||
pubDate: dateList[index],
|
||||
};
|
||||
ctx.cache.set(itemUrl, JSON.stringify(single));
|
||||
return single;
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: '国家留学网-' + typeMap[type].name,
|
||||
link,
|
||||
item: out,
|
||||
};
|
||||
};
|
||||
@@ -1,50 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const id = ctx.params.id || 'bwzq';
|
||||
|
||||
const rootUrl = 'http://news.ctei.cn';
|
||||
const currentUrl = `${rootUrl}/${id}`;
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: currentUrl,
|
||||
});
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const list = $('.news_text ul li a')
|
||||
.map((_, item) => {
|
||||
item = $(item);
|
||||
|
||||
return {
|
||||
title: item.text(),
|
||||
link: `${currentUrl}${item.attr('href').replace(/\./, '')}`,
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
const items = await Promise.all(
|
||||
list.map((item) =>
|
||||
ctx.cache.tryGet(item.link, async () => {
|
||||
const detailResponse = await got({
|
||||
method: 'get',
|
||||
url: item.link,
|
||||
});
|
||||
const content = cheerio.load(detailResponse.data);
|
||||
|
||||
item.description = content('.TRS_Editor').html();
|
||||
item.pubDate = parseDate(item.link.match(/\/t(\d{8})_\d+.htm/)[1], 'YYYYMMDD');
|
||||
|
||||
return item;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: $('title').text(),
|
||||
link: currentUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,59 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const host = 'https://api.ctfhub.com';
|
||||
const opt = { like: {} };
|
||||
for (const i of ['title', 'form', 'class']) {
|
||||
if (ctx.params[i] !== undefined) {
|
||||
opt.like[i] = ctx.params[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (opt.like.class !== undefined) {
|
||||
const types = await got
|
||||
.post(`${host}/User_API/Event/getType`, {
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
body: '{}',
|
||||
})
|
||||
.json();
|
||||
opt.like.class = types.data[opt.like.class];
|
||||
}
|
||||
if (opt.like.form !== undefined) {
|
||||
opt.like.form = ['线上', '线下'][Number.parseInt(opt.like.form)];
|
||||
}
|
||||
|
||||
if (Object.keys(opt.like).length === 0) {
|
||||
delete opt.like;
|
||||
}
|
||||
|
||||
opt.offset = 0;
|
||||
opt.limit = Number.parseInt(ctx.params.limit) || 10;
|
||||
|
||||
const response = await got
|
||||
.post(`${host}/User_API/Event/getAll`, {
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(opt),
|
||||
})
|
||||
.json();
|
||||
|
||||
if (response.status !== true) {
|
||||
return;
|
||||
}
|
||||
const data = response.data;
|
||||
|
||||
ctx.state.data = {
|
||||
title: 'CTFHub Calendar',
|
||||
link: 'https://www.ctfhub.com/#/calendar',
|
||||
description: '提供全网最全最新的 CTF 赛事信息,关注赛事定制自己专属的比赛日历吧。',
|
||||
item: data.items.map((item) => ({
|
||||
title: item.title,
|
||||
description: '',
|
||||
pubDate: new Date(item.start_time * 1000).toUTCString(),
|
||||
link: item.official_url,
|
||||
})),
|
||||
};
|
||||
};
|
||||
@@ -1,58 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const md5 = require('@/utils/md5');
|
||||
|
||||
const host = 'https://api.ctfhub.com';
|
||||
|
||||
async function get_details(event_id) {
|
||||
const res = await got
|
||||
.post(`${host}/User_API/Event/getInfo`, {
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ event_id }),
|
||||
})
|
||||
.json();
|
||||
if (res.status !== true) {
|
||||
return '';
|
||||
}
|
||||
return res.data;
|
||||
}
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const opt = {
|
||||
offset: 0,
|
||||
limit: Number.parseInt(ctx.params.limit) || 5,
|
||||
};
|
||||
|
||||
const response = await got
|
||||
.post(`${host}/User_API/Event/getUpcoming`, {
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(opt),
|
||||
})
|
||||
.json();
|
||||
|
||||
if (response.status !== true) {
|
||||
return;
|
||||
}
|
||||
const items = await Promise.all(
|
||||
response.data.items.map(async (item) => {
|
||||
const det = await get_details(item.id);
|
||||
return {
|
||||
title: item.title,
|
||||
description: det.details,
|
||||
pubDate: new Date(item.start_time * 1000).toUTCString(),
|
||||
link: det.official_url,
|
||||
guid: md5(item.title + item.start_time),
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: 'CTFHub Calendar',
|
||||
link: 'https://www.ctfhub.com/#/calendar',
|
||||
description: '提供全网最全最新的 CTF 赛事信息,关注赛事定制自己专属的比赛日历吧。',
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,33 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const { body } = await got.post('https://panel.getdailyart.com/APIMobile/artworks/query', {
|
||||
headers: {
|
||||
Language: ctx.params.language || 'en',
|
||||
AuthSalt: 'ZG9jY29tcGFuaW9uc2FsdA==',
|
||||
},
|
||||
json: {
|
||||
take: 10,
|
||||
skip: 0,
|
||||
local_date: new Date().toISOString().split('T')[0],
|
||||
},
|
||||
responseType: 'json',
|
||||
});
|
||||
|
||||
const data = body.entities;
|
||||
|
||||
ctx.state.data = {
|
||||
title: `DailyArt`,
|
||||
link: 'https://www.getdailyart.com/',
|
||||
item: data.map((item) => ({
|
||||
title: item.title,
|
||||
description: `<img src='${item.photo_ipad}'><br>
|
||||
${item.info}<br>
|
||||
${item.size || ''}<br>
|
||||
${item.genre && item.genre.name ? item.genre.name : ''}<br>
|
||||
${item.museum && item.museum.name ? item.museum.name : ''}`,
|
||||
pubDate: new Date(item.publish_date).toUTCString(),
|
||||
link: item.photo_retina,
|
||||
})),
|
||||
};
|
||||
};
|
||||
@@ -1,51 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const caty = ctx.params.caty || 'all';
|
||||
|
||||
const rootUrl = 'https://daodu.tech';
|
||||
const currentUrl = `${rootUrl}${caty === 'all' ? '' : '/archive_' + caty}`;
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: currentUrl,
|
||||
});
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const list = $('h2[itemprop="headline"] a, .post-header .archive__article__title a')
|
||||
.slice(0, 15)
|
||||
.map((_, item) => {
|
||||
item = $(item);
|
||||
return {
|
||||
title: item.text(),
|
||||
link: item.attr('href'),
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
const items = await Promise.all(
|
||||
list.map((item) =>
|
||||
ctx.cache.tryGet(item.link, async () => {
|
||||
const detailResponse = await got({
|
||||
method: 'get',
|
||||
url: item.link,
|
||||
});
|
||||
const content = cheerio.load(detailResponse.data);
|
||||
|
||||
content('.member-only').remove();
|
||||
|
||||
item.description = content('.post-entry-text').html();
|
||||
item.pubDate = new Date(content('meta[property="article:published_time"]').attr('content')).toUTCString();
|
||||
|
||||
return item;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: $('title').text().replace('一覽表', ''),
|
||||
link: currentUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,45 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const parser = require('@/utils/rss-parser');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const feed = await parser.parseURL('http://www.daxiaamu.com/rss');
|
||||
|
||||
const ProcessFeed = async (link) => {
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: link,
|
||||
});
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
return $('.main-content').html();
|
||||
};
|
||||
|
||||
const items = await Promise.all(
|
||||
feed.items.map(async (item) => {
|
||||
const cache = await ctx.cache.get(item.link);
|
||||
if (cache) {
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const description = await ProcessFeed(item.link);
|
||||
|
||||
const single = {
|
||||
title: item.title,
|
||||
description,
|
||||
pubDate: item.pubDate,
|
||||
link: item.link,
|
||||
author: item.author,
|
||||
};
|
||||
ctx.cache.set(item.link, JSON.stringify(single));
|
||||
return single;
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: feed.title,
|
||||
link: feed.link,
|
||||
description: feed.description,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,35 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const timezone = require('@/utils/timezone');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const type = ctx.params.type || 'online';
|
||||
|
||||
const rootUrl = 'https://dbaplus.cn';
|
||||
const currentUrl = `${rootUrl}/activity-${type === 'online' ? '12' : '48'}-1.html`;
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: currentUrl,
|
||||
});
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const items = $('.media')
|
||||
.map((_, item) => {
|
||||
item = $(item);
|
||||
|
||||
return {
|
||||
title: item.find('.media-heading').text(),
|
||||
link: item.find('.pull-left').attr('href'),
|
||||
description: `<img src="${item.find('.media-object').attr('src')}">`,
|
||||
pubDate: timezone(new Date(item.find('.time').text().replace('时间:', '')), +8),
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
ctx.state.data = {
|
||||
title: $('title').text().split(':')[0],
|
||||
link: currentUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,50 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const tab = ctx.params.tab || 'All';
|
||||
|
||||
const rootUrl = 'https://dbaplus.cn';
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: rootUrl,
|
||||
});
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const list = $(`#tab${tab} li`)
|
||||
.slice(0, 15)
|
||||
.map((_, item) => {
|
||||
item = $(item);
|
||||
|
||||
return {
|
||||
link: item.find('a').eq(0).attr('href'),
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
const items = await Promise.all(
|
||||
list.map((item) =>
|
||||
ctx.cache.tryGet(item.link, async () => {
|
||||
const detailResponse = await got({
|
||||
method: 'get',
|
||||
url: item.link,
|
||||
});
|
||||
const content = cheerio.load(detailResponse.data);
|
||||
|
||||
item.title = content('h2.title').text();
|
||||
item.author = content('span.user').text();
|
||||
item.description = content('.new-detailed').html();
|
||||
item.pubDate = new Date(content('span.time').eq(0).text()).toUTCString();
|
||||
|
||||
return item;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `${response.data.match(`<a href="#tab${tab}" data-toggle="tab">(.*)</a>`)[1]} - dbaplus社群`,
|
||||
link: rootUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,66 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const url = require('url');
|
||||
|
||||
const domain = 'https://m.dcinside.com';
|
||||
|
||||
const headers = {
|
||||
Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
|
||||
'Accept-Encoding': 'gzip, deflate, br',
|
||||
'Accept-Language': 'ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7',
|
||||
'Cache-Control': 'max-age=0',
|
||||
Connection: 'keep-alive',
|
||||
Host: 'm.dcinside.com',
|
||||
'Sec-Fetch-Dest': 'document',
|
||||
'Sec-Fetch-Mode': 'navigate',
|
||||
'Sec-Fetch-Site': 'none',
|
||||
'Sec-Fetch-User': '?1',
|
||||
'Upgrade-Insecure-Requests': '1',
|
||||
'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Mobile Safari/537.36',
|
||||
};
|
||||
|
||||
async function getData(ctx, link) {
|
||||
const { body } = await got.get(link, { headers });
|
||||
const $ = cheerio.load(body);
|
||||
const { path } = url.parse(link);
|
||||
const key = `dcinside${path}`;
|
||||
|
||||
let result = await ctx.cache.get(key);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = {
|
||||
title: $('head title').text().trim(),
|
||||
pubDate: new Date($('body > div.container > div > div > section > div.gallview-tit-box > div > ul > li:nth-child(2)').text()),
|
||||
link,
|
||||
description: $('body > div.container > div > div > section > div.gall-thum-btm > div > div.thum-txt').html(),
|
||||
};
|
||||
|
||||
ctx.cache.set(key, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
function getItems(ctx, $) {
|
||||
return Promise.all(
|
||||
$('body > div > div > div > section > ul.gall-detail-lst > li:not([class]) > div > a.lt')
|
||||
.toArray()
|
||||
.map((row) => getData(ctx, row.attribs.href))
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const { id } = ctx.params;
|
||||
const link = `${domain}/board/${id}`;
|
||||
|
||||
const { body } = await got.get(link, { headers });
|
||||
const $ = cheerio.load(body);
|
||||
const rss = {
|
||||
title: $('head title').text(),
|
||||
description: $('head title').text(),
|
||||
link,
|
||||
item: await getItems(ctx, $),
|
||||
};
|
||||
rss.item = rss.item.sort((a, b) => b.pubDate - a.pubDate);
|
||||
ctx.state.data = rss;
|
||||
};
|
||||
@@ -1,32 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const name = ctx.params.name;
|
||||
const season = ctx.params.season;
|
||||
|
||||
let link = `https://ddys.pro/${name}/`;
|
||||
|
||||
if (season) {
|
||||
link += `${season}/`;
|
||||
}
|
||||
|
||||
const response = await got(link);
|
||||
const $ = cheerio.load(response.body);
|
||||
|
||||
const title = $('title').html();
|
||||
const description = $('.abstract').html();
|
||||
const tracks = JSON.parse($('.wp-playlist-script').html()).tracks.reverse();
|
||||
const total = tracks.length;
|
||||
|
||||
ctx.state.data = {
|
||||
title,
|
||||
link,
|
||||
description,
|
||||
item: tracks.map(({ caption, description }, index) => ({
|
||||
title: caption,
|
||||
link: `${link}?ep=${total - index}`,
|
||||
description,
|
||||
})),
|
||||
};
|
||||
};
|
||||
@@ -1,37 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const md5 = require('@/utils/md5');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const url = ctx.params.tag ? `https://ddys.pro/tag/${encodeURIComponent(ctx.params.tag)}/` : ctx.params.category ? `https://ddrk.me/category/${ctx.params.category}/` : 'https://ddys.pro/';
|
||||
|
||||
const response = await got(url);
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const title = $('title').html();
|
||||
const list = $('.post-box-list .post-box-container').toArray();
|
||||
|
||||
ctx.state.data = {
|
||||
title,
|
||||
link: url,
|
||||
item: list.map((single, index) => {
|
||||
const item = $(single);
|
||||
const name = item.find('.post-box-title').text();
|
||||
const poster = item
|
||||
.find('.post-box-image')
|
||||
.attr('style')
|
||||
.match(/url\((.*?)\)/)[1];
|
||||
const text = item.find('.post-box-text p').html();
|
||||
const time = new Date();
|
||||
time.setMinutes(time.getMinutes() - index);
|
||||
return {
|
||||
title: name,
|
||||
author: '低端影视',
|
||||
description: `<img src="${poster}" style="max-width: 100%;" >${text ?? ''}`,
|
||||
link: item.find('.post-box-title a').attr('href'),
|
||||
pubDate: time,
|
||||
guid: md5(name),
|
||||
};
|
||||
}),
|
||||
};
|
||||
};
|
||||
@@ -1,34 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const lang = ctx.params.lang || 'en';
|
||||
|
||||
const rootUrl = 'https://www.deepl.com';
|
||||
const currentUrl = `${rootUrl}/zh/blog`;
|
||||
const blogUrl = `${rootUrl}/gatsby/locales/${lang}/blog.json`;
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: blogUrl,
|
||||
});
|
||||
|
||||
const items = [];
|
||||
const data = response.data;
|
||||
for (const key in data) {
|
||||
const matches = key.match(/post_content_(\d{8})/);
|
||||
if (matches) {
|
||||
const date = matches[1];
|
||||
items.push({
|
||||
description: data[key],
|
||||
link: `${currentUrl}/${date}`,
|
||||
title: data['post_title_' + date],
|
||||
pubDate: new Date(`${date.slice(0, 4)}-${date.slice(4, 6)}-${date.slice(6, 8)}`).toUTCString(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ctx.state.data = {
|
||||
title: response.data.title,
|
||||
link: currentUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,44 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const url = require('url');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const type = ctx.params.type;
|
||||
|
||||
const host = 'https://www.dekudeals.com/';
|
||||
const link = url.resolve(host, type);
|
||||
|
||||
const response = await got.get(link);
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const title = $('#search-title').text();
|
||||
const list = $('.search-main > .item-grid2 > div.cell');
|
||||
|
||||
const out = await Promise.all(
|
||||
list
|
||||
.map((index, item) => {
|
||||
item = $(item);
|
||||
const title = item.find('.name').text();
|
||||
const link = url.resolve(host, item.find('.main-link').attr('href'));
|
||||
const img = item.find('.main-link img').attr('src');
|
||||
const price = item.find('strong').html();
|
||||
const oldprice = item.find('s.text-muted').html();
|
||||
const description = `<img src="${img}"><br><s>${oldprice}</s><br>${price}`;
|
||||
|
||||
const single = {
|
||||
title,
|
||||
link,
|
||||
description,
|
||||
};
|
||||
|
||||
return Promise.resolve(single);
|
||||
})
|
||||
.get()
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `${title}—dekudeals`,
|
||||
link,
|
||||
item: out,
|
||||
};
|
||||
};
|
||||
@@ -1,62 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const category = ctx.params.category || 'energy-resources-industrials';
|
||||
const options = {
|
||||
consumer: {
|
||||
icid: 'top_consumer',
|
||||
label: '消费行业',
|
||||
},
|
||||
'energy-resources-industrials': {
|
||||
icid: 'top_energy-resources-industrials',
|
||||
label: '能源、资源及工业行业',
|
||||
},
|
||||
'financial-services': {
|
||||
icid: 'top_financial-services',
|
||||
label: '金融服务行业',
|
||||
},
|
||||
'government-public-services': {
|
||||
icid: 'top_government-public-services',
|
||||
label: '政府及公共服务',
|
||||
},
|
||||
'life-sciences-healthcare': {
|
||||
icid: 'top_life-sciences-healthcare',
|
||||
label: '生命科学与医疗行业',
|
||||
},
|
||||
'technology-media-telecommunications': {
|
||||
icid: 'top_technology-media-telecommunications',
|
||||
label: '科技、传媒及电信行业',
|
||||
},
|
||||
};
|
||||
const response = await got({
|
||||
url: 'https://www2.deloitte.com/cn/zh/industries/energy-resources-industrials.html',
|
||||
searchParams: {
|
||||
icid: options[category].icid,
|
||||
},
|
||||
});
|
||||
const $ = cheerio.load(response.data);
|
||||
const articles = $('.featuredpromo a.promo-focus')
|
||||
.map((index, ele) => ({
|
||||
title: $(ele).text().trim(),
|
||||
link: $(ele).attr('href'),
|
||||
}))
|
||||
.get();
|
||||
|
||||
const item = await Promise.all(
|
||||
articles.slice(0, 10).map((item) =>
|
||||
ctx.cache.tryGet(item.link, async () => {
|
||||
const detailResponse = await got.get(`https://www2.deloitte.com/${item.link}`);
|
||||
const s = cheerio.load(detailResponse.data);
|
||||
item.description = s('.two-columns-c0').html();
|
||||
return item;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `Deloitte - ${options[category].label}`,
|
||||
link: `https://www2.deloitte.com/cn/zh/industries/energy-resources-industrials.html?icid=top_energy-resources-`,
|
||||
item,
|
||||
};
|
||||
};
|
||||
@@ -1,57 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: 'https://opser.api.dgtle.com/v1/app/index?page=1',
|
||||
});
|
||||
|
||||
const article_items = response.data.items.filter((item) => item.type in { 1: '', 4: '' });
|
||||
|
||||
const items = await Promise.all(
|
||||
article_items.map(async (item) => {
|
||||
let title = '';
|
||||
let olink = ''; // 原始链接
|
||||
let dlink = ''; // description 链接
|
||||
let category = '';
|
||||
let description = '';
|
||||
|
||||
if (1 === item.type) {
|
||||
title = item.title;
|
||||
dlink = `https://opser.api.dgtle.com/v1/article/view/${item.aid}`;
|
||||
olink = `https://www.dgtle.com/article-${item.aid}-1.html`;
|
||||
category = '文章';
|
||||
description = await ctx.cache.tryGet(dlink, async () => {
|
||||
const resp = await got.get(dlink);
|
||||
return resp.data.content;
|
||||
});
|
||||
} else if (4 === item.type) {
|
||||
title = item.summary;
|
||||
dlink = `https://opser.api.dgtle.com/v1/feeds/inst/${item.aid}`;
|
||||
olink = `https://www.dgtle.com/inst-${item.aid}-1.html`;
|
||||
category = '兴趣动态';
|
||||
description = await ctx.cache.tryGet(dlink, async () => {
|
||||
const resp = await got.get(dlink);
|
||||
|
||||
return resp.data.imgs_url.reduce((content, dimg) => (content += `<img src=${dimg.path.split('?')[0]} />`), resp.data.content);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
title,
|
||||
description,
|
||||
pubDate: new Date(item.send_at * 1000).toUTCString(),
|
||||
link: olink,
|
||||
category,
|
||||
author: item.author.username,
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: '数字尾巴 - 首页',
|
||||
link: 'https://www.dgtle.com',
|
||||
description: '数字尾巴首页内容',
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,30 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const sanitizeHtml = require('sanitize-html');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const keyword = ctx.params.keyword;
|
||||
|
||||
const url = `https://www.dgtle.com/search?search_word=${encodeURIComponent(keyword)}`;
|
||||
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: `https://www.dgtle.com/search/sale?search_word=${encodeURIComponent(keyword)}&page=1`,
|
||||
headers: {
|
||||
Referer: url,
|
||||
},
|
||||
});
|
||||
|
||||
const list = response.data.data.dataList;
|
||||
|
||||
ctx.state.data = {
|
||||
title: `数字尾巴 - 闲置 - ${keyword}`,
|
||||
link: url,
|
||||
item: list.map((item) => ({
|
||||
title: sanitizeHtml(item.title, { allowedTags: [], allowedAttributes: {} }),
|
||||
author: item.author.username,
|
||||
description: `<p>价格: ¥${item.price}</p><p>地址: ${item.address}</p><p>${item.content}</p><img src="${item.cover}" style="max-width: 100%;"/>`,
|
||||
pubDate: new Date(item.created_at * 1000),
|
||||
link: `https://www.dgtle.com/sale-${item.id}-1.html`,
|
||||
})),
|
||||
};
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user